300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Android 高手进阶之自定义View 自定义属性(带进度的圆形进度条)

Android 高手进阶之自定义View 自定义属性(带进度的圆形进度条)

时间:2022-07-26 22:04:01

相关推荐

Android 高手进阶之自定义View 自定义属性(带进度的圆形进度条)

转载请注明地址:/xiaanming/article/details/10298163

很多的时候,系统自带的View满足不了我们功能的需求,那么我们就需要自己来自定义一个能满足我们需求的View,自定义View我们需要先继承View,添加类的构造方法,重写父类View的一些方法,例如onDraw,为了我们自定义的View在一个项目中能够重用,有时候我们需要自定义其属性,举个很简单的例子,我在项目中的多个界面使用我自定义的View,每个界面该自定义View的颜色都不相同,这时候如果没有自定义属性,那我们是不是需要构建不同颜色的View出来呢,这样子我们的代码就会显得很沉厄,所以这时候我们就需要自定义其属性来满足我们不同的需求,自定义属性呢,我们需要在values下建立attrs.xml文件,在其中定义我们需要定义的属性,然后在自定义View中也要做相对应的修改,我们还是用一个小例子来看看自定义View和自定义属性的使用

今天带大家来自己定义一个带进度的圆形进度条,我们还是先看一下效果吧

从上面可以看出,我们可以自定义圆环的颜色,圆环进度的颜色,是否显示进度的百分比,进度百分比的颜色,以及进度是实心还是空心等等,这样子是不是很多元化很方便呢?接下来我们就来教大家怎么来定义

1.在values下面新建一个attrs.xml,现在里面定义我们的属性,不同的属性对应不同的format,属性对应的format可以参考/pgalxx/article/details/6766677,介绍的还是比较详细,接下来我贴上我在自定义这个进度条所用到的属性

[html]view plaincopy <?xmlversion="1.0"encoding="UTF-8"?><resources><declare-styleablename="RoundProgressBar"><attrname="roundColor"format="color"/><attrname="roundProgressColor"format="color"/><attrname="roundWidth"format="dimension"></attr><attrname="textColor"format="color"/><attrname="textSize"format="dimension"/><attrname="max"format="integer"></attr><attrname="textIsDisplayable"format="boolean"></attr><attrname="style"><enumname="STROKE"value="0"></enum><enumname="FILL"value="1"></enum></attr></declare-styleable></resources>

2.自定义View的属性我们算是定义好了,接下来就是怎么获取属性和代码的编写了,我们需要在构造方法中获取我们自己定义的相关属性,我们先调用context.obtainStyledAttributes(attrs,R.styleable.RoundProgressBar)来获取TypedArray,然后从TypedArray获取我们定义的属性,例如

[java]view plaincopy roundColor=mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor,Color.RED);roundProgressColor=mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor,Color.GREEN);textColor=mTypedArray.getColor(R.styleable.RoundProgressBar_textColor,Color.GREEN);textSize=mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize,15);roundWidth=mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth,5);max=mTypedArray.getInteger(R.styleable.RoundProgressBar_max,100);textIsDisplayable=mTypedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable,true);style=mTypedArray.getInt(R.styleable.RoundProgressBar_style,0);

上面的代码中,如roundColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.RED); getColor方法的第一个参数是我们在XML文件中定义的颜色,如果我们没有给我们自定义的View定义颜色,他就会使用第二个参数中的默认值,即Color.RED

3.为了方便大家理解,我将自定义View的全部代码贴出来,里面的代码我也有详细的注释

[java]view plaincopy packagecom.example.roundprogressbar;importandroid.content.Context;importandroid.content.res.TypedArray;importandroid.graphics.Canvas;importandroid.graphics.Color;importandroid.graphics.Paint;importandroid.graphics.RectF;importandroid.graphics.Typeface;importandroid.util.AttributeSet;importandroid.util.Log;importandroid.view.View;importcom.example.circlepregress.R;/***仿iphone带进度的进度条,线程安全的View,可直接在线程中更新进度*@authorxiaanming**/publicclassRoundProgressBarextendsView{/***画笔对象的引用*/privatePaintpaint;/***圆环的颜色*/privateintroundColor;/***圆环进度的颜色*/privateintroundProgressColor;/***中间进度百分比的字符串的颜色*/privateinttextColor;/***中间进度百分比的字符串的字体*/privatefloattextSize;/***圆环的宽度*/privatefloatroundWidth;/***最大进度*/privateintmax;/***当前进度*/privateintprogress;/***是否显示中间的进度*/privatebooleantextIsDisplayable;/***进度的风格,实心或者空心*/privateintstyle;publicstaticfinalintSTROKE=0;publicstaticfinalintFILL=1;publicRoundProgressBar(Contextcontext){this(context,null);}publicRoundProgressBar(Contextcontext,AttributeSetattrs){this(context,attrs,0);}publicRoundProgressBar(Contextcontext,AttributeSetattrs,intdefStyle){super(context,attrs,defStyle);paint=newPaint();TypedArraymTypedArray=context.obtainStyledAttributes(attrs,R.styleable.RoundProgressBar);//获取自定义属性和默认值roundColor=mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor,Color.RED);roundProgressColor=mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor,Color.GREEN);textColor=mTypedArray.getColor(R.styleable.RoundProgressBar_textColor,Color.GREEN);textSize=mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize,15);roundWidth=mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth,5);max=mTypedArray.getInteger(R.styleable.RoundProgressBar_max,100);textIsDisplayable=mTypedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable,true);style=mTypedArray.getInt(R.styleable.RoundProgressBar_style,0);mTypedArray.recycle();}@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);/***画最外层的大圆环*/intcentre=getWidth()/2;//获取圆心的x坐标intradius=(int)(centre-roundWidth/2);//圆环的半径paint.setColor(roundColor);//设置圆环的颜色paint.setStyle(Paint.Style.STROKE);//设置空心paint.setStrokeWidth(roundWidth);//设置圆环的宽度paint.setAntiAlias(true);//消除锯齿canvas.drawCircle(centre,centre,radius,paint);//画出圆环Log.e("log",centre+"");/***画进度百分比*/paint.setStrokeWidth(0);paint.setColor(textColor);paint.setTextSize(textSize);paint.setTypeface(Typeface.DEFAULT_BOLD);//设置字体intpercent=(int)(((float)progress/(float)max)*100);//中间的进度百分比,先转换成float在进行除法运算,不然都为0floattextWidth=paint.measureText(percent+"%");//测量字体宽度,我们需要根据字体的宽度设置在圆环中间if(textIsDisplayable&&percent!=0&&style==STROKE){canvas.drawText(percent+"%",centre-textWidth/2,centre+textSize/2,paint);//画出进度百分比}/***画圆弧,画圆环的进度*///设置进度是实心还是空心paint.setStrokeWidth(roundWidth);//设置圆环的宽度paint.setColor(roundProgressColor);//设置进度的颜色RectFoval=newRectF(centre-radius,centre-radius,centre+radius,centre+radius);//用于定义的圆弧的形状和大小的界限switch(style){caseSTROKE:{paint.setStyle(Paint.Style.STROKE);canvas.drawArc(oval,0,360*progress/max,false,paint);//根据进度画圆弧break;}caseFILL:{paint.setStyle(Paint.Style.FILL_AND_STROKE);if(progress!=0)canvas.drawArc(oval,0,360*progress/max,true,paint);//根据进度画圆弧break;}}}publicsynchronizedintgetMax(){returnmax;}/***设置进度的最大值*@parammax*/publicsynchronizedvoidsetMax(intmax){if(max<0){thrownewIllegalArgumentException("maxnotlessthan0");}this.max=max;}/***获取进度.需要同步*@return*/publicsynchronizedintgetProgress(){returnprogress;}/***设置进度,此为线程安全控件,由于考虑多线的问题,需要同步*刷新界面调用postInvalidate()能在非UI线程刷新*@paramprogress*/publicsynchronizedvoidsetProgress(intprogress){if(progress<0){thrownewIllegalArgumentException("progressnotlessthan0");}if(progress>max){progress=max;}if(progress<=max){this.progress=progress;postInvalidate();}}publicintgetCricleColor(){returnroundColor;}publicvoidsetCricleColor(intcricleColor){this.roundColor=cricleColor;}publicintgetCricleProgressColor(){returnroundProgressColor;}publicvoidsetCricleProgressColor(intcricleProgressColor){this.roundProgressColor=cricleProgressColor;}publicintgetTextColor(){returntextColor;}publicvoidsetTextColor(inttextColor){this.textColor=textColor;}publicfloatgetTextSize(){returntextSize;}publicvoidsetTextSize(floattextSize){this.textSize=textSize;}publicfloatgetRoundWidth(){returnroundWidth;}publicvoidsetRoundWidth(floatroundWidth){this.roundWidth=roundWidth;}}

4.通过上面几步我们就实现了自定义View,和自定义View的属性,当然使用过程中还是有一点变化,我们必须在界面布局的最顶层加上

xmlns:android_custom="/apk/res/com.example.circlepregress"这个即命名空间,

红色部分是自定义属性的前缀,什么意思呢?对于android系统控件我们定义其控件属性是用android:XXX="XXXXXXX",而我们自己定义的就用android_custom:XXX = "XXXXXX"绿色部分则是我们的包的名字

通过上面这两步我们就能自己定义属性了,我贴出自定义View在XML中使用情况

[java]view plaincopy <RelativeLayoutxmlns:android="/apk/res/android"xmlns:android_custom="/apk/res/com.example.circlepregress"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"><com.example.roundprogressbar.RoundProgressBarandroid:id="@+id/roundProgressBar2"android:layout_width="80dip"android:layout_height="80dip"android:layout_alignLeft="@+id/roundProgressBar1"android:layout_alignParentBottom="true"android:layout_marginBottom="78dp"android_custom:roundColor="#D1D1D1"android_custom:roundProgressColor="@android:color/black"android_custom:textColor="#9A32CD"android_custom:textIsDisplayable="false"android_custom:roundWidth="10dip"android_custom:textSize="18sp"/></RelativeLayout>

今天就到此结束,如果大家有什么疑问,请留言,我会及时回复大家的

项目源码,点击下载

from:/xiaanming/article/details/10298163

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。