日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android自定义波浪加载圆形进度条——(自定义控件 一)

發(fā)布時間:2025/7/14 Android 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android自定义波浪加载圆形进度条——(自定义控件 一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

?

自定義控件—— 波浪形狀圓形進(jìn)度加載

時間管理的基礎(chǔ)是精力管理,精力的高低、正負(fù)分影響到我們的效率

而時間是無法管理的,能夠管理的只有自己,透過管理自己的習(xí)慣,管理自己的事件來達(dá)成對時間的管理。

而在每一天中,人生不豐于做多少事,而在于把重要的事情專注做、用心做,把它做到極致。

1、效果簡閱

2、實(shí)現(xiàn)思路設(shè)計(jì)

3、初始化操作

private void init(Context context) {//繪制圓形的 PaintmCicrlPaint = new Paint();mCicrlPaint.setAntiAlias(true);mCicrlPaint.setColor(Color.BLUE);//繪制進(jìn)度的 PaintmProgressPaint = new Paint();mProgressPaint.setAntiAlias(true);mProgressPaint.setColor(Color.RED);//設(shè)置只繪制重疊的部分mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//繪制文字的 PaintmTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setColor(Color.WHITE);mTextPaint.setTextSize(20);//繪制進(jìn)度的PathmPath = new Path();/*** 手勢識別監(jiān)聽*/final GestureDetector gestureDetector = new GestureDetector(listener);/*** 將觸摸識別事件傳遞給 GestureDetector*/this.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {return gestureDetector.onTouchEvent(event);}});this.setClickable(true);//設(shè)置布局加載監(jiān)聽 this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {//更新控件的大小viewHeight = ProgressView.this.getHeight();viewWidth = ProgressView.this.getWidth();//創(chuàng)建 bitmap 與 canvasbitmap = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);mCanvas = new Canvas(bitmap);/*** 更新默認(rèn)設(shè)置*/updateDefaulBuildValue();}});}GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {/*** 單擊點(diǎn)擊監(jiān)聽* @param e* @return*/@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {System.out.println("sing click ");if (clickListener != null) {clickListener.onSingleClick(e);return true;}return super.onSingleTapConfirmed(e);}/*** 雙擊點(diǎn)擊監(jiān)聽* @param e* @return*/@Overridepublic boolean onDoubleTap(MotionEvent e) {if (clickListener != null) {clickListener.onDoubleClick(e);}return super.onDoubleTap(e);}/*** 常按事件監(jiān)聽* @param e*/@Overridepublic void onLongPress(MotionEvent e) {if (clickListener != null) {clickListener.onLongPressClick(e);}super.onLongPress(e);}};

同時設(shè)置了點(diǎn)擊事件的監(jiān)聽接口回調(diào)

/*** 控件 點(diǎn)擊事件監(jiān)聽 回調(diào)*/public interface OnWaveProgressClickListener {/*** 單擊回調(diào)接口* @param e*/public void onSingleClick(MotionEvent e);/*** 雙擊回調(diào)接口* @param e*/public void onDoubleClick(MotionEvent e);/*** 找按回調(diào)接口* @param e*/public void onLongPressClick(MotionEvent e);}private OnWaveProgressClickListener clickListener;/*** 設(shè)置控件的點(diǎn)擊事件** @param listener*/public void setWaveOnClickListener(OnWaveProgressClickListener listener) {this.clickListener = listener;}

4、測量

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);/*** 繪制的為正方形進(jìn)度條,測量比較較小的長度為圓形的直徑長度*/int width;int height;width = Math.min(widthSize, heightSize);height = Math.min(widthSize, heightSize);setMeasuredDimension(width, height);}

5、繪制

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制整體圓形mCanvas.drawCircle(viewWidth / 2, viewWidth / 2, viewWidth / 2, mCicrlPaint);//繪制進(jìn)度圖形mPath.reset();//進(jìn)度圖形的高度 隨著加載進(jìn)度的改變float y = (1 - (float) currentProgress / maxProgress) * viewHeight;mPath.moveTo(viewWidth, y);mPath.lineTo(viewWidth, viewHeight);mPath.lineTo(0, viewHeight);mPath.lineTo(0, y); ///*** 計(jì)算振幅的比例* 振幅 的大小 是隨著進(jìn)度的大小動態(tài)改變的*/int amplitude = (int) ((1 - (float) currentProgress / maxProgress) * mDefaulAmplitude);if (currentProgress % 2 == 0) {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);}} else {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);}}mPath.close();mCanvas.drawPath(mPath, mProgressPaint); ////繪制 中間顯示的百分比文字String text = "" + (int) (((float) currentProgress / maxProgress) * 100);//獲取繪制文字的寬度float textWidth = mTextPaint.measureText(text);//獲取繪制文字的高度Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();//Descent是baseline之下至字符最低處的距離//Ascent是baseline之上至字符最高處的距離//ascent + descent 就是測量文字的高度float textHeight = fontMetrics.ascent + fontMetrics.descent;//計(jì)算繪制中間顯示進(jìn)度文字的坐標(biāo)float textY = viewHeight / 2 - textHeight / 2;float textX = viewWidth / 2 - textWidth / 2;//繪制顯示進(jìn)度的文字mCanvas.drawText(text, textX, textY, mTextPaint);canvas.drawBitmap(bitmap, 0, 0, null);}

繪制分析

5.1繪制圓形背景

5.2繪制進(jìn)度

5.3繪制波浪曲線

曲線分析 一

曲線分析 二

曲線分析三

?

繪制:

/*** 計(jì)算振幅的比例* 振幅 的大小 是隨著進(jìn)度的大小動態(tài)改變的*/int amplitude = (int) ((1 - (float) currentProgress / maxProgress) * mDefaulAmplitude);if (currentProgress % 2 == 0) {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);}} else {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);}}

效果?

上面的圖形中繪制了四組正反曲線,也就是說分別繪制了四個開口向上的曲線,四個開口向下的曲線,

這里采用的繪制思想是每一次都 繪制一個開口向上的曲線 和一個開口向下的曲線,然后形成一個完整的類似正弦曲線的線形,這里繪制了四次,也就是在FOR循環(huán)中循環(huán)了四次,具體的循環(huán)次數(shù)是不定的,依據(jù)控件的大小來動態(tài)設(shè)置

?

5.4繪制顯示文本?

//獲取繪制文字的寬度float textWidth = mTextPaint.measureText(text);//獲取繪制文字的高度Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();//Descent是baseline之下至字符最低處的距離//Ascent是baseline之上至字符最高處的距離//ascent + descent 就是測量文字的高度float textHeight = fontMetrics.ascent + fontMetrics.descent;//計(jì)算繪制中間顯示進(jìn)度文字的坐標(biāo)float textY = viewHeight / 2 - textHeight / 2;float textX = viewWidth / 2 - textWidth / 2;//繪制顯示進(jìn)度的文字mCanvas.drawText(text, textX, textY, mTextPaint);

其中涉及到一些文本測量

?

6、完整源碼

package com.animation.androidlongs.a360animationapplication.view;import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver;/*** Created by androidlongs on 16/8/9.*/ public class WaveProgressView extends View {private Paint mCicrlPaint;private Paint mProgressPaint;private Paint mTextPaint;private Canvas mCanvas;private Path mPath;private Bitmap bitmap;public WaveProgressView(Context context) {super(context);init(context);}public WaveProgressView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public WaveProgressView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}private void init(Context context) {//繪制圓形的 PaintmCicrlPaint = new Paint();mCicrlPaint.setAntiAlias(true);mCicrlPaint.setColor(Color.BLUE);//繪制進(jìn)度的 PaintmProgressPaint = new Paint();mProgressPaint.setAntiAlias(true);mProgressPaint.setColor(Color.RED);//設(shè)置只繪制重疊的部分mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//繪制文字的 PaintmTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setColor(Color.WHITE);mTextPaint.setTextSize(20);//繪制進(jìn)度的PathmPath = new Path();/*** 手勢識別監(jiān)聽*/final GestureDetector gestureDetector = new GestureDetector(listener);/*** 將觸摸識別事件傳遞給 GestureDetector*/this.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {return gestureDetector.onTouchEvent(event);}});this.setClickable(true);//設(shè)置布局加載監(jiān)聽 this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {//更新控件的大小viewHeight = WaveProgressView.this.getHeight();viewWidth = WaveProgressView.this.getWidth();//創(chuàng)建 bitmap 與 canvasbitmap = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);mCanvas = new Canvas(bitmap);/*** 更新默認(rèn)設(shè)置*/updateDefaulBuildValue();}});}GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {/*** 單擊點(diǎn)擊監(jiān)聽* @param e* @return*/@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {System.out.println("sing click ");if (clickListener != null) {clickListener.onSingleClick(e);return true;}return super.onSingleTapConfirmed(e);}/*** 雙擊點(diǎn)擊監(jiān)聽* @param e* @return*/@Overridepublic boolean onDoubleTap(MotionEvent e) {if (clickListener != null) {clickListener.onDoubleClick(e);}return super.onDoubleTap(e);}/*** 常按事件監(jiān)聽* @param e*/@Overridepublic void onLongPress(MotionEvent e) {if (clickListener != null) {clickListener.onLongPressClick(e);}super.onLongPress(e);}};@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);/*** 繪制的為正方形進(jìn)度條,測量比較較小的長度為圓形的直徑長度*/int width;int height;width = Math.min(widthSize, heightSize);height = Math.min(widthSize, heightSize);setMeasuredDimension(width, height);}/*** 默認(rèn)控件的 寬 高* 默認(rèn)的 當(dāng)前的進(jìn)度 總的進(jìn)度*/public int viewWidth = 150;public int viewHeight = 150;public int currentProgress = 0;public int maxProgress = 100;/*** 計(jì)算振幅大小 所用的比例數(shù) 默認(rèn)為10*/private int mAplitudeCunt = 10;/*** 默認(rèn)振幅的大小 為控件高度的 1/10*/private int mDefaulAmplitude = viewHeight / mAplitudeCunt;/*** 計(jì)算周期長度使用的比例數(shù) 默認(rèn)為8*/private int mPriodicCount = 8;/*** 曲線默認(rèn)的周期長度*/private int mDefaulPriodic = viewHeight / mPriodicCount;/*** 曲線的繪制次數(shù)*/private int mquadLineDrawCount = (int) ((float) viewWidth / mDefaulPriodic);/*** 更新默認(rèn)的設(shè)置*/private void updateDefaulBuildValue() {if (viewHeight < 400) {mPriodicCount = 8;mAplitudeCunt = 10;} else if (viewHeight < 600 && viewHeight >= 400) {mPriodicCount = 14;mAplitudeCunt = 16;} else if (viewHeight < 1000 && viewHeight >= 600) {mPriodicCount = 20;mAplitudeCunt = 20;} else if (viewHeight < 1400 && viewHeight >= 100) {mAplitudeCunt = 24;mPriodicCount = 26;} else {mPriodicCount = 30;mAplitudeCunt = 30;}/*** 默認(rèn)振幅的大小 為控件高度的 1/10*/mDefaulAmplitude = viewHeight / mAplitudeCunt;/*** 曲線默認(rèn)的周期長度*/mDefaulPriodic = viewHeight / 8;/*** 曲線的繪制次數(shù)*/mquadLineDrawCount = (int) ((float) viewWidth / mDefaulPriodic);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制整體圓形mCanvas.drawCircle(viewWidth / 2, viewWidth / 2, viewWidth / 2, mCicrlPaint);//繪制進(jìn)度圖形mPath.reset();//進(jìn)度圖形的高度 隨著加載進(jìn)度的改變float y = (1 - (float) currentProgress / maxProgress) * viewHeight;mPath.moveTo(viewWidth, y);mPath.lineTo(viewWidth, viewHeight);mPath.lineTo(0, viewHeight);mPath.lineTo(0, y); ///*** 計(jì)算振幅的比例* 振幅 的大小 是隨著進(jìn)度的大小動態(tài)改變的*/int amplitude = (int) ((1 - (float) currentProgress / maxProgress) * mDefaulAmplitude);if (currentProgress % 2 == 0) {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);}} else {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);}}mPath.close();mCanvas.drawPath(mPath, mProgressPaint); ////繪制 中間顯示的百分比文字String text = "" + (int) (((float) currentProgress / maxProgress) * 100);//獲取繪制文字的寬度float textWidth = mTextPaint.measureText(text);//獲取繪制文字的高度Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();//Descent是baseline之下至字符最低處的距離//Ascent是baseline之上至字符最高處的距離//ascent + descent 就是測量文字的高度float textHeight = fontMetrics.ascent + fontMetrics.descent;//計(jì)算繪制中間顯示進(jìn)度文字的坐標(biāo)float textY = viewHeight / 2 - textHeight / 2;float textX = viewWidth / 2 - textWidth / 2;//繪制顯示進(jìn)度的文字mCanvas.drawText(text, textX, textY, mTextPaint);canvas.drawBitmap(bitmap, 0, 0, null);}/*** 控件 點(diǎn)擊事件監(jiān)聽 回調(diào)*/public interface OnWaveProgressClickListener {/*** 單擊回調(diào)接口** @param e*/public void onSingleClick(MotionEvent e);/*** 雙擊回調(diào)接口** @param e*/public void onDoubleClick(MotionEvent e);/*** 找按回調(diào)接口** @param e*/public void onLongPressClick(MotionEvent e);}private OnWaveProgressClickListener clickListener;/*** 控件 加載進(jìn)度回調(diào)接口*/public interface OnWaveProgressListener {public void onProgresUpdate(int progress);public void onFinish();}private OnWaveProgressListener progressListener;/*** 設(shè)置更新當(dāng)前進(jìn)度** @param progress*/public void updateProgress(int progress) {if (progress <= 0) {progress = 0;} else if (progress > this.maxProgress) {progress = maxProgress;}this.currentProgress = progress;//進(jìn)度更新接口回調(diào)if (progressListener != null) {progressListener.onProgresUpdate(currentProgress);}if (progress == maxProgress) {if (progressListener != null) {progressListener.onFinish();}}//重繪invalidate();}/*** 設(shè)置最大進(jìn)度** @param max*/public void setMaxProgress(int max) {if (max <= 0) {max = 100;}this.setMaxProgress(max);}/*** 設(shè)置控件的點(diǎn)擊事件** @param listener*/public void setWaveOnClickListener(OnWaveProgressClickListener listener) {this.clickListener = listener;}/*** 加載進(jìn)度監(jiān)聽設(shè)置** @param listener*/public void setWaveOnProgressListener(OnWaveProgressListener listener) {this.progressListener = listener;}}

7、Activity中的使用

package com.animation.androidlongs.a360animationapplication;import android.content.Intent; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MotionEvent;import com.animation.androidlongs.a360animationapplication.view.WaveProgressView;public class MainActivity extends AppCompatActivity {private WaveProgressView customWaveProgressView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(MainActivity.this, FloatViewService.class);//startService(intent);customWaveProgressView = (WaveProgressView) findViewById(R.id.progress);handler.postDelayed(runnable,2000);//設(shè)置點(diǎn)擊事件監(jiān)聽customWaveProgressView.setWaveOnClickListener(new WaveProgressView.OnWaveProgressClickListener() {@Overridepublic void onSingleClick(MotionEvent e) {System.out.println("onSingleClick");}@Overridepublic void onDoubleClick(MotionEvent e) {System.out.println("onDoubleClick");}@Overridepublic void onLongPressClick(MotionEvent e) {System.out.println("onLongPressClick");}});//設(shè)置進(jìn)度更新監(jiān)聽customWaveProgressView.setWaveOnProgressListener(new WaveProgressView.OnWaveProgressListener() {@Overridepublic void onProgresUpdate(int progress) {}@Overridepublic void onFinish() {}});}private Handler handler = new Handler();private Runnable runnable = new Runnable() {@Overridepublic void run() {currentNum++;customWaveProgressView.updateProgress(currentNum);if (currentNum<maxNum){handler.postDelayed(runnable,200);}else {handler.removeCallbacks(runnable);currentNum = 0;}}};private int maxNum = 100;private int currentNum =0; }

?

?

?

?

轉(zhuǎn)載于:https://my.oschina.net/u/2447911/blog/730908

總結(jié)

以上是生活随笔為你收集整理的Android自定义波浪加载圆形进度条——(自定义控件 一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。