博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android 自定义控件 (二) 初步认识
阅读量:4352 次
发布时间:2019-06-07

本文共 6482 字,大约阅读时间需要 21 分钟。

  最近一直在忙项目,也在不断的面试,每次问道这个自定义控件,好多人云里雾绕的,今天就这个机会,简单做个完全自定义控件的入门吧。上一篇讲了继承已有控件的过程,发现我们只是简答的在封装的布局里操作,并没有重写onDraw,onMeasure,onLayout这些方法。其实继承控件这种形式基本能满足我们大部分的功能,但对于现有控件无法满足的怎么办,那就让我们重写上述三个方法,自己写特定需求的控件。完全自定义控件一般有两种,一种继承View,一种继承Viewgroup。根据view树结构,我们知道Viewgroup可以包含view,也可以包含viewgroup。View也可以包含Viewgroup。不能一看到Viewgroup,望文生义。今天先以一个简单的例子,来打开完全自定义之门。

经常在项目中遇到进度条的问题,比如圆形进度条,显示百分比进度等。请看代码。

 

1.分析:

从图中我们看到,分三个部分:大圆,红色的进度,中间的文字。而圆形还有一定的宽度,颜色,进度显示也有颜色,文字有颜色,同时还有大小等细节。

2.实现思路:

刚才说到字体大小等细节,这些可以作为属性,绘制大圆,文字,进度等可以在onDraw里重绘(画圆用到drawCircle,绘制文字用到drawText,进度用到drawArc),自定义view就完全自己来嘛。

3.额外的细节(添加监听等):

上述绘制完view暂时还是精致的,想动起来,需要不断的更新进度,不断刷新重绘view。这时候就用到了invalidate()或postinvalidate();当invalidate()方法调用时会重新调用onDraw() 方法。当进度达到100%时,还要有个回调,执行完毕等。针对其他的自定义我们可能还要重新onTouchEvent,onSroll等触摸,滑动等,这样才算是一个完整的控件。

 

好了,基本的思路都告诉大家了。以后无外乎就这几个思路。重要的还是把自己掌握的技能融会贯通,多练。下面就看实现代码吧:

(1)values里的attrs代码

(2)自定义控件核心代码

1 public class CircleView extends View  {  2   3     private int mCirlceViewColor;  4     private int mCirlceViweProgressColor;  5     private  int mProgress;  6     private float mTextSize;  7     private int mTextColor;  8     private  int mStyle;  9     private  float mRoudWidth; 10     private  int  max; 11     private Paint mPaint ; 12  13     private  static final int STROKE = 0; 14     private  static final int FILL = 1; 15  16     public CircleView(Context context) { 17         this(context, null); 18     } 19  20     public CircleView(Context context, AttributeSet attrs) { 21         this(context, attrs, 0); 22     } 23  24     public CircleView(Context context, AttributeSet attrs, int defStyleAttr) { 25         super(context, attrs, defStyleAttr); 26         mPaint = new Paint(); 27  28         TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleView); 29         mCirlceViewColor = array.getColor(R.styleable.CircleView_roundColor, Color.BLACK); 30         mCirlceViweProgressColor = array.getColor(R.styleable.CircleView_roundProgressColor,Color.RED); 31         mTextColor = array.getColor(R.styleable.CircleView_textColor,Color.BLUE); 32         mTextSize = array.getDimension(R.styleable.CircleView_textSize,40); 33         mRoudWidth = array.getDimension(R.styleable.CircleView_roundWidth,6); 34         max = array.getInteger(R.styleable.CircleView_max,100); 35         mStyle = array.getInt(R.styleable.CircleView_style, 0); 36  37         array.recycle(); 38     } 39  40     @Override 41     protected void onDraw(Canvas canvas) { 42         super.onDraw(canvas); 43  44         /** 45          * 先画圆,直接使用draw Circle 46          * Draw the specified circle using the specified paint. If radius is <= 0, 47          * then nothing will be drawn. The circle will be filled or framed based 48          * on the Style in the paint. 49          * 50           public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) 51          * @param cx     The x-coordinate of the center of the cirle to be drawn 52          * @param cy     The y-coordinate of the center of the cirle to be drawn 53          * @param radius The radius of the cirle to be drawn 54          * @param paint  The paint used to draw the circle 55          */ 56  57         int cx = getWidth()/2; 58  59         int radius =(int) (cx -mRoudWidth/2);//设置圆环的半径 60         mPaint.setColor(mCirlceViewColor); //设置圆环的颜色 61         mPaint.setStyle(Paint.Style.STROKE); //设置空心 62         mPaint.setStrokeWidth(mRoudWidth); //设置圆环的宽度 63         mPaint.setAntiAlias(true);  //消除锯齿 64         canvas.drawCircle(cx,cx,radius,mPaint); 65  66  67         /** 68          * 有了外层的圆,现在绘制圆内的文字.使用drawText 69  70          * Draw the text, with origin at (x,y), using the specified paint. The 71          * origin is interpreted based on the Align setting in the paint. 72          * 73          public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) 74          * @param text  The text to be drawn 75          * @param x     The x-coordinate of the origin of the text being drawn 76          * @param y     The y-coordinate of the baseline of the text being drawn 77          * @param paint The paint used for the text (e.g. color, size, style) 78          */ 79  80         mPaint.setStrokeWidth(0); 81         mPaint.setColor(mTextColor); 82         mPaint.setTextSize(mTextSize); 83         int percent = (int)(((float)mProgress/(float) max) *100); 84         float textWidth  = mPaint.measureText (percent+"%"); 85         canvas.drawText(percent+"%",cx-textWidth/2,cx+mTextSize/2,mPaint); 86  87         /** 88          * 画圆弧 ,画圆环的进度 89          */ 90  91         mPaint.setStrokeWidth(mRoudWidth); //设置圆环的宽度 92         mPaint.setColor(mCirlceViweProgressColor);  //设置进度的颜色 93         RectF oval = new RectF(cx - radius, cx - radius, cx 94                 + radius, cx + radius);  //用于定义的圆弧的形状和大小的界限 95  96         switch (mStyle) { 97             case STROKE:{ 98                 mPaint.setStyle(Paint.Style.STROKE); 99                 canvas.drawArc(oval, 0, 360 * mProgress / max, false, mPaint);  //根据进度画圆弧100                 break;101             }102             case FILL:{103                 mPaint.setStyle(Paint.Style.FILL_AND_STROKE);104                 if(mProgress !=0)105                     canvas.drawArc(oval, 0, 360 * mProgress / max, true, mPaint);  //根据进度画圆弧106                 break;107             }108         }109     }110 111     public  void  setProgress(int progress){112         this.mProgress = progress;113     }114 115     private  int getProgress(){116         return this.mProgress;117 118 119     }120 121     private  void setMax(int max){122         this.max = max;123     }124     private  int getMax(){125         return  max;126     }
View Code

说明几个点:

a.public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint)的几个参数

cx和cy是圆心坐标,这个圆心坐标是相对当前绘制的圆心大小的,x和y,而不是屏幕左上角的。

radius是半径,paint是当前的所持有的画笔。

b.public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint)

x:是文本内容最开始绘制的位置。在此view中可以看出应该是(中心点的x-文字宽度的/2)

y是基线的值。在view中应该是中心点的y+文字大小/2.

 

(3)监听事件的添加如下

上述只是个初步重写view的大致过程,实际项目中更复杂的自定义,设计的内容会则会更加庞大,比如滑动效果,比如事件分发,比如点击事件等等。接下来就从view 的基本知识点讲起,逐步完成一个复杂的自定义view。敬请期待,当然我的博客都比较简单,旨在给大家提供一个思路。后续我会把我的心得转成代码形式放到github上,希望能帮到大家。

 

转载于:https://www.cnblogs.com/javawing-android/p/5660506.html

你可能感兴趣的文章
linux 系统运行级别一般为 0-6,请分别写出每个级别的含义
查看>>
支撑千万级,大型电商分布式架构解析
查看>>
全景图转局部平面视图原理详解
查看>>
初入PHP,(for循环~水仙花数)
查看>>
flask表单flask-wtf
查看>>
【转】RDO、SAD、SATD、λ
查看>>
百度地图通过IP定位附近城市
查看>>
同步异步 阻塞非阻塞
查看>>
2019春第九周作业
查看>>
初等函数定义
查看>>
NamedParameterJdbcTemplate常用方法总结
查看>>
synchronized 锁优化
查看>>
XLUA
查看>>
较正规的CSS层叠样式表命名参考表
查看>>
mysql数据库的增删改
查看>>
Vue中使用axios如何解决跨域问题
查看>>
Eclipse中导入外部jar包步骤
查看>>
基本控件文档-UIButton属性
查看>>
poj1065
查看>>
(C#) VS类视图和对象浏览器图标
查看>>