一. 前言 系统的ProgressBar或者SeekBar本身不支持竖直布局,只有通过旋转的方式才可以达到效果。
Github地址:XLSeekBar
二. 自定义View 1. 自定义用到的属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 private Paint paint_bg;private Paint paint_progress;private Paint paint_thumb;private int lineSize = 10 ;private int lineColorBg = Color.BLACK;private int lineColorProgress = Color.MAGENTA;public static final int PROGRESS = 0 ;public static final int SLIDE = 1 ;private int lineStyle = SLIDE;private int cx = 0 ;private int cy = 0 ;private int radius = 10 ;private int thumbScale = 4 ;private int position;private int currentProgress = 50 ;private int maxProgress = 100 ;private OnProgressChangeListener listener;
2. 在values文件夹下自定义属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?xml version="1.0" encoding="utf-8"?> <resources > <declare-styleable name ="MySeekBar" > <attr name ="lineSize" format ="integer" /> <attr name ="lineColorBg" format ="color" /> <attr name ="lineColorProgress" format ="color" /> <attr name ="lineStyle" format ="enum" > <enum name ="PROGRESS" value ="0" /> <enum name ="SLIDE" value ="1" /> </attr > <attr name ="currentProgress" format ="integer" /> <attr name ="maxProgress" format ="integer" /> </declare-styleable > </resources >
3. 创建构造方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public MySeekBar (Context context, int lineSize, int lineStyle, int lineColorBg, int lineColorProgress, int currentProgress ,int maxProgress) { super (context); this .lineSize = lineSize; this .lineStyle = lineStyle; this .lineColorBg = lineColorBg; this .lineColorProgress = lineColorProgress; this .currentProgress = currentProgress; this .maxProgress = maxProgress; init(); } public MySeekBar (Context context, @Nullable AttributeSet attrs) { super (context, attrs); if (attrs != null ){ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MySeekBar); lineSize = typedArray.getInteger(R.styleable.MySeekBar_lineSize,lineSize); lineColorBg = typedArray.getColor( R.styleable.MySeekBar_lineColorBg, lineColorBg ); lineColorProgress = typedArray.getColor( R.styleable.MySeekBar_lineColorProgress, lineColorProgress ); lineStyle = typedArray.getInt(R.styleable.MySeekBar_lineStyle, lineStyle); currentProgress = typedArray.getInteger( R.styleable.MySeekBar_currentProgress, currentProgress ); maxProgress = typedArray.getInteger( R.styleable.MySeekBar_maxProgress, maxProgress ); typedArray.recycle(); } init(); }
4. 绘制进度背景,进度以及进度文本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 @Override protected void onDraw (Canvas canvas) { super .onDraw(canvas); if (getWidth() > getHeight()){ canvas.drawLine( 0 , getHeight() >> 1 , getWidth(), getHeight() >> 1 , paint_bg ); if (position > 0 ){ canvas.drawLine( 0 , getHeight() >> 1 , position, getHeight() >> 1 , paint_progress ); } if (lineStyle == SLIDE) { radius = getHeight() / thumbScale; cx = radius; cy = getHeight() / 2 ; if (position < radius) cx = radius; else cx = Math.min(position, getWidth() - radius); canvas.drawCircle(cx,cy,radius,paint_thumb); } }else { canvas.drawLine( getWidth() >> 1 , 0 , getWidth() >> 1 , getHeight(), paint_bg ); if (position < getHeight()){ canvas.drawLine( getWidth() >> 1 , getHeight(), getWidth() >> 1 , position, paint_progress ); } if (lineStyle == SLIDE) { radius = getWidth() / thumbScale; cx = getWidth() / 2 ; cy = getHeight() - radius; if (position < radius) cy = radius; else if (position < getHeight() - radius){ cy = position; }else { cy = getHeight()-radius; } canvas.drawCircle(cx,cy,radius,paint_thumb); } } }
5. 回调进度事件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent (MotionEvent event) { if (lineStyle == SLIDE){ switch (event.getAction()){ case MotionEvent.ACTION_DOWN: thumbScale /= 2 ; if (getWidth() > getHeight()){ position = (int ) event.getX(); }else { position = (int ) event.getY(); } callBack(); break ; case MotionEvent.ACTION_MOVE: if (getWidth() > getHeight()){ position = (int ) event.getX(); }else { position = (int ) event.getY(); } callBack(); break ; case MotionEvent.ACTION_UP: thumbScale *= 2 ; break ; } invalidate(); } return true ; } private void callBack () { if (listener != null ){ if (getWidth() > getHeight()){ currentProgress = position * maxProgress / getWidth(); }else { currentProgress = (getHeight() - position) * maxProgress / getHeight(); } if (currentProgress <= 0 ) currentProgress = 0 ; if (currentProgress >= maxProgress) currentProgress = maxProgress; listener.progressChanged(currentProgress); } } public interface OnProgressChangeListener { void progressChanged (float progress) ; }
6. 视图宽高改变的影响解决 1 2 3 4 5 6 7 8 9 10 11 12 @Override protected void onSizeChanged (int w, int h, int oldw, int oldh) { super .onSizeChanged(w, h, oldw, oldh); if (getWidth() > getHeight()){ position = currentProgress * getWidth() / maxProgress; }else { position = getHeight() - (currentProgress * getHeight() / maxProgress); } }
三. 具体的使用 首先需要添加依赖,添加依赖之后,在布局文件中这样调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" tools:context =".MainActivity" > <swu.xl.xlseekbar.MySeekBar android:layout_marginTop="30dp" android:background="#999999" android:layout_width="match_parent" android:layout_height="30dp" app:currentProgress="80" app:maxProgress="100" app:lineStyle="PROGRESS" /> <swu.xl.xlseekbar.MySeekBar android:id="@+id/seek_bar_hor" android:layout_marginTop="90dp" android:background="#999999" android:layout_width="match_parent" android:layout_height="30dp" app:currentProgress="50" app:maxProgress="100" app:lineStyle="SLIDE" /> <swu.xl.xlseekbar.MySeekBar android:id="@+id/seek_bar_ver" android:layout_centerInParent="true" android:background="#999999" android:layout_width="30dp" android:layout_height="300dp" app:currentProgress="50" app:maxProgress="100" app:lineStyle="SLIDE" app:lineColorBg="#ffffff" app:lineColorProgress="@color/colorAccent" /> </RelativeLayout >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class MainActivity extends AppCompatActivity { @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); MySeekBar mySeekBarHor = findViewById(R.id.seek_bar_hor); MySeekBar mySeekBarVer = findViewById(R.id.seek_bar_ver); mySeekBarHor.setProgressChangeListener(new MySeekBar.OnProgressChangeListener() { @Override public void progressChanged (float progress) { Toast.makeText(MainActivity.this , "横向滑动条的进度:" +progress, Toast.LENGTH_SHORT).show(); } }); mySeekBarVer.setProgressChangeListener(new MySeekBar.OnProgressChangeListener() { @Override public void progressChanged (float progress) { Toast.makeText(MainActivity.this , "竖向滑动条的进度:" +progress, Toast.LENGTH_SHORT).show(); } }); } }