Android 自定义View,自定义属性--自定义圆形进度条(整理)
很多的時候,系統自帶的View滿足不了我們的功能需求,那么我們就需要自定義View來滿足我們的需求
自定義View時要先繼承View,添加類的構造方法,重寫父類View的一些方法,例如onDraw,為了使我們自定義的View在一個項目中能夠重用,有時候我們需要自定義其屬性,舉個很簡單的例子,我在項目中的多個界面使用我自定義的View,每個界面該自定義View的顏色都不相同,這時候如果沒有自定義屬性,那我們是不是需要構建不同顏色的View出來,這樣子我們的代碼就會顯得很冗余,所以這時候我們就需要自定義其屬性來滿足我們不同的需求。
自定義屬性時,我們需要在values下建立attrs.xml文件,在其中定義我們需要定義的屬性,然后在自定義View中也要做相對應的修改。
我們還是用一個小例子來看看自定義View和自定義屬性的使用--帶進度的圓形進度條,我們還是先看一下效果吧
1.在values下面新建一個attrs.xml,在里面定義我們的屬性,不同的屬性對應不同的format,屬性對應的format可以參考http://blog.csdn.net/pgalxx/article/details/6766677,介紹的還是比較詳細,接下來我貼上我在自定義這個進度條所用到的屬性
2.自定義View的屬性定義之后,接下來就是怎么獲取屬性和代碼的編寫了,我們需要在構造方法中獲取我們自己定義的相關屬性,我們先調用context.obtainStyledAttributes(attrs,R.styleable.RoundProgressBar)來獲取TypedArray,然后從TypedArray獲取我們定義的屬性,例如
private void initAttrs(Context context, AttributeSet attrs) {TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.TasksCompletedView, 0, 0);mRadius = typeArray.getDimension(R.styleable.TasksCompletedView_mRadius, 80);mStrokeWidth = typeArray.getDimension(R.styleable.TasksCompletedView_mStrokeWidth, 10);mCircleColor = typeArray.getColor(R.styleable.TasksCompletedView_mCircleColor, 0xFFFFFFFF);mRingColor = typeArray.getColor(R.styleable.TasksCompletedView_mRingColor, 0xFFFFFFFF);mRingRadius = mRadius + mStrokeWidth / 2;}
上面的代碼中,如mCircleColor = typeArray.getColor(
R.styleable.TasksCompletedView_mCircleColor, 0xFFFFFFFF);getColor方法的第一個參數是我們在XML文件中定義的顏色,如果我們沒有給我們自定義的View定義顏色,他就會使用第二個參數中的默認值,即oxFFFFFFFF.
3.為了方便大家理解,我將自定義View的全部代碼貼出來,里面的代碼我也有詳細的注釋
package com.snailws.taskscompleted.activity;import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.FontMetrics; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View;import com.snailws.taskscompleted.R;public class TasksCompletedView extends View {// 畫實心圓的畫筆private Paint mCirclePaint;// 畫圓環的畫筆private Paint mRingPaint;// 畫字體的畫筆private Paint mTextPaint;// 圓形顏色private int mCircleColor;// 圓環顏色private int mRingColor;// 半徑private float mRadius;// 圓環半徑private float mRingRadius;// 圓環寬度private float mStrokeWidth;// 圓心x坐標private int mXCenter;// 圓心y坐標private int mYCenter;// 字的長度private float mProgressTxtWidth;// 字的高度private float mProgressTxtHeight;// 總進度private int mTotalProgress = 100;// 當前進度private int mProgress;public TasksCompletedView(Context context, AttributeSet attrs) {super(context, attrs);// 獲取自定義的屬性initAttrs(context, attrs);initVariable();}private void initAttrs(Context context, AttributeSet attrs) {TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.TasksCompletedView, 0, 0);mRadius = typeArray.getDimension(R.styleable.TasksCompletedView_mRadius, 80);mStrokeWidth = typeArray.getDimension(R.styleable.TasksCompletedView_mStrokeWidth, 10);mCircleColor = typeArray.getColor(R.styleable.TasksCompletedView_mCircleColor, 0xFFFFFFFF);mRingColor = typeArray.getColor(R.styleable.TasksCompletedView_mRingColor, 0xFFFFFFFF);mRingRadius = mRadius + mStrokeWidth / 2;}private void initVariable() {mCirclePaint = new Paint();mCirclePaint.setAntiAlias(true);mCirclePaint.setColor(mCircleColor);mCirclePaint.setStyle(Paint.Style.STROKE);mRingPaint = new Paint();mRingPaint.setAntiAlias(true);mRingPaint.setColor(mRingColor);mRingPaint.setStyle(Paint.Style.STROKE);mRingPaint.setStrokeWidth(mStrokeWidth);mTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setStyle(Paint.Style.FILL);//mTextPaint.setColor(color.black);mTextPaint.setARGB(255, 0, 0, 255);mTextPaint.setTextSize(mRadius / 2);FontMetrics fm = mTextPaint.getFontMetrics();mProgressTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);}RectF oval = new RectF();@Overrideprotected void onDraw(Canvas canvas) {mXCenter = getWidth() / 2;mYCenter = getHeight() / 2;canvas.drawCircle(mXCenter, mYCenter, mRadius, mCirclePaint);if (mProgress > 0) {oval.left = (mXCenter - mRingRadius);oval.top = (mYCenter - mRingRadius);oval.right = mRingRadius * 2 + (mXCenter - mRingRadius);oval.bottom = mRingRadius * 2 + (mYCenter - mRingRadius);canvas.drawArc(oval, -90,((float) mProgress / mTotalProgress) * 360, false,mRingPaint); //String txt = mProgress + "%";mProgressTxtWidth = mTextPaint.measureText(txt, 0, txt.length());canvas.drawText(txt, mXCenter - mProgressTxtWidth / 2, mYCenter+ mProgressTxtHeight / 4, mTextPaint);}}public void setProgress(int progress) {mProgress = progress;// invalidate();postInvalidate();}}4.如何使用該自定義布局
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:tc="http://schemas.android.com/apk/res/com.snailws.taskscompleted"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/white"android:orientation="vertical"tools:context=".MainActivity" ><!-- 自定義控件:圓形進度條 --><com.snailws.taskscompleted.activity.TasksCompletedViewandroid:id="@+id/tasks_view"android:layout_width="fill_parent"android:layout_height="fill_parent"tc:mCircleColor="@color/circle_color"tc:mRadius="100dip"tc:mRingColor="@color/ring_color"tc:mStrokeWidth="20dip" /></LinearLayout>注意:
通過上面幾步我們就實現了自定義View,和自定義View的屬性,當然使用過程中還是有一點變化,我們必須在界面布局的最頂層加上
xmlns:tc="http://schemas.android.com/apk/res/com.snailws.taskscompleted"(如編號1所示)
編號3是自定義屬性的前綴,什么意思呢?對于android系統控件我們定義其控件屬性是用android:XXX="XXXXXXX",而我們自己定義的就用tc:XXX = "XXXXXX"(如編號2 )
編號4則是我們的包名,它是Manifest.xml中的package屬性值,如下圖所示
5,在代碼中使用該自定義控件
package com.snailws.taskscompleted.activity;import android.app.Activity; import android.os.Bundle; import android.view.Window;import com.snailws.taskscompleted.R;public class MainActivity extends Activity {private TasksCompletedView mTasksView;private int mTotalProgress;private int mCurrentProgress;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);initVariable();initView();// 啟動線程new Thread(new ProgressRunable()).start();}private void initVariable() {mTotalProgress = 100;mCurrentProgress = 0;}private void initView() {mTasksView = (TasksCompletedView) findViewById(R.id.tasks_view);}class ProgressRunable implements Runnable {@Overridepublic void run() {while (mCurrentProgress < mTotalProgress) {mCurrentProgress += 1;mTasksView.setProgress(mCurrentProgress);try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}}}}}該項目的目標結構如下:
參考1:自定義漂亮的圓形進度條
參考2:Android 高手進階之自定義View,自定義屬性(帶進度的圓形進度條)
參考3:error: No resource identifier found for attribute ‘backIcon’ in package
總結
以上是生活随笔為你收集整理的Android 自定义View,自定义属性--自定义圆形进度条(整理)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 获取GitHub上远程分支内容
- 下一篇: Android自定义属性,format详