自定义View(1)简单流程及示例模板

1,继承View , ViewGroup,或TextView等等

2,绘制相关的api,

  • canvas 画布,
  • paint 画笔

2,重写重要的函数(注意这个顺序)

  • onMeasure 属于View的方法,用来测量自己及其中绘制内容的定宽度和高度
  • onLayout  布局其内部view的位置和大小
  • onSizeChanged 本view大小变化时的回调
  • onDraw  在其中用绘制api 绘制本view
  • onTouchEvent  处理感兴趣的事件,这里是touch事件
  • view 还可以定义一些xml属性(少用)

示例代码

  1 import android.app.Dialog;
  2 import android.content.Context;
  3 import android.graphics.Bitmap;
  4 import android.graphics.BitmapFactory;
  5 import android.graphics.Canvas;
  6 import android.graphics.Color;
  7 import android.graphics.DashPathEffect;
  8 import android.graphics.LinearGradient;
  9 import android.graphics.Paint;
 10 import android.graphics.Paint.Align;
 11 import android.graphics.Paint.FontMetrics;
 12 import android.graphics.Path;
 13 import android.graphics.PathEffect;
 14 import android.graphics.PorterDuff.Mode;
 15 import android.graphics.PorterDuffXfermode;
 16 import android.graphics.Rect;
 17 import android.graphics.RectF;
 18 import android.graphics.Shader;
 19 import android.graphics.Xfermode;
 20 import android.util.AttributeSet;
 21 import android.view.Gravity;
 22 import android.view.MotionEvent;
 23 import android.view.View;
 24 import android.view.ViewGroup;
 25 import android.widget.ListView;
 26 import android.widget.SectionIndexer;
 27 import android.widget.TextView;
 28 
 29 import com.example.fastscroll.R;
 30 
 31 public class CustomAlphabetFastScrollView extends View {
 32 
 33     //下面3个是用于绘制,其中canvas,bitmap用于缓冲
 34     Paint     paint;
 35     Canvas  canvasForCache;
 36     Bitmap     bitmapForCache;
 37     
 38     String     alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 39     SectionIndexer sectionIndexer;
 40     ListView mListView;
 41     int     currentSection;
 42     int     baseline;
 43     int      bgColor;
 44     int     alphabetTxtColor;
 45     int      alphabetHighlightTxtColor;
 46     
 47     Dialog     sectionDlg;        //显示section文本    
 48     TextView sectionText;    //sectionDlg使用的view
 49     
 50     /*属于View的方法,用来测量自己及其中绘制内容的定宽度和高度*/
 51     @Override
 52     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 53         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 54         int width = MeasureSpec.getSize(widthMeasureSpec);
 55         int height = MeasureSpec.getSize(heightMeasureSpec);
 56         ViewGroup.LayoutParams l = getLayoutParams();
 57         if (l.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
 58             width = (int) paint.getTextSize()*2;
 59         } 
 60         if (l.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
 61             height = (int) paint.getTextSize() * alphabet.length();
 62         }
 63         setMeasuredDimension(width, height);
 64         System.out.println(String.format("width = %d ,height = %d ", width,height));
 65     }
 66     /*本view大小变化时的回调*/
 67     @Override
 68     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
 69         super.onSizeChanged(w, h, oldw, oldh);
 70         bitmapForCache = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
 71         canvasForCache.setBitmap(bitmapForCache);
 72         drawToCache();
 73     }
 74     /*布局 子view在位置和大小*/
 75     @Override
 76     protected void onLayout(boolean changed, int left, int top, int right,
 77             int bottom) {
 78         super.onLayout(changed, left, top, right, bottom);
 79     }
 80     @Override
 81     public boolean onTouchEvent(MotionEvent event) {
 82         switch (event.getAction()) {
 83         case MotionEvent.ACTION_DOWN:
 84         case MotionEvent.ACTION_MOVE:
 85             setBackgroundColor(Color.parseColor("#8B7355"));
 86             float y =  event.getY() ;
 87             for (int i = alphabet.length() - 1; i >= 0 ; --i) {
 88                 if ( i * paint.getTextSize() < y){
 89                     currentSection = i;
 90                     sectionText.setText(alphabet.charAt(i) + "");
 91                     if (mListView != null && sectionIndexer != null) {
 92                         int pos = sectionIndexer.getPositionForSection(currentSection);
 93                         mListView.setSelection(pos);
 94                     }
 95                     break;
 96                 }
 97             }
 98             sectionDlg.show();
 99             drawToCache();
100             break;
101         case MotionEvent.ACTION_UP:
102             sectionDlg.dismiss();
103             setBackgroundColor(bgColor);
104             break;
105         default:
106             break;
107         }
108         return true;
109     }
110     void clearCanvas(Canvas canvas){
111         Xfermode old = paint.getXfermode();
112         paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
113         canvasForCache.drawPaint(paint);
114         paint.setXfermode(old);
115     }
116     void drawToCache(){
117         clearCanvas(canvasForCache);
118         canvasForCache.save();
119         paint.setColor(bgColor);
120         Rect outRect = new Rect();
121         getDrawingRect(outRect);
122         canvasForCache.drawRect(outRect, paint);
123         int viewHeight = getHeight();
124         int sectionHeight = viewHeight / alphabet.length();
125         int diff = viewHeight - sectionHeight * alphabet.length();
126         baseline = sectionHeight + diff/2;
127         paint.setColor(alphabetTxtColor);
128         canvasForCache.drawLine(0, baseline, getWidth(), baseline, paint);
129         paint.setTextSize(sectionHeight);
130         for (int i = 0; i < alphabet.length(); ++i){
131             if (currentSection == i){
132                 paint.setColor(alphabetHighlightTxtColor);
133             }else{
134                 paint.setColor(alphabetTxtColor);
135             }
136             canvasForCache.drawText("" + alphabet.charAt(i), 0, baseline  + sectionHeight * i, paint);
137         }
138         canvasForCache.restore();
139     }
140     
141     void init(){
142         bgColor = Color.parseColor("#00E3E3E3");
143         alphabetTxtColor = Color.BLACK;
144         alphabetHighlightTxtColor = Color.parseColor("#FF00FF");
145 
146         paint = new Paint(Paint.ANTI_ALIAS_FLAG);
147         paint.setStyle(Paint.Style.FILL);
148         paint.setColor(bgColor);
149         paint.setTextAlign(Paint.Align.LEFT);
150         
151         canvasForCache = new Canvas();
152         sectionText = new TextView(getContext());
153         sectionText.setMinEms(2);
154         sectionText.setGravity(Gravity.CENTER);
155         sectionText.setWidth((int) (paint.getTextSize()*4));
156         sectionText.setHeight((int) (paint.getTextSize()*4));
157         sectionDlg = new Dialog(getContext(),R.style.customDlgTheme);
158         sectionDlg.setContentView(sectionText);
159     }
160 
161     void drawSample(Canvas canvas) {
162         /*
163          * 方法 说明 drawRect 绘制矩形 drawCircle 绘制圆形 drawOval 绘制椭圆 drawPath 绘制路径
164          * drawLine 绘制直线 drawPoin 绘制点 
165          */
166         // 创建画笔
167         Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
168         int txtSize = 24;
169         paint.setTextSize(txtSize);
170         /*画点*/
171         paint.setStyle(Paint.Style.FILL);
172         canvas.drawText("画点:", 10, txtSize, paint);
173         paint.setColor(Color.RED);
174         float stroke = paint.getStrokeWidth();
175         paint.setStrokeWidth(3);
176         canvas.drawPoint(100, 20, paint);// 画一个点
177         canvas.drawPoints(new float[] { 170, 20, 180, 20, 190, 20 }, paint);// 画多个点
178         paint.setStrokeWidth(stroke);
179         
180         
181         /*画线*/
182         paint.setColor(Color.BLACK);
183         canvas.drawText("画线:", 10, 54, paint);
184         canvas.drawLine(110, 40, 200, 40, paint);// 画线
185         canvas.drawLine(210, 40, 400, 55, paint);// 斜线
186         
187         /*画虚线*/
188         canvas.drawText("画虚线:", 10,84, paint);
189         paint.setStyle(Paint.Style.STROKE);
190         Path path3 = new Path();     
191         path3.moveTo(110, 84);
192         path3.lineTo(400,84);
193         /*DashPathEffect第一个参数必须为偶数个整数,其中偶数位上的整数表示绘制的间隔,奇数位上的整数表示不绘制的间隔。*/
194         PathEffect effects = new DashPathEffect(new float[]{5,30,5,30,5,30},1);
195         PathEffect oldEffect = paint.getPathEffect();
196         paint.setPathEffect(effects);
197         canvas.drawPath(path3, paint);
198 
199         /*画弧线*/
200         paint.setPathEffect(oldEffect);
201         canvas.drawText("画弧线:", 10, 124, paint);
202         
203         RectF oval1 = new RectF(170, 114, 190, 134);    // 弧线是画在矩形中的
204         canvas.drawArc(oval1, 180, 180, false, paint);    // 左眼弧线 ^_^
205         
206         oval1.set(230, 114, 250, 134);
207         canvas.drawArc(oval1, 180, 180, false, paint);    // 右眼弧线 ^_^
208         
209         oval1.set(190, 124, 230, 134);
210         canvas.drawArc(oval1, 0, 180, false, paint);    // 嘴弧线 ^_^
211         
212         /*画贝塞尔曲线*/
213         /* Path类封装复合(多轮廓几何图形的路径
214          * 由直线段*、二次曲线,和三次方曲线,也可画以油画。drawPath(路径、油漆),要么已填充的或抚摸
215          * (基于油漆的风格),或者可以用于剪断或画画的文本在路径。
216          */
217         canvas.drawText("画贝塞尔曲线:", 10, 174, paint);
218         Path path2 = new Path();
219         path2.moveTo(170, 174);                // 设置Path的起点
220         path2.quadTo(400, 120, 450, 600);     // 设置贝塞尔曲线的控制点坐标和终点坐标
221         canvas.drawPath(path2, paint);        // 画出贝塞尔曲线
222 
223         /*画圆*/
224         canvas.drawText("画圆:", 10, 214, paint);    // 画文本
225         canvas.drawCircle(150, 204, 10, paint);        // 小圆
226         paint.setAntiAlias(true);                    // 设置画笔的锯齿效果。true是去除
227         canvas.drawCircle(200, 204, 20, paint);        // 大圆
228 
229         /*画扇形和椭圆*/
230         canvas.drawText("画扇形和椭圆:", 10, 274, paint);
231         /*设置渐变色 这个正方形的颜色是改变的 */
232         Shader mShader = new LinearGradient(0, 0, 200, 244,
233                 new int[] { Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW,
234                         Color.LTGRAY }, null, Shader.TileMode.REPEAT); // 一个材质,打造出一个线性梯度沿著一条线。
235         paint.setShader(mShader);
236         // p.setColor(Color.BLUE);
237 
238         // 画扇形,drawArc第一个参数是RectF:该类是第二个参数是角度的开始,第三个参数是多少度,第四个参数是真的时候画扇形,是假的时候画弧线
239         RectF oval2 = new RectF(170, 244, 250, 320);// 设置个新的长方形,扫描测量
240         canvas.drawArc(oval2, 200, 130, true, paint);
241 
242         // 画椭圆,把oval改一下
243         oval2.set(250, 244,320,274);
244         canvas.drawOval(oval2, paint);
245         
246         /*画矩形*/
247         canvas.drawText("画矩形:", 10, 320, paint);
248         paint.setStyle(Paint.Style.FILL);// 设置填满
249         canvas.drawRect(150, 300, 170, 320, paint);// 正方形
250         canvas.drawRect(180, 300, 250, 320, paint);// 长方形
251 
252         /*画圆角矩形*/
253         canvas.drawText("画圆角矩形:", 10, 360, paint);
254         paint.setStyle(Paint.Style.FILL);// 充满
255         paint.setColor(Color.LTGRAY);
256         paint.setAntiAlias(true);// 设置画笔的锯齿效果
257         RectF oval3 = new RectF(160, 330, 300, 360);// 设置个新的长方形
258         canvas.drawRoundRect(oval3, 20, 15, paint);// 第二个参数是x半径,第三个参数是y半径
259         
260         /*画三角形*/
261         canvas.drawText("画三角形:", 10, 400, paint);
262         // 绘制这个三角形,你可以绘制任意多边形
263         Path path = new Path();
264         path.moveTo(160, 380);// 此点为多边形的起点
265         path.lineTo(300, 380);
266         path.lineTo(200, 430);
267 //        path.lineTo(160, 380);
268         path.close(); // 使这些点构成封闭的多边形,就不用画回到起点 path.lineTo(160, 380); 
269         canvas.drawPath(path, paint);
270 
271         /*画任意多边形,*/
272         paint.setShader(null);
273         canvas.drawText("画任意多边形:", 10, 460, paint);
274         paint.setColor(Color.LTGRAY);
275         paint.setStyle(Paint.Style.STROKE);// 设置空心
276         Path path1 = new Path();
277         path1.moveTo(180, 450);
278         path1.lineTo(300, 450);
279         path1.lineTo(310, 460);
280         path1.lineTo(180, 470);
281         path1.close();        // 封闭形状
282         canvas.drawPath(path1, paint);
283 
284         /*画图片,就是贴图*/
285         canvas.drawText("画图片:", 10, 520, paint);
286         Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
287         canvas.drawBitmap(bitmap, 150, 460, paint);
288         
289         /*画文本*/
290         paint.setColor(Color.BLACK);
291         canvas.drawText("画文本:", 10, 670, paint);
292         paint.setTextSize(txtSize * 3);
293         paint.setStyle(Paint.Style.FILL);
294 
295         FontMetrics fontMetrics = paint.getFontMetrics();
296         float originX = 200;
297         float originY = 700;
298         float topY = originY + fontMetrics.top;
299         float ascentY = originY + fontMetrics.ascent;
300         float descentY = originY + fontMetrics.descent;
301         float bottomY = originY + fontMetrics.bottom;
302         float leading = fontMetrics.leading;
303         
304         //文本
305         paint.setColor(Color.RED);
306         paint.setTextAlign(Align.LEFT);
307         canvas.drawText("text1", originX , originY, paint);
308         
309         //origin point
310         canvas.drawCircle(originX, originY, 5, paint);
311         paint.setTextAlign(Align.LEFT);
312 
313         //baseline
314         paint.setColor(Color.LTGRAY);
315         paint.setTextSize(txtSize);
316         canvas.drawText("baseline", originX - 100 , originY, paint);
317         canvas.drawLine(originX, originY, originX + 140, originY, paint);
318         
319         //top line
320         paint.setColor(Color.GREEN);
321         canvas.drawText("topline", originX - 80, topY, paint);
322         canvas.drawLine(originX, topY, originX + 100, topY, paint);
323         
324         //ascent line
325         paint.setColor(Color.CYAN);
326         canvas.drawText("ascent line", originX + 155, ascentY, paint);
327         canvas.drawLine(originX+50, ascentY, originX + 150, ascentY, paint);
328         
329         //descent line
330         paint.setColor(Color.YELLOW);
331         canvas.drawText("descent line", originX + 140, descentY, paint);
332         canvas.drawLine(originX+30, descentY, originX + 139, descentY, paint);
333         
334         //bottom line
335         paint.setColor(Color.BLUE);
336         canvas.drawText("bottom line", originX - 155, descentY, paint);
337         canvas.drawLine(originX-30, bottomY, originX + 110, bottomY, paint);
338     }
339     
340     @Override
341     protected void onDraw(Canvas canvas) {
342         drawSample(canvas);
343 //        canvas.drawBitmap(bitmapForCache, 0,0, paint);
344 //        
345 //        canvas.save();
346 //        
347 //        int viewHeight = getHeight();
348 //        int sectionHeight = viewHeight / alphabet.length();
349 //        int diff = viewHeight - sectionHeight * alphabet.length();
350 //        
351 //        paint.setStrokeWidth(3);
352 //        paint.setColor(Color.RED);
353 //        canvas.drawPoint(0,0, paint);
354 //
355 //        paint.setColor(alphabetTxtColor);
356 //        baseline = sectionHeight + diff/2;
357 ////        canvas.drawLine(0, baseline, getWidth(), baseline, paint);
358 //        paint.setTextSize(sectionHeight);
359 //
360 //        
361 //        for (int i = 0; i < alphabet.length(); ++i){
362 //            if (currentSection == i){
363 //                paint.setColor(alphabetHighlightTxtColor);
364 //            }else{
365 //                paint.setColor(alphabetTxtColor);
366 //            }
367 //            canvas.drawText("" + alphabet.charAt(i), getWidth()/2, baseline  + sectionHeight * i, paint);
368 //        }
369 //        canvas.restore();
370     }
371     public CustomAlphabetFastScrollView(Context context, AttributeSet attrs) {
372         super(context, attrs);
373         init();
374     }
375 }

 

posted @ 2015-12-11 16:39  f9q  阅读(337)  评论(0编辑  收藏  举报