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 }
用法布局文件
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 }
渐变背景
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>