怎么在Android中通过自定义View实现渐变色进度条(android,view,移动开发)

时间:2024-05-05 02:02:15 作者 : 石家庄SEO 分类 : 移动开发
  • TAG :

效果分解:

1.渐变色,看起来颜色变化并不复杂,使用LinearGradient应该可以实现。
2.圆头,无非是画两个圆,外圆使用渐变色的颜色,内圆固定为白色。
3.灰底,还没有走到的进度部分为灰色。
4.进度值,使用文本来显示;
5.弧形的头部,考虑使用直线进行连接,或者使用曲线,例如贝塞尔曲线;

我首先初步实现了进度条的模样,发现样子有了,却不太美观。
反思了一下,我只是个写代码的,对于哪种比例比较美观,是没有清晰的认识的,所以,还是参考原图吧。

然后就进行了精细的测量:

将图像放大4倍,进行测量,然后获取到各部分的比例关系,具体过程就不细说了,说一下测量结果(按比例的):

视图总长300,其中前面留空5,进度长258,然后再留空5,显示文本占26,后面留空6;

高度分为4个:
外圆:10
字高:9
内圆:6
线粗:5
考虑上下各留空10,则视图的高度为30。

考虑到视图整体的效果,可以由用户来设置长度值与高度值,按比例取最小值来进行绘图。
首先计算出一个单位的实际像素数,各部分按比例来显示即可。

还有一个弧形的头部,是怎么实现的呢?
在放大之后,能看出来图形比较简单,看不出有弧度,那么,使用一小段直线连接就可以了。
估算这小段直线:线粗为2,呈30度角,长为8-10即可,连接直线与弧顶,起点在弧顶之左下方。
注意:在进度的起点时,不能画出。避免出现一个很突兀的小尾巴。在2%进度之后,才开始画。

在文字的绘制过程中,遇到一个小问题,就是文字不居中,略微偏下,上网查了下,原因是这样的:我们绘制文本时,使用的这个函数:canvas.drawText(“30%”, x, y, paint);
其中的参数 y 是指字符串baseline的的位置,不是文本的中心。通过计算可以调整为居中,如下:

//计算坐标使文字居中FontMetricsfontMetrics=mPaint.getFontMetrics();floatfontHeight=fontMetrics.bottom-fontMetrics.top;floatbaseY=height/2+fontHeight/2-fontMetrics.bottom;

按比例来绘制之后,就确实是原来那个修长优雅的感觉了。
实际运行后,发现字体偏小,不太适合竖屏观看,调大了些。

另外对于参数,做了如下几个自定义属性:
前景色:开始颜色,结束颜色;
进度条未走到时的默认颜色,
字体颜色。

属性xml如下:

<?xmlversion="1.0"encoding="utf-8"?><resources><attrname="startColor"format="color"/><attrname="endColor"format="color"/><attrname="backgroundColor"format="color"/><attrname="textColor"format="color"/><declare-styleablename="GoodProgressView"><attrname="startColor"/><attrname="endColor"/><attrname="backgroundColor"/><attrname="textColor"/></declare-styleable></resources>

自定义View文件:

packagecom.customview.view;importandroid.content.Context;importandroid.content.res.TypedArray;importandroid.graphics.Canvas;importandroid.graphics.Color;importandroid.graphics.LinearGradient;importandroid.graphics.Paint;importandroid.graphics.Shader;importandroid.graphics.Paint.Cap;importandroid.graphics.Paint.FontMetrics;importandroid.graphics.Paint.Style;importandroid.util.AttributeSet;importandroid.util.Log;importandroid.view.View;importcom.customview.R;publicclassGoodProgressViewextendsView{privateint[]mColors={Color.RED,Color.MAGENTA};//进度条颜色(渐变色的2个点)privateintbackgroundColor=Color.GRAY;//进度条默认颜色privateinttextColor=Color.GRAY;//文本颜色privatePaintmPaint;//画笔privateintprogressValue=0;//进度值//privateRectFrect;//绘制范围publicGoodProgressView(Contextcontext,AttributeSetattrs){this(context,attrs,0);}publicGoodProgressView(Contextcontext){this(context,null);}//获得我自定义的样式属性publicGoodProgressView(Contextcontext,AttributeSetattrs,intdefStyle){super(context,attrs,defStyle);//获得我们所定义的自定义样式属性TypedArraya=context.getTheme().obtainStyledAttributes(attrs,R.styleable.GoodProgressView,defStyle,0);intn=a.getIndexCount();for(inti=0;i<n;i++){intattr=a.getIndex(i);switch(attr){caseR.styleable.GoodProgressView_startColor://渐变色之起始颜色,默认设置为红色mColors[0]=a.getColor(attr,Color.RED);break;caseR.styleable.GoodProgressView_endColor://渐变色之结束颜色,默认设置为品红mColors[1]=a.getColor(attr,Color.MAGENTA);break;caseR.styleable.GoodProgressView_backgroundColor://进度条默认颜色,默认设置为灰色backgroundColor=a.getColor(attr,Color.GRAY);break;caseR.styleable.GoodProgressView_textColor://文字颜色,默认设置为灰色textColor=a.getColor(attr,Color.GRAY);break;}}a.recycle();mPaint=newPaint();progressValue=0;}publicvoidsetProgressValue(intprogressValue){if(progressValue>100){progressValue=100;}this.progressValue=progressValue;Log.i("customView","log:progressValue="+progressValue);}publicvoidsetColors(int[]colors){mColors=colors;}@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){intwidth=0;intheight=0;/***设置宽度*/intspecMode=MeasureSpec.getMode(widthMeasureSpec);intspecSize=MeasureSpec.getSize(widthMeasureSpec);switch(specMode){caseMeasureSpec.EXACTLY://明确指定了width=specSize;break;caseMeasureSpec.AT_MOST://一般为WARP_CONTENTwidth=getPaddingLeft()+getPaddingRight();break;}/***设置高度*/specMode=MeasureSpec.getMode(heightMeasureSpec);specSize=MeasureSpec.getSize(heightMeasureSpec);switch(specMode){caseMeasureSpec.EXACTLY://明确指定了height=specSize;break;caseMeasureSpec.AT_MOST://一般为WARP_CONTENTheight=width/10;break;}Log.i("customView","log:w="+width+"h="+height);setMeasuredDimension(width,height);}@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);intmWidth=getMeasuredWidth();intmHeight=getMeasuredHeight();//按比例计算进度条各部分的值floatunit=Math.min(((float)mWidth)/300,((float)mHeight)/30);floatlineWidth=5*unit;//线粗floatinnerCircleDiameter=6*unit;//内圆直径floatouterCircleDiameter=10*unit;//外圆直径floatwordHeight=12*unit;//字高//9*unit//floatwordWidth=26*unit;//字长floatoffsetLength=5*unit;//留空//floatwidth=300*unit;//绘画区域的长度floatheight=30*unit;//绘画区域的高度floatprogressWidth=258*unit;//绘画区域的长度mPaint.setAntiAlias(true);mPaint.setStrokeWidth((float)lineWidth);mPaint.setStyle(Style.STROKE);mPaint.setStrokeCap(Cap.ROUND);mPaint.setColor(Color.TRANSPARENT);floatoffsetHeight=height/2;floatoffsetWidth=offsetLength;floatsection=((float)progressValue)/100;if(section>1)section=1;intcount=mColors.length;int[]colors=newint[count];System.arraycopy(mColors,0,colors,0,count);//底部灰色背景,指示进度条总长度mPaint.setShader(null);mPaint.setColor(backgroundColor);canvas.drawLine(offsetWidth+section*progressWidth,offsetHeight,offsetWidth+progressWidth,offsetHeight,mPaint);//设置渐变色区域LinearGradientshader=newLinearGradient(0,0,offsetWidth*2+progressWidth,0,colors,null,Shader.TileMode.CLAMP);mPaint.setShader(shader);//画出渐变色进度条canvas.drawLine(offsetWidth,offsetHeight,offsetWidth+section*progressWidth,offsetHeight,mPaint);//渐变色外圆mPaint.setStrokeWidth(1);mPaint.setStyle(Paint.Style.FILL);canvas.drawCircle(offsetWidth+section*progressWidth,offsetHeight,outerCircleDiameter/2,mPaint);//绘制两条斜线,使外圆到进度条的连接更自然if(section*100>1.8){mPaint.setStrokeWidth(2*unit);canvas.drawLine(offsetWidth+section*progressWidth-6*unit,offsetHeight-(float)1.5*unit,offsetWidth+section*progressWidth-1*unit,offsetHeight-(float)3.8*unit,mPaint);canvas.drawLine(offsetWidth+section*progressWidth-6*unit,offsetHeight+(float)1.5*unit,offsetWidth+section*progressWidth-1*unit,offsetHeight+(float)3.8*unit,mPaint);}//白色内圆mPaint.setShader(null);mPaint.setColor(Color.WHITE);canvas.drawCircle(offsetWidth+section*progressWidth,offsetHeight,innerCircleDiameter/2,mPaint);//白色内圆//绘制文字--百分比mPaint.setStrokeWidth(2*unit);mPaint.setColor(textColor);mPaint.setTextSize(wordHeight);//计算坐标使文字居中FontMetricsfontMetrics=mPaint.getFontMetrics();floatfontHeight=fontMetrics.bottom-fontMetrics.top;floatbaseY=height/2+fontHeight/2-fontMetrics.bottom;canvas.drawText(""+progressValue+"%",progressWidth+2*offsetWidth,baseY,mPaint);//略微偏下,baseline}}

主xml:

放了两个进度条,一个使用默认值,一个设置了进度条默认颜色与字体颜色:

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:custom="http://schemas.android.com/apk/res/com.customview"android:layout_width="match_parent"android:layout_height="match_parent"><com.customview.view.GoodProgressViewandroid:id="@+id/good_progress_view1"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="10dp"/><com.customview.view.GoodProgressViewandroid:id="@+id/good_progress_view2"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerInParent="true"custom:backgroundColor="#ffcccccc"custom:textColor="#ff000000"android:padding="10dp"/></RelativeLayout>

Activity文件:

一个使用默认渐变色效果,一个的渐变色使用随机颜色,这样每次运行效果不同,比较有趣一些,另外我们也可以从随机效果中找到比较好的颜色组合。进度的变化,是使用了一个定时器来推进。

packagecom.customview;importandroid.os.Bundle;importandroid.os.Handler;importandroid.os.Message;importandroid.util.Log;importandroid.view.WindowManager;importjava.util.Random;importjava.util.Timer;importjava.util.TimerTask;importcom.customview.view.GoodProgressView;importandroid.app.Activity;importandroid.graphics.Color;publicclassMainActivityextendsActivity{GoodProgressViewgood_progress_view1;GoodProgressViewgood_progress_view2;intprogressValue=0;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉信息栏setContentView(R.layout.activity_main);good_progress_view1=(GoodProgressView)findViewById(R.id.good_progress_view1);good_progress_view2=(GoodProgressView)findViewById(R.id.good_progress_view2);//第一个进度条使用默认进度颜色,第二个指定颜色(随机生成)good_progress_view2.setColors(randomColors());timer.schedule(task,1000,1000);//1s后执行task,经过1s再次执行}Handlerhandler=newHandler(){publicvoidhandleMessage(Messagemsg){if(msg.what==1){Log.i("log","handler:progressValue="+progressValue);//通知view,进度值有变化good_progress_view1.setProgressValue(progressValue*2);good_progress_view1.postInvalidate();good_progress_view2.setProgressValue(progressValue);good_progress_view2.postInvalidate();progressValue+=1;if(progressValue>100){timer.cancel();}}super.handleMessage(msg);};};privateint[]randomColors(){int[]colors=newint[2];Randomrandom=newRandom();intr,g,b;for(inti=0;i<2;i++){r=random.nextInt(256);g=random.nextInt(256);b=random.nextInt(256);colors[i]=Color.argb(255,r,g,b);Log.i("customView","log:colors["+i+"]="+Integer.toHexString(colors[i]));}returncolors;}Timertimer=newTimer();TimerTasktask=newTimerTask(){@Overridepublicvoidrun(){//需要做的事:发送消息Messagemessage=newMessage();message.what=1;handler.sendMessage(message);}};}

最终效果如下:

竖屏时:

怎么在Android中通过自定义View实现渐变色进度条

横屏时:

怎么在Android中通过自定义View实现渐变色进度条

Android是什么

Android是一种基于Linux内核的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由美国Google公司和开放手机联盟领导及开发。

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:怎么在Android中通过自定义View实现渐变色进度条的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:eclipse下怎么搭建hibernate5.0环境下一篇:

5 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18