摘要:先看效果原諒我的渣像素,進度的刻度寬度顏色可以隨意設定項目地址實現起來并不難,通過本文,我們可以學到自定義屬性的使用。
先看效果(原諒我的渣像素),進度的刻度、寬度、顏色可以隨意設定:
項目github地址: https://github.com/zhangke301...
實現起來并不難,通過本文,我們可以學到:
1、自定義屬性的使用。
2、shader的使用
3、自定義View中對onmeasure的處理
4、增深對PathMeasure工具類的了解
5、最主要的是對自定義View有個比較清晰的思路認識
做這樣一個進度效果,我們可以拆分如下步驟來實現:
從外部圓環(huán)開始測量繪制;
再加入刻度條效果;
再加入刻度隨進度增加而增加效果;
增加自定義屬性增加可定制性;
控件使用方法介紹
OK,有了這個思路,那我們開始吧:
1、測量繪制外部圓環(huán)
首先我們要開始繪制外部的圓環(huán),這步很簡單,主要是使用canvas的drawArc()方法,
/* * @param oval 畫弧線矩形區(qū)域 * @param startAngle 開始的角度 * @param sweepAngle 劃過的角度 * @param useCenter 如果為true 為實心圓弧 * @param paint 畫筆 * / public void drawArc(RectF oval, float startAngle, float sweepAngle,boolean useCenter,Paint paint)
這個相對簡單,主要是確定開始角度,并不斷增加繪制劃過角度,圓弧就出現在界面中了,這里需要注意的是RectF oval的大小確定:
在確定RectF oval之前,我們要先測量確定當前控件的寬高,根據當前控件的寬高來確定oval的合適大小。
測量當前控件的大小一般我們在onmeasure()方法中處理,resolveMeasured()方法傳遞兩個參數,第一各參數為widthMeasureSpec或者heightMeasureSpec,第二個參數為期望值也就是默認值。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(resolveMeasured(widthMeasureSpec, nDesired), resolveMeasured(heightMeasureSpec, nDesired)); } /** * * @param measureSpec * @param desired * @return */ private int resolveMeasured(int measureSpec, int desired) { int result = 0; int specSize = MeasureSpec.getSize(measureSpec); switch (MeasureSpec.getMode(measureSpec)) { case MeasureSpec.UNSPECIFIED: // result = desired; break; case MeasureSpec.AT_MOST: //wrap-content result = Math.min(specSize, desired); break; case MeasureSpec.EXACTLY: //match-content default: result = specSize; } return result; }
在測量之后我們就可以來求oval的具體大小 ,我把這步操作放在了onSizeChanged方法中,求出最小一邊的一半減去圓環(huán)的寬度,得到圓弧的半徑,然后根據半徑以控件中心為中心繪制我們所需要的矩形區(qū)域。
radiu = (int) ((Math.min(getWidth(), getHeight()))/2-mPaint.getStrokeWidth()); oval.left = getWidth()/2-radiu; oval.top = getHeight()/2-radiu; oval.right = getWidth()/2+radiu; oval.bottom = getHeight()/2+radiu;
這樣下來,基本上就可以繪制比較理想的弧線了,在這里也把繪制中心文字也說下吧,主要通過getTextBounds()方法獲取文字區(qū)域的寬高,然后在drawText()方法中將坐標進行適當偏移以使文字居中顯示。
String strProgressText = ""; if(mOnProgressListener !=null){//如果不為空 則為接口返回的值 strProgressText = mOnProgressListener.OnProgress(mMax, mProgress); }else{ strProgressText = mProgress+"/"+mMax; } mTextPaint.getTextBounds(strProgressText, 0, strProgressText.length(), bounds); canvas.drawText(strProgressText, oval.centerX()-bounds.width()/2, oval.centerY()+bounds.height()/2, mTextPaint);
最后還有一個小點就是漸變色的繪制,用的SweepGradient,我們可以看下Shader的子類,shader類是很強大的,類似與圓形圖片、漸變效果都可以用它來實現,這里就不過多展開了:
SweepGradient sweepGradient = new SweepGradient(getWidth()/2, getHeight()/2, colors, null); p.setShader(sweepGradient);
到這里為止,我們的圓環(huán)已經繪制好了,包括中間的文字以及圓環(huán)的漸變效果都已經實現了,就是這樣的:
2、加入刻度效果
接下來要加入刻度效果,實現思路是這樣的,我先默認實現兩個圓弧(注意這兩個圓弧只是我們假定添加的,并不是真正加在控件中顯示),然后獲取相同角度,根據相對位置獲取兩個圓環(huán)上的點進行連線,將這兩個點連起的刻度線封裝成對象添加在集合中,最后在onDraw方法中遍歷集合,進行繪制。
oval2 = new RectF();//內環(huán) oval2.left = getWidth()/2-radiu/4f*3; oval2.top = getHeight()/2-radiu/4f*3; oval2.right = getWidth()/2+radiu/4f*3; oval2.bottom = getHeight()/2+radiu/4f*3; oval3 = new RectF();//外環(huán) oval3.left = getWidth()/2-radiu/8f*7; oval3.top = getHeight()/2-radiu/8f*7; oval3.right = getWidth()/2+radiu/8f*7; oval3.bottom = getHeight()/2+radiu/8f*7; //然后初始化數據 /** * 初始化數據 */ private void initData() { mLinesList.clear(); Path path = new Path(); Path path1 = new Path(); //從startAngle開始 繪制180角度 path.addArc(oval2, mStartAngle, mGraduationSweepAngle); path1.addArc(oval3, mStartAngle, mGraduationSweepAngle); PathMeasure pm = new PathMeasure(path, false); float itemLength = pm.getLength()/(nGraduationCount-1); PathMeasure pm1 = new PathMeasure(path1, false); float[] pos = new float[2]; float[] postemp = new float[2]; for (int i = 0; i < nGraduationCount; i++) { pm.getPosTan(itemLength*i, pos , null ); pm1.getPosTan(itemLength*i/pm.getLength()*pm1.getLength(), postemp , null); Line line = new Line(); line.p1.x = pos[0]; line.p1.y = pos[1]; line.p2.x = postemp[0]; line.p2.y = postemp[1]; mLinesList.add(line); } } //ondraw方法: for (int i = 0; i < mLinesList.size(); i++) { Line line = mLinesList.get(i); canvas.drawLine(line.p1.x, line.p1.y, line.p2.x, line.p2.y, mRollPaint); }
這里用到了PathMeasure這個輔助工具,這里簡單講一下:
public PathMeasure() //path:需要測量的path forceClosed:是否關閉path public PathMeasure(Path path, boolean forceClosed) //指定需要測量的path public void setPath(Path path, boolean forceClosed) //返回當前path的總長度。 getLength() //返回值是boolean,如過path為空,則返回false 傳入參數有三個: //distance:傳入距離起點的距離。 //pos[]:意思是position,分別對應點的x,y坐標 //tan[]:獲取切線值,不常用。 public boolean getPosTan(float distance, float pos[], float tan[]) //返回一個處理好的matrix,但是這個matrix是以左上角作為旋轉點,所以需要將這個點移動到中心點。 其中一個參數flags,指這個martrix需要什么信息。flags的值有如下兩個 PathMeasure.POSITION_MATRIX_FLAG:位置信息 pathMeasure.TANGENT_MATRIX_FLAG:切邊信息,方位角信息 public boolean getMatrix(float distance, Matrix matrix, int flags) //這個方法返回boolean,如果截取的長度為0則返回false,否則為true。參數如下 //startD:起始距離 //stopD:終點距離 //dst:接收截取的path //startWithMoveTo:是否把截取的path,moveto到起始點。 public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)
3、加入刻度隨進度增加而增加效果,并增加進度變化回調方便操作
加入刻度隨進度增加而增加,我們可以這樣想,首先我總的刻度數是一定的,判斷劃過的角度占圓周的百分比,隨之就可以得到劃過刻度數占總刻度數的百分比,進而就求出劃過的刻度數了。
for (int i = 0; i < Math.round(mSweepAngle*nGraduationCount/360f); i++) { if(i將劃過的刻度數用畫筆再繪制一次,隨進度增加的刻度效果就出現啦!
/** * 設置進度監(jiān)聽 * @param mOnProgressListener */ public void setOnProgressListener(OnProgressListener mOnProgressListener) { this.mOnProgressListener = mOnProgressListener; } /** * 用于外部判斷當前進度狀態(tài) */ interface OnProgressListener{ /** * 返回中間部分文字內容 * @param max * @param progress * @return */ String OnProgress(int max,int progress); }設置回調監(jiān)聽,這樣在每次進度變化的時候,可以隨意變化中間部分文字顯示的內容。
4、增加自定義屬性增加可定制性
attrs.xml:
layout文件:
xmlns:app="http://schemas.android.com/apk/res-auto"獲取自定義屬性值:
TypedArray typedArray = getResources().obtainAttributes(attrs, R.styleable.LoadingStyle); mTextSize = (int) typedArray.getDimension(R.styleable.LoadingStyle_textSize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics())); mStrokeWidth = (int) typedArray.getDimension(R.styleable.LoadingStyle_strokeWidth, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics())); mGraduationWidth = (int) typedArray.getDimension(R.styleable.LoadingStyle_graduationWidth, mStrokeWidth/2); mTextColor = (int) typedArray.getColor(R.styleable.LoadingStyle_textColor, Color.BLACK); mGraduationBackgroundColor = (int) typedArray.getColor(R.styleable.LoadingStyle_graduationBackgroundColor, Color.BLACK); mStartAngle = (int) typedArray.getInt(R.styleable.LoadingStyle_startAngle, 180); mMax = (int) typedArray.getInt(R.styleable.LoadingStyle_max, 0); mProgress = (int) typedArray.getInt(R.styleable.LoadingStyle_progress, 0); nGraduationCount = (int) typedArray.getInt(R.styleable.LoadingStyle_graduationCount, 35); isShowGraduationBackground = typedArray.getBoolean(R.styleable.LoadingStyle_isShowGraduationBackground, true); isShowOutRoll = typedArray.getBoolean(R.styleable.LoadingStyle_isShowOutRoll, true); typedArray.recycle();5、使用方法
int[] colors = {0xFFE5BD7D, 0xFFFAAA64, 0xFFFFFFFF, 0xFF6AE2FD, 0xFF8CD0E5, 0xFFA3CBCB, 0xFFBDC7B3, 0xFFD1C299, 0xFFE5BD7D}; lv_loading.setTextColor(Color.BLACK);//設置中心文字顏色 lv_loading.setMax(500);//設置最大進度 lv_loading.setShowGraduationBackgroundEnable(true);//是否顯示刻度背景 lv_loading.setGraduationBackgroundColor(Color.GRAY);//刻度的背景顏色 lv_loading.setStartAngle(180);//設置開始旋轉角度 lv_loading.setGraduationCount(10);//設置刻度數 lv_loading.setGraduationWidth(5);//設置刻度的寬度 lv_loading.setOutColors(colors);//設置外部圓環(huán)顏色 lv_loading.setInnerGraduationColors(colors);//設置內部刻度進度顏色 lv_loading.setTextSize(35);//設置內部文字字體大小 lv_loading.setShowOutRollEnable(false);//設置是否顯示外部進度框 lv_loading.setOnProgressListener(new OnProgressListener() { @Override public String OnProgress(int max, int progress) { return progress*100f/max+"%"; } });項目github地址: https://github.com/zhangke301...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65003.html
摘要:地址中文自定義能改變尺寸顏色滑塊圖片刻度圖片刻度文字和氣泡指示器,當滑動時顯示帶有進度的指示器。給選擇圓角方角默認兩端是圓角,可以設置為方形。滑塊下顯示進度當的類型為時可以設置滑動后滑塊下顯示保留進度。 IndicatorSeekBar showImg(https://segmentfault.com/img/remote/1460000011967195);showImg(https...
閱讀 1290·2021-11-24 09:39
閱讀 2632·2021-09-30 09:47
閱讀 1325·2021-09-22 15:15
閱讀 2410·2021-09-10 10:51
閱讀 1954·2019-08-30 15:55
閱讀 2977·2019-08-30 11:06
閱讀 896·2019-08-30 10:53
閱讀 830·2019-08-29 17:26