完全自定义控件-简单环形进度条制作

JayHead 8年前
   <p>昨天简单熟悉了下canvas的API,今天来做个小demo巩固下</p>    <p>回顾 <a href="http://www.open-open.com/lib/view/open1472215830501.html" rel="nofollow,noindex">完全自定义控件-Canvas之绘制基本形状</a></p>    <h2>简单环形进度条制作</h2>    <p>本文实现一个自定义的加载进度条,效果如下图所示:</p>    <p><img src="https://simg.open-open.com/show/f6366a891503e027a9cd73f4b62c7301.gif"></p>    <p>效果</p>    <h2>实现步骤:</h2>    <ol>     <li>新建CircleProgressView类继承View</li>     <li> <p>在构造函数中初始化画笔</p> <pre>  <code class="language-java">private void init() {       mPaint = new Paint();       mPaint.setColor(Color.BLACK);       mPaint.setStyle(Paint.Style.STROKE);//绘图为描边模式       mPaint.setStrokeWidth(20);//画笔宽度       mPaint.setAntiAlias(true);//抗锯齿   }</code></pre> </li>     <li> <p>重写onDraw</p> <p>主要逻辑为先绘制一个圆环,然后在它上面根据进度来绘制圆弧</p> <pre>  <code class="language-java">protected void onDraw(Canvas canvas) {       super.onDraw(canvas);       //得到画布一半的宽度       int center = getWidth() / 2;       //定义圆的半径       int radius = 100;       //定义一个圆       mRectF = new RectF(center - radius, center - radius, center + radius, center + radius);       if (!mChanged) {           //设置画笔的颜色           mPaint.setColor(Color.BLUE);           //画一个圆,由于画笔是描边模式,所以展现的是个圆环           canvas.drawCircle(center, center, radius, mPaint);           //设置画笔的颜色           mPaint.setColor(Color.RED);           //绘制圆弧,从12点方向(-90度)开始绘制,偏移角度为进度           canvas.drawArc(mRectF, -90, mProgress, false, mPaint);       } else {           mPaint.setColor(Color.RED);           canvas.drawCircle(center, center, radius, mPaint);           mPaint.setColor(Color.BLUE);           canvas.drawArc(mRectF, -90, mProgress, false, mPaint);       }       //进度更新方法       startProgress();   }</code></pre> <p>进度更新方法</p> <pre>  <code class="language-java">private void startProgress() {       //当view控件可见时,每50毫秒更新一次视图       if (isShown()) {           postDelayed(new Runnable() {               @Override               public void run() {                   mProgress += 10;                   //如果偏移角度超过360,则至为0,并且跟换绘制颜色                   if (mProgress >= 360) {                       mProgress = 0;                       mChanged = !mChanged;                   }                   invalidate();               }           }, 50);       }   }</code></pre> </li>    </ol>    <h2>自定义属性</h2>    <ul>     <li>很明显,我们不可能在代码中写死控件的参数,我们需要提供一些可定制属性,方便在XML布局文件中对控件进行设置。</li>    </ul>    <h3>为控件添加自定义属性的几个步骤。</h3>    <ol>     <li> <p>在values目录下新建一个attrs.xml文件,内容如下:</p> <pre>  <code class="language-java"><?xml version="1.0" encoding="utf-8"?>  <resources>   <declare-styleable name="CircleProgressView">       <attr name="firstColor" format="color"/> <!--圆环颜色-->       <attr name="secondColor" format="color"/> <!--圆环颜色-->       <attr name="circleWidth" format="integer"/><!--色带宽度-->   </declare-styleable>  </resources></code></pre> <p>不同的属性对应不同的format,属性对应的format可以参考</p> <a href="/misc/goto?guid=4959677324871527337" rel="nofollow,noindex">http://blog.csdn.net/pgalxx/article/details/6766677</a></li>     <li> <p>获取属性</p> <p>在CircleProgressView的构造方法中获取布局文件中的属性</p> <pre>  <code class="language-java">//获取TypedArray  context.obtainStyledAttributes(attrs,R.styleable.RoundProgressBar)</code></pre> <p>然后从TypedArray获取我们定义的属性</p> <pre>  <code class="language-java">public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {       super(context, attrs, defStyleAttr);       TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView, defStyleAttr, 0);         //获取自定义属性和默认值       //getColor方法的第一个参数是我们在XML文件中定义的颜色,如果我们没有给我们自定义的View定义颜色,他就会使用第二个参数中的默认值       mFirstColor = ta.getColor(R.styleable.CircleProgressView_firstColor, Color.RED);       mSecondColor = ta.getColor(R.styleable.CircleProgressView_secondColor, Color.BLUE);       mCircleWidth = ta.getDimensionPixelSize(R.styleable.CircleProgressView_circleWidth,               (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics()));         //释放该实例,从而使其可被其他模块复用       ta.recycle();       init();   }</code></pre> </li>     <li> <p>在onDraw()中使用</p> <pre>  <code class="language-java">protected void onDraw(Canvas canvas) {       super.onDraw(canvas);       //得到画布一半的宽度       int center = getWidth() / 4;       //定义圆的半径       int radius = 100;       //定义一个圆       mRectF = new RectF(center - radius, center - radius, center + radius, center + radius);       if (!mChanged) {           //设置画笔的颜色           mPaint.setColor(mFirstColor);           //画一个圆,由于画笔是描边模式,所以展现的是个圆环           canvas.drawCircle(center, center, radius, mPaint);           //设置画笔的颜色           mPaint.setColor(mSecondColor);           //绘制圆弧,从12点方向(-90度)开始绘制,偏移角度为进度           canvas.drawArc(mRectF, -90, mProgress, false, mPaint);       } else {           mPaint.setColor(mSecondColor);           canvas.drawCircle(center, center, radius, mPaint);           mPaint.setColor(mFirstColor);           canvas.drawArc(mRectF, -90, mProgress, false, mPaint);       }       //进度更新方法       startProgress();   }</code></pre> </li>     <li> <p>在布局中使用</p> <p>第二个控件使用了自定义属性</p> <pre>  <code class="language-java"><?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="zhj.progressbardemo.MainActivity">     <zhj.progressbardemo.CircleProgressView       android:layout_width="match_parent"       android:layout_height="259dp"       />     <zhj.progressbardemo.CircleProgressView       android:layout_width="match_parent"       android:layout_height="wrap_content"       android:layout_marginTop="50dp"       app:circleWidth="30dp"       app:firstColor="#f58a47"       app:secondColor="#5be9d8"       />  </LinearLayout></code></pre> <p>效果展示</p> </li>    </ol>    <p><img src="https://simg.open-open.com/show/b3db479bf7a475d0f0d5fb8e4aae8c8a.gif"></p>    <p>效果</p>    <p>这里是 <a href="/misc/goto?guid=4959677324964492761" rel="nofollow,noindex">项目地址</a></p>    <p>参考</p>    <p><a href="/misc/goto?guid=4959677325058312931" rel="nofollow,noindex">https://segmentfault.com/a/1190000004624339</a></p>    <p><a href="/misc/goto?guid=4959677325147416344" rel="nofollow,noindex">http://blog.csdn.net/lmj623565791/article/details/24500107</a></p>    <p> </p>    <p>来自:http://www.jianshu.com/p/dfa2d62311ff</p>    <p> </p>