Home » Android -10. 2D 그래픽 처리 및 애니메이션

Android -10. 2D 그래픽 처리 및 애니메이션

10.1. 2D 그래픽 처리 – 도형

<step8/ GraphicSample>
[php]
setContentView(new GraphicSampleView(GraphicSample.this));
[/php]

<step8/ GraphicSampleView>
[php]
public GraphicSampleView(Context context) {
super(context);
mPaint = new Paint(); // 페인트 객체 생성
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon9);
mRect = new Rect(10, 10, 100, 100); // 사각형 생성
mRectF = new RectF(110, 10, 200, 100);
}
… 생략

// 실제 그리기를 실행하는 메소드
// 인자로 넘어오는 canvas가 도화지의 개념이다
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// view의 화면 색 설정
canvas.drawColor(Color.WHITE);

// 사각형을 그리기 위한 페인트 색상 설정
mPaint.setColor(Color.RED);

// canvas에 사각형을 그려주는 메소드
canvas.drawRect(mRect, mPaint);

// 페인트 색상 재설정
mPaint.setColor(Color.BLUE);

// 호를 그려주는 메소드
canvas.drawArc(mRectF, 0, 90, true, mPaint);

// 페인트 색상 재설정
mPaint.setColor(Color.BLACK);

// 원을 그려주는 메소드
canvas.drawCircle(getWidth()/2, getHeight()/2, 50, mPaint);

// 페인트 색상 재설정, parseColor 메소드를 이용해 색상표의 값으로 지정 가능하다
mPaint.setColor(Color.parseColor("#148CFF"));
// 선의 굵기 설정
mPaint.setStrokeWidth(5);

// 지정된 좌료에 점을 찍는다
canvas.drawPoint(300, 30, mPaint);

// 페인트 색상 설정, rgb 메소드를 이용하여 설정 가능
mPaint.setColor(Color.rgb(128, 128, 128));
// 첫 두개의 인자는 선의 시작 점의 위치
// 3, 4번째의 인자는 선의 종료 점의 위치이다..
canvas.drawLine(0, getHeight() / 2, getWidth() / 2, getHeight(), mPaint);

// View의 좌측 하단에 아이콘을 그린다.
canvas.drawBitmap(mBitmap, 0, getHeight() – mBitmap.getHeight(), null);

// dash line
DashPathEffect dashPath = new DashPathEffect(new float[]{20,3}, 1);
mPaint.setPathEffect(dashPath);
mPaint.setStrokeWidth(8);
canvas.drawLine(getWidth() / 2, getHeight()/2 + 100, 320, 350, mPaint);
}
[/php]


그림 45. 그래픽 처리 1

10.2. 2D 그래픽 처리 – 텍스트 스타일

<step8/ GraphicSampleView2>
[php]
// view의 화면 색 설정
canvas.drawColor(Color.WHITE);

// anti alias 설정
mPaint.setAntiAlias(false);

// stroke style
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(2);
mPaint.setColor(Color.MAGENTA);
mPaint.setTextSize(30);
canvas.drawText("STROKE STYLE", 75, 110, mPaint);

// FILL style
mPaint.setStyle(Paint.Style.FILL);
// anti alias 설정
mPaint.setAntiAlias(true);
mPaint.setTextSize(30);
canvas.drawText("FILL STYLE", 75, 150, mPaint);

// 텍스트 회전
String text = "!Roate";
float x = 175f;
float y = 350f;

mPaint.setTextSize(60);
// 글자의 외부를 감싸고 있는 사각크기를 가져온다
mPaint.getTextBounds(text, 0, text.length(), rect);
canvas.translate(x, y);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText(text, 0, 0, mPaint);

/** 위치값을 원래대로 돌리고 글자를 회전한다. */
String strRotated = "Rotated!";
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setTextSize(60);
canvas.drawRect(rect, mPaint);
// 위치값을 원래대로 돌린다.
canvas.translate(-x, -y);
canvas.rotate(-45, x + rect.exactCenterX(), y + rect.exactCenterY());

mPaint.setStyle(Paint.Style.FILL);
canvas.drawText(strRotated, x, y, mPaint);

canvas.restore();
[/php]


그림 46. 그래픽 처리 2

10.3. 페인트 보드

  • 터치한채 움직이면 움직임에 따라 선이 그어지는 예제

<step8/GraphicSampleView3>
[php]
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

canvas.drawColor(Color.WHITE);

// title text
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(30);
canvas.drawText("Paint board", 10, 50, mPaint);

if(pointList.size() < 2) return;
for(int i = 1; i<pointList.size(); i++) { (1)
if(pointList.get(i).draw) {
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawLine(pointList.get(i-1).x,
pointList.get(i-1).y, pointList.get(i).x, pointList.get(i).y, mPaint);
}
}
}

@Override
public boolean onTouch(View v, MotionEvent event) {
x = event.getX();
y = event.getY();

switch(event.getAction()) {
case MotionEvent.ACTION_DOWN : // 눌렀을 때는 포인트만 저장, 그리지는 않음
pointList.add(new Point(x, y, false)); (2)
invalidate();
break;

case MotionEvent.ACTION_MOVE : // 움직였을때 포인트 저장, 그리기 적용
pointList.add(new Point(x, y, true)); (3)
invalidate();
break;

case MotionEvent.ACTION_UP : // 손을 떼었을 때
break;
}
return true;
} }
[/php]

번호 설명
(1) 포인트 리스트에 값을 빼내어 점과 점을 라인을 그려준다.
(2) 터치만 했을 때는 포인트만 추가, 그리지는 않도록 함
(3) 움직였을 때는 화면에 그려주도록 함


그림 47. 페인트 보드

10.4. 애니메이션

<step8/AnimationSample>
[php]
@Override
public void onClick(View v) {
Animation anim = null;
switch (v.getId()) {
case R.id.animationSampleAlphaButton:
// xml 파일로부터 정보를 가져와 애니메이션 객체 생성
anim =
AnimationUtils.loadAnimation(AnimationSample.this, R.anim.alpha_sample); (1)
break;
case R.id.animationSampleRotateButton:
anim =
AnimationUtils.loadAnimation(AnimationSample.this, R.anim.rotate_sample);
break;
… 생략
// 해당 뷰의 애니메이션 시작
imgView.startAnimation(anim); (2)
}
[/php]

번호 설명
(1) 애니메이션이 정의된 xml로부터 정보를 가져와 객체 생성
(2) 이미지뷰의 애니메이션을 실행 시킴

투명도 애니메이션

<anim/alpha_sample.xml>
[php]
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000" (1)
android:fromAlpha="0.0" (2)
android:interpolator="@android:anim/accelerate_interpolator" (3)
android:toAlpha="1.0" /> (4)
[/php]

번호 설명
(1) 애니메이션 동작 시간
(2) 투명도 시작 값 설정
(3) 가속도 설정, 점점 빠르게 진행됨
(4) 투명도 종료 값 설정

회전 애니메이션

<anim/rotate_sample.xml>
[php]
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0" (1)
android:toDegrees="360" (2)
android:pivotX="50%" (3)
android:pivotY="50%" (4)
android:duration="6000"
/>
[/php]

번호 설명
(1) 회전에 대한 초기값
(2) 회전에 대한 종료 값
(3) 뷰의 크기가 변경될 때 뷰의 위치를 의미. 0% 이면 뷰의 좌측이 고정된 상태로 크기가 변경되며 50% 이면 뷰의 중점을 중심으로 뷰의 크기가 변경 즉, 뷰가 커질 땐 좌우로 함께 커지고, 작아질때에도 좌우로 줄어든다.
(4) 뷰의 크기가 변경될 때 뷰의 위치를 의미. 0% 이면 뷰의 상단이 고정된 상태로 크기가 변경되며 50% 이면 뷰의 중점을 중심으로 뷰의 크기가 변경된다. 즉, 뷰가 커질 땐 상하로 함께 커지고, 작아질때에도 상하로 줄어든다.

크기조절 애니메이션

<anim/scale_sample.xml>
[php]
<?xml version="1.0" encoding="utf-8"?>
<scale
android:duration="2500"
android:fromXScale="1.0" (1)
android:fromYScale="1.0" (2)
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.5" (3)
android:toYScale="0.5" /> (4)
<scale
android:startOffset="2500" (5)
android:duration="2500"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="2.0"
android:toYScale="2.0" />
[/php]

번호 설명
(1) 가로 크기의 초기 값. 1.0일 경우 원본 상태
(2) 세로 크기의 초기 값. 1.0일 경우 원본 상태
(3) 변화 할 가로의 크기 값. 0.5면 1/2로 작아짐
(4) 변화 할 세로의 크기 값. 0.5면 1/2로 작아짐
(5) 2.5초 뒤에 애니메이션이 시작하도록 하는 설정

움직임 애니메이션

<anim/translate_sample.xml>
[php]
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fromXDelta="0" (1)
android:fromYDelta="0" (2)
android:repeatCount="0" (3)
android:toXDelta="50%p" /> (4)
[/php]

번호 설명
(1) 뷰의 X 좌표상 시작 위치. 수치값을 직접 입력하면 픽셀단위의 위치로 판단하여 해당 위치에서 시작하며 퍼센트값을 입력하면 뷰의 너비에서 해당 퍼센트를 연산한 위치에서 시작. 또 퍼센트 뒤에 p 를 붙이면 뷰를 소유한 부모 객체의 너비에서 퍼센트를 연산한 위치에서 시작하게 된다.
(2) 뷰의 Y 좌표상 시작 위치. 해당 속성이 가질 수 있는 값은 fromXDelta 와 같다.
(3) 반복 횟수
(4) 뷰의 X 좌표상 이동 종료 위치. 해당 속성이 가질 수 있는 값은 fromXDelta 와 같다.

10.5. 그래프 애니메이션

<graph_sample.xml>
[php]
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" > (1)
<scale
android:duration="3000"
android:fromXScale="0.0"
android:fromYScale="1.0"
android:pivotX="0%p"
android:pivotY="50%p"
android:toXScale="1.0"
android:toYScale="1.0" />
</set>
[/php]

번호 설명
(1) Set으로 묶으면 2개이상의 애니메이션을 묶어서 실행할 수 있다.

<step8/GraphAnimationSample>
[php]
gAnim = AnimationUtils.loadAnimation(GraphAnimationSample.this, R.anim.graph_sample);
… 생략
ProgressBar proBar = new ProgressBar(act, null, android.R.attr.progressBarStyleHorizontal);
proBar.setIndeterminate(false);
proBar.setMax(100);
proBar.setProgress(100);
proBar.setAnimation(gAnim); (1)
params2.height = 20;
params2.width = value * 2;
params2.gravity = Gravity.LEFT;
itemLayout.addView(proBar, params2); (2)
… 생략
gAnim.start(); (3)
[/php]

번호 설명
(1) 프로그레스바에 scale 애니메이션을 설정
(2) 레이아웃에 프로그레스바를 추가한다.
(3) 애니메이션 시작