zoukankan      html  css  js  c++  java
  • 下载进度条

    先看一下效果图:

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

    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>
  • 相关阅读:
    在简单地形上小车运动轨迹的数学表达(一)
    结尾
    第十四章 多线程编程
    第十五章 进程池与线程池
    第十章 信号
    第十一章 定时器
    第十三章 多进程编程
    第八章 高性能服务器程序框架
    KMP 专场 POJ2752
    约瑟夫问题 双链表实现
  • 原文地址:https://www.cnblogs.com/Mr-Deng/p/11765683.html
Copyright © 2011-2022 走看看