下载进度条

先看一下效果图:

这里我加了阴影效果,所有需要加入以下依赖:

implementation 'com.google.android.material:material:1.0.0'

 然后新建一个实现下载进度条的自定义View类,直接上代码:

  1 public class FlikerProgressBar extends View implements Runnable{
  2     private PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);
  3 
  4     private int DEFAULT_HEIGHT_DP = 35;
  5 
  6     private int borderWidth;
  7 
  8     private float maxProgress = 100f;
  9 
 10     private Paint textPaint;
 11 
 12     private Paint bgPaint;
 13 
 14     private Paint pgPaint;
 15 
 16     private String progressText;
 17 
 18     private Rect textRect;
 19 
 20     private RectF bgRectf;
 21 
 22     /**
 23      * 左右来回移动的滑块
 24      */
 25     private Bitmap flikerBitmap;
 26 
 27     /**
 28      * 滑块移动最左边位置,作用是控制移动
 29      */
 30     private float flickerLeft;
 31 
 32     /**
 33      * 进度条 bitmap ,包含滑块
 34      */
 35     private Bitmap pgBitmap;
 36 
 37     private Canvas pgCanvas;
 38 
 39     /**
 40      * 当前进度
 41      */
 42     private float progress;
 43 
 44     private boolean isFinish;
 45 
 46     private boolean isStop;
 47 
 48     /**
 49      * 下载中颜色
 50      */
 51     private int loadingColor;
 52 
 53     /**
 54      * 暂停时颜色
 55      */
 56     private int stopColor;
 57 
 58     /**
 59      * 进度文本、边框、进度条颜色
 60      */
 61     private int progressColor;
 62 
 63     private int textSize;
 64 
 65     private int radius;
 66 
 67     private Thread thread;
 68 
 69     BitmapShader bitmapShader;
 70 
 71     public FlikerProgressBar(Context context) {
 72         this(context, null, 0);
 73     }
 74 
 75     public FlikerProgressBar(Context context, AttributeSet attrs) {
 76         this(context, attrs, 0);
 77     }
 78 
 79     public FlikerProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
 80         super(context, attrs, defStyleAttr);
 81         initAttrs(attrs);
 82     }
 83 
 84     private void initAttrs(AttributeSet attrs) {
 85         TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.FlikerProgressBar);
 86         try {
 87             textSize = (int) ta.getDimension(R.styleable.FlikerProgressBar_textSize, 12);
 88             loadingColor = ta.getColor(R.styleable.FlikerProgressBar_loadingColor, Color.parseColor("#40c4ff"));
 89             stopColor = ta.getColor(R.styleable.FlikerProgressBar_stopColor, Color.parseColor("#ff9800"));
 90             radius = (int) ta.getDimension(R.styleable.FlikerProgressBar_radius, 0);
 91             borderWidth = (int) ta.getDimension(R.styleable.FlikerProgressBar_borderWidth, 1);
 92         } finally {
 93             ta.recycle();
 94         }
 95     }
 96 
 97     private void init() {
 98         bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
 99         bgPaint.setStyle(Paint.Style.STROKE);
100         bgPaint.setStrokeWidth(borderWidth);
101 
102         pgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
103         pgPaint.setStyle(Paint.Style.FILL);
104 
105         textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
106         textPaint.setTextSize(textSize);
107 
108         textRect = new Rect();
109         bgRectf = new RectF(borderWidth, borderWidth, getMeasuredWidth() - borderWidth, getMeasuredHeight() - borderWidth);
110 
111         if(isStop){
112             progressColor = stopColor;
113         } else{
114             progressColor = loadingColor;
115         }
116 
117         flikerBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.flicker);
118         flickerLeft = -flikerBitmap.getWidth();
119 
120         initPgBimap();
121     }
122 
123     private void initPgBimap() {
124         pgBitmap = Bitmap.createBitmap(getMeasuredWidth() - borderWidth, getMeasuredHeight() - borderWidth, Bitmap.Config.ARGB_8888);
125         pgCanvas = new Canvas(pgBitmap);
126         thread = new Thread(this);
127         thread.start();
128     }
129 
130 
131     @Override
132     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
133         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
134         int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
135         int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
136         int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
137         int height = 0;
138         switch (heightSpecMode){
139             case MeasureSpec.AT_MOST:
140                 height = dp2px(DEFAULT_HEIGHT_DP);
141                 break;
142             case MeasureSpec.EXACTLY:
143             case MeasureSpec.UNSPECIFIED:
144                 height = heightSpecSize;
145                 break;
146         }
147         setMeasuredDimension(widthSpecSize, height);
148 
149         if(pgBitmap == null){
150             init();
151         }
152 
153     }
154 
155     @Override
156     protected void onDraw(Canvas canvas) {
157         super.onDraw(canvas);
158 
159         //背景
160         drawBackGround(canvas);
161 
162         //进度
163         drawProgress(canvas);
164 
165          //进度text
166         drawProgressText(canvas);
167 
168         //变色处理
169         drawColorProgressText(canvas);
170     }
171 
172     /**
173      * 边框
174      * @param canvas
175      */
176     private void drawBackGround(Canvas canvas) {
177         bgPaint.setColor(progressColor);
178         //left、top、right、bottom不要贴着控件边,否则border只有一半绘制在控件内,导致圆角处线条显粗
179         canvas.drawRoundRect(bgRectf, radius, radius, bgPaint);
180     }
181 
182     /**
183      * 进度
184      */
185     private void drawProgress(Canvas canvas) {
186         pgPaint.setColor(progressColor);
187 
188         float right = (progress / maxProgress) * getMeasuredWidth();
189         pgCanvas.save();
190         pgCanvas.clipRect(0, 0, right, getMeasuredHeight());
191         pgCanvas.drawColor(progressColor);
192         pgCanvas.restore();
193 
194         if(!isStop){
195             pgPaint.setXfermode(xfermode);
196             pgCanvas.drawBitmap(flikerBitmap, flickerLeft, 0, pgPaint);
197             pgPaint.setXfermode(null);
198         }
199 
200         //控制显示区域
201         bitmapShader = new BitmapShader(pgBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
202         pgPaint.setShader(bitmapShader);
203         canvas.drawRoundRect(bgRectf, radius, radius, pgPaint);
204     }
205 
206     /**
207      * 进度提示文本
208      * @param canvas
209      */
210     private void drawProgressText(Canvas canvas) {
211         textPaint.setColor(progressColor);
212         progressText = getProgressText();
213         textPaint.getTextBounds(progressText, 0, progressText.length(), textRect);
214         int tWidth = textRect.width();
215         int tHeight = textRect.height();
216         float xCoordinate = (getMeasuredWidth() - tWidth) / 2;
217         float yCoordinate = (getMeasuredHeight() + tHeight) / 2;
218         canvas.drawText(progressText, xCoordinate, yCoordinate, textPaint);
219     }
220 
221     /**
222      * 变色处理
223      * @param canvas
224      */
225     private void drawColorProgressText(Canvas canvas) {
226         textPaint.setColor(Color.WHITE);
227         int tWidth = textRect.width();
228         int tHeight = textRect.height();
229         float xCoordinate = (getMeasuredWidth() - tWidth) / 2;
230         float yCoordinate = (getMeasuredHeight() + tHeight) / 2;
231         float progressWidth = (progress / maxProgress) * getMeasuredWidth();
232         if(progressWidth > xCoordinate){
233             canvas.save();
234             float right = Math.min(progressWidth, xCoordinate + tWidth * 1.1f);
235             canvas.clipRect(xCoordinate, 0, right, getMeasuredHeight());
236             canvas.drawText(progressText, xCoordinate, yCoordinate, textPaint);
237             canvas.restore();
238         }
239     }
240 
241     public void setProgress(float progress){
242         if(!isStop){
243             if(progress < maxProgress){
244                 this.progress = progress;
245             } else {
246                 this.progress = maxProgress;
247                 finishLoad();
248             }
249             invalidate();
250         }
251     }
252 
253     public void setStop(boolean stop) {
254         isStop = stop;
255         if(isStop){
256             progressColor = stopColor;
257             thread.interrupt();
258         } else {
259             progressColor = loadingColor;
260             thread = new Thread(this);
261             thread.start();
262         }
263         invalidate();
264     }
265 
266     public void finishLoad() {
267         isFinish = true;
268         setStop(true);
269     }
270 
271     public void toggle(){
272         if(!isFinish){
273             if(isStop){
274                 setStop(false);
275             } else {
276                 setStop(true);
277             }
278         }
279     }
280 
281     @Override
282     public void run() {
283         int width = flikerBitmap.getWidth();
284         try {
285             while (!isStop && !thread.isInterrupted()){
286                 flickerLeft += dp2px(5);
287                 float progressWidth = (progress / maxProgress) * getMeasuredWidth();
288                 if(flickerLeft >= progressWidth){
289                     flickerLeft = -width;
290                 }
291                 postInvalidate();
292                 Thread.sleep(20);
293             }
294         }catch (InterruptedException e) {
295             e.printStackTrace();
296         }
297     }
298 
299     /**
300      * 重置
301      */
302     public void reset(){
303         setStop(true);
304         progress = 0;
305         isFinish = false;
306         isStop = false;
307         progressColor = loadingColor;
308         progressText = "";
309         flickerLeft = -flikerBitmap.getWidth();
310         initPgBimap();
311     }
312 
313     public float getProgress() {
314         return progress;
315     }
316 
317     public boolean isStop() {
318         return isStop;
319     }
320 
321     public boolean isFinish() {
322         return isFinish;
323     }
324 
325     private String getProgressText() {
326         String text= "";
327         if(!isFinish){
328             if(!isStop){
329                 text = "下载中" + progress + "%";
330             } else {
331                 text = "继续";
332             }
333         } else{
334             text = "下载完成";
335         }
336 
337         return text;
338     }
339 
340     private int dp2px(int dp){
341         float density = getContext().getResources().getDisplayMetrics().density;
342         return (int) (dp * density);
343     }
344 }

在MainActivity中使用,直接贴出代码:

 1 public class MainActivity extends AppCompatActivity implements View.OnClickListener,Runnable{
 2 
 3     private FlikerProgressBar flikerProgressBar,roundProgressBar;
 4     private Thread downLoadThread;
 5     private Handler handler = new Handler(){
 6         @Override
 7         public void handleMessage(@NonNull Message msg) {
 8             super.handleMessage(msg);
 9             flikerProgressBar.setProgress(msg.arg1);
10             roundProgressBar.setProgress(msg.arg1);
11             if(msg.arg1 == 100){
12                 flikerProgressBar.finishLoad();
13                 roundProgressBar.finishLoad();
14             }
15         }
16     };
17 
18     @Override
19     protected void onCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21         setContentView(R.layout.activity_main);
22         initView();
23     }
24 
25     private void initView(){
26         flikerProgressBar = (FlikerProgressBar)findViewById(R.id.fliker1);
27         roundProgressBar = (FlikerProgressBar)findViewById(R.id.fliker2);
28         flikerProgressBar.setOnClickListener(this);
29         roundProgressBar.setOnClickListener(this);
30         downLoad();
31     }
32 
33     private void downLoad(){
34         downLoadThread = new Thread(this);
35         downLoadThread.start();
36     }
37 
38     public void reLoad(View view){
39         downLoadThread.interrupt();
40         //重新加载
41         flikerProgressBar.reset();
42         roundProgressBar.reset();
43         downLoad();
44     }
45 
46     @Override
47     public void onClick(View view) {
48         if(!flikerProgressBar.isFinish()){
49             flikerProgressBar.toggle();
50             roundProgressBar.toggle();
51             if(flikerProgressBar.isStop()){
52                 downLoadThread.interrupt();
53             } else {
54                 downLoad();
55             }
56         }
57     }
58 
59     @Override
60     public void run() {
61         try {
62             while( ! downLoadThread.isInterrupted()){
63                 float progress = flikerProgressBar.getProgress();
64                 progress  += 2;
65                 Thread.sleep(200);
66                 Message message = handler.obtainMessage();
67                 message.arg1 = (int) progress;
68                 handler.sendMessage(message);
69                 if(progress == 100){
70                     break;
71                 }
72             }
73         }catch (InterruptedException e) {
74             e.printStackTrace();
75         }
76     }
77 }

最后就是布局文件的代码:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:app="http://schemas.android.com/apk/res-auto"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:orientation="vertical"
 8     tools:context=".MainActivity">
 9     <androidx.cardview.widget.CardView
10         app:cardElevation="5dp"
11         android:layout_width="match_parent"
12         android:layout_height="wrap_content">
13         <TextView
14             android:gravity="center"
15             android:textStyle="bold"
16             android:textSize="16sp"
17             android:text="下载进度条"
18             android:textColor="#FFF"
19             android:background="#01CCFF"
20             android:layout_width="match_parent"
21             android:layout_height="45dp" />
22     </androidx.cardview.widget.CardView>
23 
24    <LinearLayout
25        android:padding="20dp"
26        android:orientation="vertical"
27        android:layout_width="match_parent"
28        android:layout_height="match_parent">
29        <androidx.cardview.widget.CardView
30            app:cardElevation="5dp"
31            android:layout_marginTop="30dp"
32            android:layout_width="match_parent"
33            android:layout_height="wrap_content">
34            <com.example.download.FlikerProgressBar
35                android:id="@+id/fliker1"
36                android:layout_width="match_parent"
37                android:layout_height="wrap_content"
38                app:textSize="12sp"
39                app:loadingColor="#01CCFF"
40                app:stopColor="#ff9800"/>
41        </androidx.cardview.widget.CardView>
42 
43        <androidx.cardview.widget.CardView
44            app:cardElevation="5dp"
45            app:cardCornerRadius="18dp"
46            android:layout_marginTop="30dp"
47            android:layout_width="match_parent"
48            android:layout_height="wrap_content">
49            <com.example.download.FlikerProgressBar
50                android:id="@+id/fliker2"
51                android:layout_width="match_parent"
52                android:layout_height="wrap_content"
53                app:textSize="12sp"
54                app:loadingColor="#01CCFF"
55                app:stopColor="#ff9800"
56                app:radius="20dp"/>
57        </androidx.cardview.widget.CardView>
58 
59        <Button
60            android:text="重新下载"
61            android:onClick="reLoad"
62            android:layout_marginTop="30dp"
63            android:layout_marginLeft="20dp"
64            android:layout_marginRight="20dp"
65            android:background="@drawable/button_five_theme_gray"
66            android:textColor="@drawable/button_five_theme_gray"
67            android:layout_width="match_parent"
68            android:layout_height="45dp" />
69    </LinearLayout>
70 </LinearLayout>

猜你喜欢

转载自www.cnblogs.com/Mr-Deng/p/11765683.html