처음부터 차근차근

안드로이드 그래픽 본문

프로그래밍/Android

안드로이드 그래픽

_soyoung 2022. 5. 30. 14:44
반응형

안드로이드에서의 그래픽

안드로이드는 XML 파일로 그래픽이나 애니메이션을 정의한다.

그리는 작업은 안드로이드 시스템이 담당한다.

onDraw() 메소드 안에 draw...()와 같은 메소드를 호출하여 직접 그린다.

 

 

전체적인 구조

public class MyView extends View {
    ...
    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        // 여기에 그림그리는 코드
    }
    ...
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // MyView를 생성하고 이것을 Activity의 컨텐트 뷰로 설정
        MyView myView = new MyView(this);
        setContentView(myView);
    }
}

 

 

Canvas 클래스와 Paint 클래스

  • Canvas 클래스 : 그림을 그리는 캔버스(화포)에 해당
  • Paint 클래스 : 색상이나 선의 스타일, 채우기 스타일, 폰트, 앤티앨리어싱 여부 등과 같은 그리기 속성을 가지고 있는 클래스

 

예제

MyView class MainActivity 위치에다가 새로 생성

public class MyView extends View {

    public MyView(Context context) {
        super(context);
        setBackgroundColor(Color.BLUE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.YELLOW);
        paint.setStrokeWidth(20);
        paint.setTextSize(50);

        canvas.drawLine(100, 100, 300, 100, paint);
        canvas.drawRect(100, 200, 300, 300, paint);
        canvas.drawCircle(300, 500, 100, paint);
        canvas.drawText("This is a test", 100, 350, paint);
    }
}

paint 주요 메서드
Canvas 주요 메서드

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        MyView myView = new MyView(this);
        setContentView(myView);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

</LinearLayout>

 

 

 

예제2

위의 코드에서 MyView만 변경

public class MyView extends View {

    public MyView(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.YELLOW);
        paint.setStrokeWidth(20);
        paint.setTextSize(50);

        //canvas.drawRoundRect(new RectF(30, 50, 600, 600), 45, 45, paint);
        //canvas.drawOval(new RectF(30, 50, 400, 600), paint);
        //canvas.drawArc(new RectF(30, 50, 400, 600), 0, 90, true, paint);
        float[] pts = {30, 120, 120, 220, 120, 220, 180, 50, 180, 50, 400, 400};
        canvas.drawLines(pts, paint);
    }
}

 

 

커스텀 뷰를 XML에서 참조하기

위의 예제에서 MyView class와 activity_main 수정

public class MyView extends View {

    public MyView(Context context) {
        super(context);
        setBackgroundColor(Color.YELLOW);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStrokeWidth(20);

        canvas.drawArc(new RectF(30, 50, 600, 600), 120, 270, true, paint);
    }
}

drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

RectF(float left, float top, float right, float bottom)

 

지정된 타원 내부에 맞게 크기가 조정되는 지정된 호를 그리는 함수

 

RectF : rect 사각형 안에 원을 그린다.

startAngle : 시작 각도입니다

sweepAngle : 몇 도 그릴지 정합니다(시계반향)

useCenter : 맨 위 결과화면을 보면 됩니다(false : 호, true : 부채꼴모양)

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.induk.graphic.MyView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

 

 

컨텍스트 도형 이용해서 도형그리기

drawable 아래에서 New -> Drawable Resource file 클릭 한후 이미지와 같이 새로 생성

 

border.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" android:thickness="0sp">
    <size android:width="30sp" />
    <solid android:color="#0000ff" />

</shape>

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="5sp"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textColor="#0000FF"
            android:text="컨텍스트 메뉴를 이용하여 도형그리기" />

        <EditText
            android:id="@+id/edtCount"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:inputType="number"
            android:textColor="#ffffff"
            android:gravity="center"
            android:background="@drawable/border"
            android:layout_marginLeft="10sp"
            android:layout_marginRight="10sp"
            android:text="1"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="개" />

    </LinearLayout>

    <com.induk.graphic.MyView
        android:id="@+id/vCanvas"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5sp"/>

</LinearLayout>
public class MyView extends View {

    private int count;
    private int what;

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setBackgroundColor(Color.YELLOW);
        setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
            @Override
            public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
                contextMenu.setHeaderTitle("도형선택");
                contextMenu.add(0, 1, 0, "선");
                contextMenu.add(0, 2, 0, "면");
                contextMenu.add(0, 3, 0, "원");
                contextMenu.add(0, 4, 0, "타원");
                contextMenu.add(0, 5, 0, "부채꼴");
                contextMenu.add(0, 6, 0, "텍스트");
            }
        });
    }

    public void setting(int w, int c) {
        what = w;
        count = c;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        Paint paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setTextSize(100);
        paint.setStrokeWidth(20);
        switch (what) {
            case 1:
                for (int ii=0; ii < count; ii++) {
                    canvas.drawLine(100, 100 + (50 * ii), 600, 100 + (50 * ii), paint);
                }
                break;
            case 2:
                canvas.drawRect(100, 200, 300, 300, paint);
                break;
            case 3:
                for (int ii=0; ii < count; ii++) {
                    canvas.drawCircle(300 + (150 * ii), 500, 100, paint);
                }
                break;
            case 4:
                canvas.drawOval(new RectF(30, 50, 400, 600), paint);
                break;
            case 5:
                canvas.drawArc(new RectF(30, 50, 400, 600), 0, 90, true, paint);
                break;
            case 6:
                canvas.drawText("This is a test", 100, 350, paint);
                break;
            default:
                break;
        }
    }
}
public class MainActivity extends AppCompatActivity {

    private MyView myView;
    private EditText edtCount;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        edtCount = (EditText) findViewById(R.id.edtCount);
        myView = (MyView) findViewById(R.id.vCanvas);
    }

    @Override
    public boolean onContextItemSelected(@NonNull MenuItem item) {
//        int count;
//        if (edtCount.getText().toString().equals("")) {
//            count = 0;
//            Toast myToast = Toast.makeText(this.getApplicationContext(),"숫자를 입력해주세요!", Toast.LENGTH_SHORT);
//            myToast.show();
//        }
//        else {
//            count = Integer.parseInt(edtCount.getText().toString());
//        }
        switch (item.getItemId()) {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
                myView.setting(item.getItemId(), count);
                myView.invalidate(); // 중요!!!이 코드 없으면 감점, 메뉴가 바뀔 때마다 다시 그리게 하는 코드
                return true;
            default:
                return super.onContextItemSelected(item);
        }
    }

}

 

 

 

 

 

출처 : 안드로이드프로그래밍(22-1학기)김용남교수 강의 내용 변형 및 요약

반응형

'프로그래밍 > Android' 카테고리의 다른 글

고급 위젯과 프래그먼트  (0) 2022.06.13
Splash 화면 만들기  (0) 2022.06.03
RxJava  (0) 2022.05.08
Reactive programming(수정)  (1) 2022.04.22
팝업 메뉴  (1) 2022.04.19
Comments