編輯:關於Android編程
1.進度圓環的顏色是漸變。 2.添加一個進度標尺,類似與鐘表表盤的樣子,用來顯示刻度。主要是在原來的基礎上添加了如下功能
3.添加一個進度指示器,三角形的樣子,用來顯示進度。
效果圖如下
下面,就針對這三個變化來說明一下:
/** * 設置圓形漸變 * 【第一個參數】:中心點x坐標 * 【第二個參數】:中心點y坐標 * 【第三個參數】:漸變的顏色數組 * 【第四個參數】:漸變的顏色數組對應的相對位置 */ paintCurrent.setShader(new SweepGradient(centerX, centerX, new int[]{getResources().getColor(R.color.start_color), getResources().getColor(R.color.end_color)}, null));
/** * 通過這個拿到一個資源圖片對象 */ bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.arrow);
2.計算三角形移動軌跡的坐標
/** * 為進度設置動畫 * ValueAnimator是整個屬性動畫機制當中最核心的一個類,屬性動畫的運行機制是通過不斷地對值進行操作來實現的, * 而初始值和結束值之間的動畫過渡就是由ValueAnimator這個類來負責計算的。 * 它的內部使用一種時間循環的機制來計算值與值之間的動畫過渡, * 我們只需要將初始值和結束值提供給ValueAnimator,並且告訴它動畫所需運行的時長, * 那麼ValueAnimator就會自動幫我們完成從初始值平滑地過渡到結束值這樣的效果。 * * @param last * @param current */ @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) private void setAnimation(float last, float current, int length) { ValueAnimator progressAnimator = ValueAnimator.ofFloat(last, current); progressAnimator.setDuration(length); progressAnimator.setTarget(currentAngleLength); progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { /**每次要繪制的圓弧角度**/ currentAngleLength = (float) animation.getAnimatedValue(); /**要繪制的三角形指示器的半徑**/ float radius=centerX - borderWidth-bitmap.getHeight(); /**要繪制的三角形指示器的x坐標**/ point.x = (float) (centerX +radius * Math.cos((startAngle + currentAngleLength) * Math.PI / 180)); /**要繪制的三角形指示器的y坐標**/ point.y = (float) (centerX + radius* Math.sin((startAngle + currentAngleLength) * Math.PI / 180)); Log.d("stepView", point + ""); /**要繪制的圓弧多繪制的部分減掉**/ double subtractionScale = borderWidth/2/(centerX*2*Math.PI); double subtractionAngle=subtractionScale*angleLength; if(currentAngleLength>subtractionAngle){ currentAngleLength-=subtractionAngle; } invalidate(); } }); progressAnimator.start(); }
3.調整旋轉的角度後繪制三角形指示器
/** * 5.畫三角形 * * @param canvas */ private void drawBitmap(Canvas canvas) { // 定義矩陣對象 Matrix matrix = new Matrix(); // 參數為正則向右旋轉 matrix.postRotate(startAngle + currentAngleLength + 90); Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);//這裡不管怎麼設置都不影響最終圖像 canvas.drawBitmap(dstbmp, point.x - dstbmp.getWidth() / 2, point.y - dstbmp.getHeight() / 2, mBitmapPaint); }
/** * 6. 畫鐘表線 * * @param canvas */ private void drawLine(Canvas canvas) { Paint mPaint = new Paint(); mPaint.setStrokeWidth(5); mPaint.setColor(getResources().getColor(R.color.start_color)); /**要繪制的表盤線的總數**/ int count = 60; /**要繪制的表盤每個間隔線條之間的夾角**/ int avgAngle = (360 / (count - 1)); /**要繪制的表盤的最長的半徑**/ float radius = centerX - borderWidth - bitmap.getHeight() - 20; /**要繪制的表盤線條長度**/ int lineLength = 25; /**起始點**/ PointF point1 = new PointF(); /**終止點**/ PointF point2 = new PointF(); for (int i = 0; i < count; i++) { int angle = avgAngle * i; /**起始點坐標**/ point1.x = centerX + (float) Math.cos(angle * (Math.PI / 180)) * radius; point1.y = centerX + (float) Math.sin(angle * (Math.PI / 180)) * radius; /**終止點坐標**/ point2.x = centerX + (float) Math.cos(angle * (Math.PI / 180)) * (radius - lineLength); point2.y = centerX + (float) Math.sin(angle * (Math.PI / 180)) * (radius - lineLength); /**畫線**/ canvas.drawLine(point1.x, point1.y, point2.x, point2.y, mPaint); } }
package cn.bluemobi.dylan.stepcirclestaffview; /** * Created by yuandl on 2016-11-08. */ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.SweepGradient; import android.graphics.Typeface; import android.os.Build; import android.support.annotation.RequiresApi; import android.util.AttributeSet; import android.util.Log; import android.view.View; import java.util.logging.Logger; /** * Created by DylanAndroid on 2016/5/26. * 顯示步數的圓弧 */ public class StepArcView extends View { /** * 圓弧的寬度 */ private float borderWidth = 38f; /** * 畫步數的數值的字體大小 */ private float numberTextSize = 0; /** * 步數 */ private String stepNumber = "0"; /** * 開始繪制圓弧的角度 */ private float startAngle = 90; /** * 終點對應的角度和起始點對應的角度的夾角 */ private float angleLength = 360; /** * 所要繪制的當前步數的紅色圓弧終點到起點的夾角 */ private float currentAngleLength = 0; /** * 動畫時長 */ private int animationLength = 3000; private PointF point; private float centerX; private Bitmap bitmap; private int totalStepNum; private void init() { point = new PointF(); /** * 通過這個拿到一個資源圖片對象 */ bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.arrow); } public StepArcView(Context context) { super(context); init(); } public StepArcView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public StepArcView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /**中心點的x坐標*/ centerX = (getWidth()) / 2; /**指定圓弧的外輪廓矩形區域*/ RectF rectF = new RectF(0 + borderWidth, borderWidth, 2 * centerX - borderWidth, 2 * centerX - borderWidth); /**【第一步】繪制整體的黃色圓弧*/ drawArcYellow(canvas, rectF); /**【第二步】繪制當前進度的紅色圓弧*/ drawArcRed(canvas, rectF); /**【第三步】繪制當前進度的紅色數字*/ drawTextNumber(canvas, centerX); /**【第四步】繪制"步數"的紅色數字*/ drawTextStepString(canvas, centerX); /**【第五步】繪制"步數"進度標尺的三角形*/ drawBitmap(canvas); /**【第六步】繪制"步數"進度標尺類似於鐘表線隔*/ drawLine(canvas); } /** * 1.繪制總步數的黃色圓弧 * * @param canvas 畫筆 * @param rectF 參考的矩形 */ private void drawArcYellow(Canvas canvas, RectF rectF) { Paint paint = new Paint(); /** 默認畫筆顏色,黃色 */ paint.setColor(getResources().getColor(R.color.default_color)); /** 結合處為圓弧*/ paint.setStrokeJoin(Paint.Join.ROUND); /** 設置畫筆的樣式 Paint.Cap.Round ,Cap.SQUARE等分別為圓形、方形*/ paint.setStrokeCap(Paint.Cap.ROUND); /** 設置畫筆的填充樣式 Paint.Style.FILL :填充內部;Paint.Style.FILL_AND_STROKE :填充內部和描邊; Paint.Style.STROKE :僅描邊*/ paint.setStyle(Paint.Style.STROKE); /**抗鋸齒功能*/ paint.setAntiAlias(true); /**設置畫筆寬度*/ paint.setStrokeWidth(borderWidth); /**繪制圓弧的方法 * drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//畫弧, 參數一是RectF對象,一個矩形區域橢圓形的界限用於定義在形狀、大小、電弧, 參數二是起始角(度)在電弧的開始,圓弧起始角度,單位為度。 參數三圓弧掃過的角度,順時針方向,單位為度,從右中間開始為零度。 參數四是如果這是true(真)的話,在繪制圓弧時將圓心包括在內,通常用來繪制扇形;如果它是false(假)這將是一個弧線, 參數五是Paint對象; */ canvas.drawArc(rectF, startAngle, angleLength, false, paint); } /** * 2.繪制當前步數的紅色圓弧 */ private void drawArcRed(Canvas canvas, RectF rectF) { Paint paintCurrent = new Paint(); paintCurrent.setStrokeJoin(Paint.Join.ROUND); paintCurrent.setStrokeCap(Paint.Cap.SQUARE);//圓角弧度 paintCurrent.setStyle(Paint.Style.STROKE);//設置填充樣式 paintCurrent.setAntiAlias(true);//抗鋸齒功能 paintCurrent.setStrokeWidth(borderWidth);//設置畫筆寬度 /** * 設置圓形漸變 * 【第一個參數】:中心點x坐標 * 【第二個參數】:中心點y坐標 * 【第三個參數】:漸變的顏色數組 * 【第四個參數】:漸變的顏色數組對應的相對位置 */ paintCurrent.setShader(new SweepGradient(centerX, centerX, new int[]{getResources().getColor(R.color.start_color), getResources().getColor(R.color.end_color)}, null)); canvas.drawArc(rectF, startAngle, currentAngleLength, false, paintCurrent); } /** * 3.圓環中心的步數 */ private void drawTextNumber(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//抗鋸齒功能 vTextPaint.setTextSize(numberTextSize); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL); vTextPaint.setTypeface(font);//字體風格 vTextPaint.setColor(getResources().getColor(R.color.center_text_color)); Rect bounds_Number = new Rect(); vTextPaint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number); canvas.drawText(stepNumber, centerX, getHeight() / 2 + bounds_Number.height() / 2, vTextPaint); } /** * 4.圓環中心[步數]的文字 */ private void drawTextStepString(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextSize(dipToPx(13)); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//抗鋸齒功能 vTextPaint.setColor(getResources().getColor(R.color.other_text_color)); String stepString = "目標 "+totalStepNum; Rect bounds = new Rect(); vTextPaint.getTextBounds(stepString, 0, stepString.length(), bounds); canvas.drawText(stepString, centerX, getHeight() / 2 + bounds.height() + getFontHeight(numberTextSize), vTextPaint); canvas.save(); stepString = "今天步數"; bounds = new Rect(); vTextPaint.getTextBounds(stepString, 0, stepString.length(), bounds); canvas.drawText(stepString, centerX, getHeight() / 2 - getFontHeight(numberTextSize), vTextPaint); } /** * 5.畫三角形 * * @param canvas */ private void drawBitmap(Canvas canvas) { // 定義矩陣對象 Matrix matrix = new Matrix(); // 參數為正則向右旋轉 matrix.postRotate(startAngle + currentAngleLength + 90); Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);//這裡不管怎麼設置都不影響最終圖像 canvas.drawBitmap(dstbmp, point.x - dstbmp.getWidth() / 2, point.y - dstbmp.getHeight() / 2, mBitmapPaint); } /** * 6. 畫鐘表線 * * @param canvas */ private void drawLine(Canvas canvas) { Paint mPaint = new Paint(); mPaint.setStrokeWidth(5); mPaint.setColor(getResources().getColor(R.color.start_color)); /**要繪制的表盤線的總數**/ int count = 60; /**要繪制的表盤每個間隔線條之間的夾角**/ int avgAngle = (360 / (count - 1)); /**要繪制的表盤的最長的半徑**/ float radius = centerX - borderWidth - bitmap.getHeight() - 20; /**要繪制的表盤線條長度**/ int lineLength = 25; /**起始點**/ PointF point1 = new PointF(); /**終止點**/ PointF point2 = new PointF(); for (int i = 0; i < count; i++) { int angle = avgAngle * i; /**起始點坐標**/ point1.x = centerX + (float) Math.cos(angle * (Math.PI / 180)) * radius; point1.y = centerX + (float) Math.sin(angle * (Math.PI / 180)) * radius; /**終止點坐標**/ point2.x = centerX + (float) Math.cos(angle * (Math.PI / 180)) * (radius - lineLength); point2.y = centerX + (float) Math.sin(angle * (Math.PI / 180)) * (radius - lineLength); /**畫線**/ canvas.drawLine(point1.x, point1.y, point2.x, point2.y, mPaint); } } /** * 獲取當前步數的數字的高度 * * @param fontSize 字體大小 * @return 字體高度 */ public int getFontHeight(float fontSize) { Paint paint = new Paint(); paint.setTextSize(fontSize); Rect bounds_Number = new Rect(); paint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number); return bounds_Number.height(); } /** * dip 轉換成px * * @param dip * @return */ private int dipToPx(float dip) { float density = getContext().getResources().getDisplayMetrics().density; return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1)); } /** * 所走的步數進度 * * @param totalStepNum 設置的步數 * @param currentCounts 所走步數 */ @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) public void setCurrentCount(int totalStepNum, int currentCounts) { this.totalStepNum = totalStepNum; stepNumber = currentCounts + ""; setTextSize(currentCounts); /**如果當前走的步數超過總步數則圓弧還是270度,不能成為園*/ if (currentCounts > totalStepNum) { currentCounts = totalStepNum; } /**所走步數占用總共步數的百分比*/ float scale = (float) currentCounts / totalStepNum; /**換算成弧度最後要到達的角度的長度-->弧長*/ float currentAngleLength = scale * angleLength; /**開始執行動畫*/ setAnimation(0, currentAngleLength, animationLength); } /** * 為進度設置動畫 * ValueAnimator是整個屬性動畫機制當中最核心的一個類,屬性動畫的運行機制是通過不斷地對值進行操作來實現的, * 而初始值和結束值之間的動畫過渡就是由ValueAnimator這個類來負責計算的。 * 它的內部使用一種時間循環的機制來計算值與值之間的動畫過渡, * 我們只需要將初始值和結束值提供給ValueAnimator,並且告訴它動畫所需運行的時長, * 那麼ValueAnimator就會自動幫我們完成從初始值平滑地過渡到結束值這樣的效果。 * * @param last * @param current */ @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) private void setAnimation(float last, float current, int length) { ValueAnimator progressAnimator = ValueAnimator.ofFloat(last, current); progressAnimator.setDuration(length); progressAnimator.setTarget(currentAngleLength); progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { /**每次要繪制的圓弧角度**/ currentAngleLength = (float) animation.getAnimatedValue(); /**要繪制的三角形指示器的半徑**/ float radius=centerX - borderWidth-bitmap.getHeight(); /**要繪制的三角形指示器的x坐標**/ point.x = (float) (centerX +radius * Math.cos((startAngle + currentAngleLength) * Math.PI / 180)); /**要繪制的三角形指示器的y坐標**/ point.y = (float) (centerX + radius* Math.sin((startAngle + currentAngleLength) * Math.PI / 180)); Log.d("stepView", point + ""); /**要繪制的圓弧多繪制的部分減掉**/ double subtractionScale = borderWidth/2/(centerX*2*Math.PI); double subtractionAngle=subtractionScale*angleLength; if(currentAngleLength>subtractionAngle){ currentAngleLength-=subtractionAngle; } invalidate(); } }); progressAnimator.start(); } /** * 設置文本大小,防止步數特別大之後放不下,將字體大小動態設置 * * @param num */ public void setTextSize(int num) { String s = String.valueOf(num); int length = s.length(); if (length <= 4) { numberTextSize = dipToPx(40); } else if (length > 4 && length <= 6) { numberTextSize = dipToPx(30); } else if (length > 6 && length <= 8) { numberTextSize = dipToPx(25); } else if (length > 8) { numberTextSize = dipToPx(20); } } }
Android和java啟動的區別不同於使用 main() 方法啟動應用的其他編程范例,Android 系統會通過調用對應於其生命周期中特定階段的特定回調方法在 Acti
最近無意中和同事交流數據安全傳輸的問題,想起自己曾經使用過的Rsa非對稱加密算法,閒下來總結一下。什麼是Rsa加密?RSA算法是最流行的公鑰密碼算法,使用長度可以變化的密
繪制曲線類:public class BaseFundChartView extends View { Paint linePaint; Paint text
第1節 ContentProvider介紹ContentProvider是安卓系統的四大組件之一,可以向其他組件提供數據訪問的能力。它就像是一個網站,其他組件(或者其他應