android canvas 의 onDraw() 내에서
삼각형, 별, 하트 그리기 예제입니다.
Canvas 내 터치 영역에서 각 도형을 새로 그리는 예제도 TouchEvent 안에 적용되어 있습니다.
참고url
http://android-er.blogspot.kr/2014/05/draw-star-on-canvas.html
간단히 도형을 선택하는 버튼과 custom view가 정의 됩니다.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/bt_triangle"
android:text="삼각형"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/bt_triangle"
android:id="@+id/bt_star"
android:text="별"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/bt_star"
android:id="@+id/bt_heart"
android:text="하트"/>
<poisonrose.myapplication_canvas.MyView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_below="@id/bt_triangle"
android:id="@+id/my_view"/>
</RelativeLayout>
MainActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MyView my_view = (MyView) findViewById(R.id.my_view);
Button bt_triangle = (Button) findViewById(R.id.bt_triangle);
bt_triangle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
my_view.drawTriangle();
}
});
Button bt_star = (Button) findViewById(R.id.bt_star);
bt_star.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
my_view.drawStar();
}
});
Button bt_heart = (Button) findViewById(R.id.bt_heart);
bt_heart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
my_view.drawHeart();
}
});
}
}
MyView.java
생성자에서는 Paint 와 Path를 초기화 합니다.
실제 도형을 그리는 부분은 onDraw내의 canvas.drawPath() 에서 그리며,
포퍼먼스를 고려하여 항상, path의 reset(), close()를 잘 사용하여야 합니다.
코드내에서 보여지는 x, y 값이 선이 시작하는 부분이며,
TouchEvent에서는 현재 터치값을 불러와서 도형을 그리는 형태로 코드를 작성했습니다.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MyView extends View {
Paint m_Paint;
Path m_Path;
Canvas m_Canvas;
enum Mode {
TRIANGLE,
STAR,
HEART
}
private Mode mMode;
private int mViewWidth = 0;
private int mViewHeight = 0;
public MyView(Context context) {
super(context);
initMyView();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initMyView();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initMyView();
}
public void initMyView(){
m_Paint = new Paint();
m_Paint.setAntiAlias(true);
m_Paint.setDither(true);
m_Paint.setColor(0xFFFF0000);
m_Paint.setStyle(Paint.Style.STROKE);
m_Paint.setStrokeJoin(Paint.Join.ROUND);
m_Paint.setStrokeCap(Paint.Cap.ROUND);
m_Paint.setStrokeWidth(4);
m_Path = new Path();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mViewWidth = MeasureSpec.getSize(widthMeasureSpec);
mViewHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(mViewWidth, mViewHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
m_Canvas = canvas;
m_Canvas.drawColor(0xFFFFFFFF);
if(mMode == Mode.HEART) {
float x = mViewWidth/2;
float y = mViewHeight/2;
m_Canvas.rotate(45,x,y);
}
// Path 갱신 영역
m_Canvas.drawPath(m_Path, m_Paint);
}
public void drawTriangle() {
float x = mViewWidth/2;
float y = mViewHeight/2;
drawTriangle(x, y);
}
public void drawTriangle(float x, float y) {
mMode = Mode.TRIANGLE;
int side = 200; /** 삼각형 크기 */
int height = 300;
y = y - height;
m_Path.reset();
Point point1_draw = new Point((int)x, (int)y); // 왼
Point point2_draw = new Point((int)x-side, (int)y+height); // 아래
Point point3_draw = new Point((int)x+side, (int)y+height); // 오른
m_Path.moveTo(point1_draw.x, point1_draw.y);
m_Path.lineTo(point2_draw.x, point2_draw.y);
m_Path.lineTo(point3_draw.x, point3_draw.y);
m_Path.lineTo(point1_draw.x, point1_draw.y);
m_Path.close();
invalidate();
}
public void drawStar() {
float x = mViewWidth/2;
float y = mViewHeight/2;
drawStar(x, y);
}
public void drawStar(float x, float y) {
mMode = Mode.STAR;
int radius = 200; /** 별 크기 */
y = y - radius;
int numOfPt = 5;
double section = 2.0 * Math.PI/numOfPt;
int innerRadius = (int) (radius / 2.5);
m_Path.reset();
m_Path.moveTo(
(float)(x + radius * Math.cos(0)),
(float)(y + radius * Math.sin(0)));
m_Path.lineTo(
(float)(x + innerRadius * Math.cos(0 + section/2.0)),
(float)(y + innerRadius * Math.sin(0 + section/2.0)));
for(int i=1; i < numOfPt; i++){
m_Path.lineTo(
(float)(x + radius * Math.cos(section * i)),
(float)(y + radius * Math.sin(section * i)));
m_Path.lineTo(
(float)(x + innerRadius * Math.cos(section * i + section/2.0)),
(float)(y + innerRadius * Math.sin(section * i + section/2.0)));
}
m_Path.close();
invalidate();
}
public void drawHeart() {
float x = mViewWidth/2;
float y = mViewHeight/2;
drawHeart(x, y);
}
public void drawHeart(float x, float y) {
mMode = Mode.HEART;
float length = 200; // 하트 크기
m_Path.reset();
m_Path.moveTo(x,y);
m_Path.lineTo(x-length, y);
m_Path.arcTo(new RectF(x-length-(length/2),y-length,x-(length/2),y),90,180);
m_Path.arcTo(new RectF(x-length,y-length-(length/2),x,y-(length/2)),180,180);
m_Path.lineTo(x,y);
m_Path.close();
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDraw(x, y);
break;
case MotionEvent.ACTION_MOVE:
touchDraw(x, y);
break;
case MotionEvent.ACTION_UP:
touchDraw(x, y);
break;
}
return true;
}
private void touchDraw(float x, float y) {
if(mMode == Mode.TRIANGLE) {
drawTriangle(x, y);
} else if(mMode == Mode.STAR) {
drawStar(x, y);
} else if(mMode == Mode.HEART) {
drawHeart(x, y);
}
}
}