完全自定义控件-简单环形进度条制作
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>