自定义Progress小控件

progress各种各样的都有,自定义大多数也是简单的,根据业务需求来自己定义,记录一下,先上效果图

自定义Progress小控件

本来想找个第三方改改就上的,不过自己的业务需求有点不搭,一下子没找到合适的,也没这么多时间去找了,想想还是自己写个吧,因为也简单

主要就是需求就是椭圆进度,百分比跟随渐变背景,这样一想其实就是一个布局,然后控制里面的进度长度,或者移动,我这是控制长度,这样毕竟简单,而且扩展好,以后进度条有什么奇葩需求也好改

  1 import android.content.Context;
  2 import android.content.res.TypedArray;
  3 import android.graphics.Color;
  4 import android.support.annotation.AttrRes;
  5 import android.support.annotation.NonNull;
  6 import android.support.annotation.Nullable;
  7 import android.util.AttributeSet;
  8 import android.view.Gravity;
  9 import android.view.View;
 10 import android.view.ViewGroup;
 11 import android.widget.FrameLayout;
 12 import android.widget.TextView;
 13 
 14 import com.app.commonlibrary.R;
 15 
 16 /**
 17  * Created by LiuZhen on 2017/7/8.
 18  */
 19 
 20 public class UpdateProgressBar extends FrameLayout {
 21 
 22     private TextView tv_progress;
 23     private int width;
 24     private ViewGroup.LayoutParams params;
 25     /**
 26      * The progress text offset.
 27      */
 28     private int mOffset;
 29     /**
 30      * The progress text size.
 31      */
 32     private float mTextSize;
 33     /**
 34      * The progress text color.
 35      */
 36     private int mTextColor;
 37     private float default_text_size;
 38     /**
 39      * The progress area bar color.
 40      */
 41     private int mReachedBarColor;
 42     /**
 43      * The bar unreached area color.
 44      */
 45     private int mUnreachedBarColor;
 46     private final int default_reached_color = Color.rgb(66, 145, 241);
 47     private final int default_unreached_color = Color.rgb(204, 204, 204);
 48     private final int default_text_color = Color.rgb(66, 145, 241);
 49 
 50     public UpdateProgressBar(@NonNull Context context) {
 51         this(context,null);
 52     }
 53 
 54     public UpdateProgressBar(@NonNull Context context, @Nullable AttributeSet attrs) {
 55         this(context, attrs,0);
 56     }
 57 
 58     public UpdateProgressBar(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
 59         super(context, attrs, defStyleAttr);
 60         init(attrs, defStyleAttr);
 61     }
 62 
 63     @Override
 64     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 65 
 66         int desiredWidth = 100;
 67         int desiredHeight = 100;
 68 
 69         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
 70         int widthSize = MeasureSpec.getSize(widthMeasureSpec);
 71         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 72         int heightSize = MeasureSpec.getSize(heightMeasureSpec);
 73 
 74         int height;
 75 
 76         //Measure Width
 77         if (widthMode == MeasureSpec.EXACTLY) {
 78             //Must be this size
 79             width = widthSize;
 80         } else if (widthMode == MeasureSpec.AT_MOST) {
 81             //Can't be bigger than...
 82             width = Math.min(desiredWidth, widthSize);
 83         } else {
 84             //Be whatever you want
 85             width = desiredWidth;
 86         }
 87 
 88         //Measure Height
 89         if (heightMode == MeasureSpec.EXACTLY) {
 90             //Must be this size
 91             height = heightSize;
 92         } else if (heightMode == MeasureSpec.AT_MOST) {
 93             //Can't be bigger than...
 94             height = Math.min(desiredHeight, heightSize);
 95         } else {
 96             //Be whatever you want
 97             height = desiredHeight;
 98         }
 99 
100         int childCount = getChildCount();
101         for (int i = 0; i < childCount; i++) {
102             View child = getChildAt(i);
103             ViewGroup.LayoutParams lp = child.getLayoutParams();
104             int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
105             int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height);
106             child.measure(childWidthSpec, childHeightSpec);
107         }
108         params = tv_progress.getLayoutParams();
109         params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
110         params.height = ViewGroup.LayoutParams.MATCH_PARENT;
111         tv_progress.setLayoutParams(params);
112         height = tv_progress.getMeasuredHeight();
113         //MUST CALL THIS
114         setMeasuredDimension(width, height);
115     }
116 
117 
118     private void init(AttributeSet attrs, int defStyleAttr){
119 
120         default_text_size = 8;
121         //load styled attributes.
122         final TypedArray attributes = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.UpdateProgressBar,
123                 defStyleAttr, 0);
124 
125         mTextSize = attributes.getDimension(R.styleable.UpdateProgressBar_update_text_size, default_text_size);
126         mReachedBarColor = attributes.getResourceId(R.styleable.UpdateProgressBar_update_reached_color, default_reached_color);
127         mUnreachedBarColor = attributes.getResourceId(R.styleable.UpdateProgressBar_update_unreached_color, default_unreached_color);
128         mTextColor = attributes.getColor(R.styleable.UpdateProgressBar_update_text_color, default_text_color);
129 
130         setDefaultProgressBar();
131 
132         mOffset = px2dip(3);
133 
134         attributes.recycle();
135     }
136 
137     private void setDefaultProgressBar(){
138         setBackgroundResource(mUnreachedBarColor);
139         tv_progress = new TextView(getContext());
140         tv_progress.setTextSize(mTextSize);
141         tv_progress.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
142         tv_progress.setTextColor(mTextColor);
143         tv_progress.setLines(1);
144         tv_progress.setBackgroundResource(mReachedBarColor);
145         tv_progress.setPadding(dip2px(4),0,dip2px(8),0);
146         tv_progress.setText("0 %");
147         addView(tv_progress);
148     }
149 
150     public void setProgress(int progress){
151         tv_progress.setText(progress+"%");
152         int proWidth = width*progress/100;
153         if (tv_progress.getMeasuredWidth() < proWidth) {
154             //这里不能填充mOffset,因为是椭圆进度条,填充会导致椭圆宽度被进度条覆盖,导致不美观
155 //            tv_progress.setLayoutParams(params);
156             tv_progress.setWidth(proWidth);
157         }
158     }
159 
160     /**
161      * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
162      */
163     public int dip2px(float dpValue) {
164         final float scale = getContext().getResources().getDisplayMetrics().density;
165         return (int) (dpValue * scale + 0.5f);
166     }
167 
168     /**
169      * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
170      */
171     public int px2dip(float pxValue) {
172         final float scale = getContext().getResources().getDisplayMetrics().density;
173         return (int) (pxValue / scale + 0.5f);
174     }
175 
176     /**
177      * 将px值转换为sp值,保证文字大小不变
178      */
179     public int px2sp(float pxValue) {
180         final float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
181         return (int) (pxValue / fontScale + 0.5f);
182     }
183 
184     /**
185      * 将sp值转换为px值,保证文字大小不变
186      */
187     public int sp2px(float spValue) {
188         final float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
189         return (int) (spValue * fontScale + 0.5f);
190     }
191 
192 }
UpdateProgressBar

用法布局文件

1 <com.progressbar.example.UpdateProgressBar
2         xmlns:pro="http://schemas.android.com/apk/res-auto"
3         android:id="@+id/progress"
4         android:layout_width="match_parent"
5         android:layout_height="wrap_content"
6         pro:update_text_size="6sp"
7         pro:update_text_color="#FFFFFF"
8         pro:update_unreached_color="@drawable/shape_corner_progressbg"
9         pro:update_reached_color="@drawable/shape_corner_progressbar"/>
 1 import android.os.Bundle;
 2 import android.support.v7.app.ActionBarActivity;
 3 import android.support.v7.app.AppCompatActivity;
 4 import android.view.Menu;
 5 import android.view.MenuItem;
 6 import android.widget.Toast;
 7 
 8 import com.progressbar.NumberProgressBar;
 9 
10 import java.util.Timer;
11 import java.util.TimerTask;
12 
13 
14 public class MainActivity extends AppCompatActivity {
15     private Timer timer;
16     private UpdateProgressBar progressBar;
17     private int progress;
18 
19     @Override
20     protected void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.activity_main);
23         progressBar = (UpdateProgressBar)findViewById(R.id.progress);
24 
25         timer = new Timer();
26         timer.schedule(new TimerTask() {
27             @Override
28             public void run() {
29                 runOnUiThread(new Runnable() {
30                     @Override
31                     public void run() {
32                         progress++;
33                         progressBar.setProgress(progress);
34                         if(progress == 100) {
35                             Toast.makeText(getApplicationContext(), getString(R.string.finish), Toast.LENGTH_SHORT).show();
36 //                            progress = 0;
37 //                            progressBar.setProgress(0);
38                             timer.cancel();
39                         }
40                     }
41                 });
42             }
43         }, 1000, 100);
44     }
45 
46     @Override
47     public boolean onCreateOptionsMenu(Menu menu) {
48         // Inflate the menu; this adds items to the action bar if it is present.
49         getMenuInflater().inflate(R.menu.main, menu);
50         return true;
51     }
52 
53     @Override
54     public boolean onOptionsItemSelected(MenuItem item) {
55         // Handle action bar item clicks here. The action bar will
56         // automatically handle clicks on the Home/Up button, so long
57         // as you specify a parent activity in AndroidManifest.xml.
58         int id = item.getItemId();
59         if (id == R.id.action_settings) {
60             return true;
61         }
62         return super.onOptionsItemSelected(item);
63     }
64 
65     @Override
66     protected void onDestroy() {
67         super.onDestroy();
68         timer.cancel();
69     }
70 }
MainActivity

渐变背景

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <shape xmlns:android="http://schemas.android.com/apk/res/android">
 3 
 4     <solid android:color="#4984f2"/>
 5 
 6     <gradient
 7         android:startColor="#4984f2"
 8         android:endColor="#000" />
 9 
10     <corners
11         android:topLeftRadius="15dp"
12         android:topRightRadius="15dp"
13         android:bottomLeftRadius="15dp"
14         android:bottomRightRadius="15dp"/>
15 </shape>
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <shape xmlns:android="http://schemas.android.com/apk/res/android">
 3 
 4     <solid android:color="#dadada"/>
 5 
 6     <gradient
 7     android:startColor="#FFF"
 8     android:endColor="#000" />
 9 
10 
11     <corners
12         android:topLeftRadius="15dp"
13         android:topRightRadius="15dp"
14         android:bottomLeftRadius="15dp"
15         android:bottomRightRadius="15dp"/>
16 </shape>