안드로이드 그림판을 만들어 보았다. 색상을 선택할 수 있도록 하였고 선의 끝부분을 달리할 수 있게 하였으며 굴기를 선택할 수 있게 하였다. 너무나도 재미있다.
기능)
1. 그림 그리기
2. 색상 선택
3. 굵기 선택
4. 선끝모양 설정
배운것)
1. OpenSource중 ColorPicker를 쉽게 해주는 오픈소스가 있다는 것을 발견함.
2. 다양한 그림 그리는 방법을 익힘.
3. 다이얼로그 사용법을 익힘.
MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
package org.techtown.paintboard;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.InputType;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
import yuku.ambilwarna.AmbilWarnaDialog;
public class MainActivity extends AppCompatActivity {
MyPaintView view;
int tColor,n=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = new MyPaintView(this);
LinearLayout container = findViewById(R.id.container);
Resources res = getResources();
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
container.addView(view, params);
RadioButton rBtn1 = findViewById(R.id.radioButton);
RadioButton rBtn2 = findViewById(R.id.radioButton2);
RadioButton rBtn3 = findViewById(R.id.radioButton3);
RadioGroup radioGroup = findViewById(R.id.radioGroup);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.radioButton:
view.setCap(0);
break;
case R.id.radioButton2:
view.setCap(1);
break;
case R.id.radioButton3:
view.setCap(2);
break;
}
}
});
Button btn=findViewById(R.id.colorPickerButton);
Button btn2=findViewById(R.id.thickPickerButton);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openColorPicker();
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
show();
}
});
}
private void show() {
final EditText editText=new EditText(this);
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("AlertDialog Title");
builder.setMessage("굵기 입력");
builder.setView(editText);
builder.setPositiveButton("입력",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
view.setStrokeWidth(Integer.parseInt(editText.getText().toString()));
}
});
builder.setNegativeButton("취소",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
builder.show();
}
private void openColorPicker() {
AmbilWarnaDialog colorPicker = new AmbilWarnaDialog(this, tColor, new AmbilWarnaDialog.OnAmbilWarnaListener() {
@Override
public void onCancel(AmbilWarnaDialog dialog) {
}
@Override
public void onOk(AmbilWarnaDialog dialog, int color) {
Toast.makeText(getApplicationContext(),""+tColor,Toast.LENGTH_LONG).show();
view.setColor(color);
}
});
colorPicker.show();
}
}
|
cs |
MyPaintView.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
package org.techtown.paintboard;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
public class MyPaintView extends View {
public boolean changed = false;
Canvas mCanvas;
Bitmap mBitmap;
Paint mPaint;
float lastX;
float lastY;
Path mPath = new Path();
float mCurveEndX;
float mCurveEndY;
int mInvalidateExtraBorder = 10;
static final float TOUCH_TOLERANCE = 8;
public MyPaintView(Context context) {
super(context);
init(context);
}
public MyPaintView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3.0F);
this.lastX = -1;
this.lastY = -1;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Bitmap img = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas();
canvas.setBitmap(img);
canvas.drawColor(Color.WHITE);
mBitmap = img;
mCanvas = canvas;
}
@Override
protected void onDraw(Canvas canvas) {
if (mBitmap != null) {
canvas.drawBitmap(mBitmap, 0, 0, null);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
changed = true;
Rect rect = touchUp(event, false);
if (rect != null) {
invalidate(rect);
}
mPath.rewind();
return true;
case MotionEvent.ACTION_DOWN:
rect = touchDown(event);
if (rect != null) {
invalidate(rect);
}
return true;
case MotionEvent.ACTION_MOVE:
rect = touchMove(event);
if (rect != null) {
invalidate(rect);
}
return true;
}
return false;
}
private Rect touchMove(MotionEvent event) {
Rect rect=processMove(event);
return rect;
}
private Rect processMove(MotionEvent event) {
final float x=event.getX();
final float y=event.getY();
final float dx=Math.abs(x-lastX);
final float dy=Math.abs(y-lastY);
Rect mInvalidateRect=new Rect();
if(dx>=TOUCH_TOLERANCE || dy>=TOUCH_TOLERANCE){
final int border=mInvalidateExtraBorder;
mInvalidateRect.set((int)mCurveEndX-border,(int)mCurveEndY-border,(int)mCurveEndX+border,(int)mCurveEndY+border);
float cx=mCurveEndX=(x+lastX)/2;
float cy=mCurveEndY=(y+lastY)/2;
mPath.quadTo(lastX,lastY,cx,cy);
mInvalidateRect.union((int)lastX-border,(int)lastY-border,(int)lastX+border,(int)lastY+border);
mInvalidateRect.union((int)cx-border,(int)cy-border,(int)cx,(int)cy+border);
lastX=x;
lastY=y;
mCanvas.drawPath(mPath,mPaint);
}
return mInvalidateRect;
}
private Rect touchDown(MotionEvent event) {
float x=event.getX();
float y=event.getY();
lastX=x;
lastY=y;
Rect mInvalidateRect=new Rect();
mPath.moveTo(x,y);
final int border=mInvalidateExtraBorder;
mInvalidateRect.set((int)x-border,(int)y-border,(int)x+border,(int)y+border);
mCurveEndX=x;
mCurveEndY=y;
mCanvas.drawPath(mPath,mPaint);
return mInvalidateRect;
}
public void setStrokeWidth(int width){
mPaint.setStrokeWidth(width);
}
private Rect touchUp(MotionEvent event, boolean b) {
Rect rect=processMove(event);
return rect;
}
public void setColor(int color){
mPaint.setColor(color);
}
public void setCap(int cap){
switch(cap){
case 0:
mPaint.setStrokeCap(Paint.Cap.BUTT);
break;
case 1:
mPaint.setStrokeCap(Paint.Cap.ROUND);
break;
case 2:
mPaint.setStrokeCap(Paint.Cap.SQUARE);
break;
}
}
}
|
cs |
activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<?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="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/colorPickerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="색상선택" />
<Button
android:id="@+id/thickPickerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="굵기입력" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="BUTT" />
<RadioButton
android:id="@+id/radioButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ROUND" />
<RadioButton
android:id="@+id/radioButton3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SQUARE" />
</RadioGroup>
</LinearLayout>
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"></LinearLayout>
</LinearLayout>
|
cs |
build.gradle.xml (app)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "org.techtown.paintboard"
minSdkVersion 15
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
dependencies { implementation 'com.github.yukuku:ambilwarna:2.0.1' }
}
|
cs |
'IT > 안드로이드' 카테고리의 다른 글
구글 테스트 아이디를 이용한 안드로이드 애드몹 적용하기 (0) | 2019.10.11 |
---|---|
안드로이드 에뮬레이터 용량문제(에뮬레이터 초기화) (0) | 2019.10.11 |
안드로이드 권한설정 관련 라이브러리 (0) | 2019.10.11 |
안드로이드 내용제공자(Content Provider) (0) | 2019.10.09 |
안드로이드의 데이터베이스 SQLite (0) | 2019.10.09 |