导航

Android学习之实现Canvas基本画图方法

Posted on 2011-10-03 17:44  Qamefay  阅读(19860)  评论(2编辑  收藏  举报

主要就画一写图形,然后更改一下坐标,使图形在屏幕之间来回动...

直接上代码了..

MainActivity
 1 public class ManiActivity extends Activity {
2 /** Called when the activity is first created. */
3 @Override
4 public void onCreate(Bundle savedInstanceState) {
5 super.onCreate(savedInstanceState);
6
7 // 隐藏状态栏
8 this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
9 WindowManager.LayoutParams.FLAG_FULLSCREEN);
10
11 // 把Activity的标题去掉
12 requestWindowFeature(Window.FEATURE_NO_TITLE);
13
14 // 设置布局
15 setContentView(new MySurfaceView(this));
16 }
17 }

 

MySurfaceView
  1 public class MySurfaceView extends SurfaceView implements Runnable, Callback {
2
3 private SurfaceHolder mHolder; //用于控制SurfaceView
4
5 private Canvas mCanvas; //声明一张画布
6
7 private Paint mPaint, qPaint; //声明两只画笔
8
9 private Path mPath, qPath, tPath; //声明三条路径
10
11 private int mX, mY; //用于控制图形的坐标
12
13 //分别 代表贝塞尔曲线的开始坐标,结束坐标,控制点坐标
14 private int qStartX, qStartY, qEndX, qEndY, qControlX, qCOntrolY;
15
16 private int screenW, screenH; //用于屏幕的宽高
17
18 private Thread mThread; //声明一个线程
19
20 //flag用于线程的标识,xReturn用于标识图形坐标是否返回,cReturn用于标识贝塞尔曲线的控制点坐标是否返回
21 private boolean flag, xReturn, cReturn;
22
23 /**
24 * 构造函数,主要对一些对象初始化
25 */
26 public MySurfaceView(Context context) {
27 super(context);
28
29 mHolder = this.getHolder(); //获得SurfaceHolder对象
30 mHolder.addCallback(this); //添加状态监听
31
32 mPaint = new Paint(); //创建一个画笔对象
33 mPaint.setColor(Color.WHITE); //设置画笔的颜色为白色
34
35 qPaint = new Paint(); //创建一个画笔对象
36 qPaint.setAntiAlias(true); //消除锯齿
37 qPaint.setStyle(Style.STROKE); //设置画笔风格为描边
38 qPaint.setStrokeWidth(3); //设置描边的宽度为3
39 qPaint.setColor(Color.GREEN); //设置画笔的颜色为绿色
40
41 //创建路径对象
42 mPath = new Path();
43 qPath = new Path();
44 tPath = new Path();
45
46 //设置坐标为50,100
47 mX = 50;
48 mY = 100;
49
50 //设置贝塞尔曲线的开始坐标为(10,200)
51 qStartX = 10;
52 qStartY = 200;
53
54 setFocusable(true); //设置焦点
55
56 }
57
58 /**
59 * 当SurfaceView创建的时候调用
60 */
61 @Override
62 public void surfaceCreated(SurfaceHolder holder) {
63
64 //获得屏幕的宽和高
65 screenW = this.getWidth();
66 screenH = this.getHeight();
67
68 qEndX = screenW - 10; //设置贝塞尔曲线的终点横坐标为屏幕宽度减10
69 qEndY = qStartY; //设置贝塞尔曲线的终点纵坐标和起点纵坐标一样
70
71 //设置贝塞尔曲线的控制点坐标为终点坐标与起点坐标对应的差值的一半,注意这里不是曲线的中点
72 qControlX = (qEndX - qStartX) / 2;
73 qCOntrolY = (qEndY - qStartY) / 2;
74
75 mThread = new Thread(this); //创建线程对象
76 flag = true; //设置线程标识为true
77 xReturn = false; //设置图形坐标不返回
78 cReturn = false; //设置贝塞尔曲线控制点坐标不返回
79 mThread.start(); //启动线程
80 }
81
82 /**
83 * 当SurfaceView视图发生改变的时候调用
84 */
85 @Override
86 public void surfaceChanged(SurfaceHolder holder, int format, int width,
87 int height) {
88 }
89
90 /**
91 * 当SurfaceView销毁的时候调用
92 */
93 @Override
94 public void surfaceDestroyed(SurfaceHolder holder) {
95 flag = false; //设置线程的标识为false
96 }
97
98 /**
99 * 线程运行的方法,当线程start后执行
100 */
101 @Override
102 public void run() {
103
104 while (flag) {
105 mDraw(); //调用自定义的绘图方法
106 mGameLogic(); //调用自定义的逻辑方法
107 try {
108 Thread.sleep(50); //让线程休息50毫秒
109 } catch (InterruptedException e) {
110 e.printStackTrace();
111 }
112 }
113 }
114
115 /**
116 * 自定义的绘图方法
117 */
118 public void mDraw() {
119
120 mCanvas = mHolder.lockCanvas(); //获得画布对象,开始对画布画画
121
122 mCanvas.drawColor(Color.BLACK); //设置画布颜色为黑色
123
124 canvasMethod(mCanvas); //调用自定义的方法,主要是在传进去的画布对象上画画
125
126 mHolder.unlockCanvasAndPost(mCanvas); //把画布显示在屏幕上
127 }
128
129 /**
130 * 自定义的方法,简单绘制一些基本图形
131 * @param mCanvas
132 * 把图形画在mCanvas上
133 */
134 public void canvasMethod(Canvas mCanvas) {
135
136 //创建对应坐标的矩形区域
137 RectF mArc = new RectF(mX, mY - 70,mX + 50, mY -20);
138 //画填充弧,在矩形区域内,从弧的最右边开始,画270度,然后再通过连接圆心来填充
139 mCanvas.drawArc(mArc, 0, 270, true, mPaint);
140
141 //获得icon的Bitmap对象
142 Bitmap mBitmap = BitmapFactory.decodeResource(getResources(),
143 R.drawable.icon);
144 //画图片
145 mCanvas.drawBitmap(mBitmap, mX, mY, mPaint);
146
147 //画圆,(x轴,y轴,半径,画笔)
148 mCanvas.drawCircle(mX + 10, mY + 60, 10, mPaint);
149
150 //画一条线,(起点横坐标,起点纵坐标,终点横坐标,终点纵坐标,画笔)
151 mCanvas.drawLine(mX, mY + 75, mX + 20, mY + 75, mPaint);
152 //画多条线,(坐标数组,画笔)坐标数组里每四个值构成一条线
153 mCanvas.drawLines(new float[] { mX + 50, mY + 45, mX + 50, mY + 75,
154 mX + 60, mY + 45, mX + 60, mY + 75 }, mPaint);
155
156 //创建对应矩形区域
157 RectF mOval = new RectF(mX, mY + 80, mX + 60, mY + 110);
158 //画椭圆
159 mCanvas.drawOval(mOval, mPaint);
160
161 /*
162 * Paint qPaint = new Paint(); qPaint.setColor(Color.RED);
163 * mCanvas.drawPaint(qPaint);
164 */
165
166 //重置Path里的所有路径
167 mPath.reset();
168 //设置Path的起点
169 mPath.moveTo(mX, mY + 120);
170 //第二个点
171 mPath.lineTo(screenW - 10, mY + 120);
172 //第三个点
173 mPath.lineTo(screenW - 10, mY + 150);
174 //画出路径,这里画的是三角形
175 mCanvas.drawPath(mPath, mPaint);
176
177 //重置Path里的所有路径
178 qPath.reset();
179 //设置Path的起点
180 qPath.moveTo(qStartX, qStartY);
181 //设置贝塞尔曲线的控制点坐标和终点坐标
182 qPath.quadTo(qControlX, qCOntrolY, qEndX, qEndY);
183 //画出贝塞尔曲线
184 mCanvas.drawPath(qPath, qPaint);
185
186 //画点
187 mCanvas.drawPoint(mX, mY + 155, qPaint);
188 //画多个点,坐标数组每两个值代表一个点的坐标
189 mCanvas.drawPoints(new float[] { mX, mY + 160, mX + 5, mY + 160,
190 mX + 5, mY + 160 }, qPaint);
191
192 //画矩形
193 mCanvas.drawRect(mX, mY + 170, mX + 100, mY + 220, mPaint);
194
195 //设置矩形区域
196 RectF mRect = new RectF(mX, mY + 230, mX + 100, mY + 260);
197 //画圆角矩形,这个方法的第二第三个参数在后面有图讲解
198 mCanvas.drawRoundRect(mRect, 10, 10, mPaint);
199
200 //画文本
201 mCanvas.drawText("drawText", mX, mY + 290, mPaint);
202 //画文本,数组里每两个值代表文本的一个字符的坐标,数组的坐标可以比字符串里的字符多,但不可以少
203 mCanvas.drawPosText("哈哈你好", new float[] { mX, mY + 310, mX + 20,
204 mY + 310, mX + 40, mY + 310, mX + 60, mY + 310 }, mPaint);
205
206 //重置Path
207 tPath.reset();
208 //添加一个圆形路径,坐标,半径,方向(顺时针还是逆时针)
209 tPath.addCircle(mX + 10, mY + 340, 10, Path.Direction.CW);
210 //画出路径
211 mCanvas.drawPath(tPath, qPaint);
212 //把文本画在路径上,但不会画出路径
213 mCanvas.drawTextOnPath("draw", tPath, 30, 0, mPaint);
214
215 }
216
217 /**
218 * 自定义游戏逻辑方法
219 */
220 public void mGameLogic() {
221
222 //判断图形横坐标是否返回
223 if (!xReturn) { //横坐标不返回
224 //判断图形横坐标是否小于屏幕宽度减去100
225 if (mX < (screenW - 100)) { //小于
226 mX += 3; //横坐标往右3
227 } else { //不小于
228 xReturn = true; //设置横坐标返回
229 }
230 } else { //横坐标返回
231 //判断横坐标是否大于10
232 if (mX > 10) { //大于
233 mX -= 3; //横坐标往左3
234 } else { //不大于
235 xReturn = false; //设置横坐标不返回
236 }
237 }
238
239 //判断贝塞尔曲线的控制点横坐标是否返回
240 if (!cReturn) { //控制点横坐标不返回
241 //判断控制点横坐标是否小于终点横坐标减3
242 if (qControlX < (qEndX - 3)) { //小于
243 qControlX += 3; //控制点横坐标往右3
244 } else { //不小于
245 cReturn = true; //设置控制点横坐标返回
246 }
247 } else { //控制点横坐标返回
248 //判断控制点横坐标是否大于起点横坐标加3
249 if (qControlX > (qStartX + 3)) { //大于
250 qControlX -= 3; //控制点横坐标减3
251 } else { //不大于
252 cReturn = false; //设置控制点横坐标不返回
253 }
254 }
255 }
256
257 /**
258 * 当屏幕被触摸时调用
259 */
260 @Override
261 public boolean onTouchEvent(MotionEvent event) {
262
263 //设置贝塞尔曲线的坐标为触摸时坐标
264 qStartX = (int) event.getX();
265 qStartY = (int) event.getY();
266
267 //设置贝塞尔曲线的控制点坐标为终点坐标与起点坐标对应的差值的一半,注意这里不是曲线的中点
268 qControlX = Math.abs(qEndX - qStartX) / 2;
269 qCOntrolY = Math.abs(qEndY - qStartY) / 2;
270
271 //设置控制点的横坐标不返回
272 cReturn = false;
273 return super.onTouchEvent(event);
274 }
275 }



 

先贴上运行起来的图片


画圆角矩形
drawRoundRect(rect, rx, ry, paint)

主要是讲第二个和第三个参数...贴张图说明,

这是在ry小于你定义的矩形区域的高的一半的时候的情况,如果你的ry设置成大于矩形区域高的一半的时候,他也会画出一个图形出来,不过那是怎么画出来的我也搞不清楚了,有自己想法的共享一下..