Seekbar常規使用方式通過xml布局方式實現,但是由於我們的是sdk,不能有xml布局,所以SeekBar使用純代碼實現。但是這樣就遇到了很多問題。
首先是SeekBar設置setProgressDrawable問題。因為我們的是視頻播放器,所以這個SeekBar需要有背景、緩衝進度和播放進度,最好的方法就是用layer-list 的xml布局實現,類似這樣:
<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background"> <shape> <solid android:color="#cc999999" /> <size android:height="3dp" /> <corners android:radius="1.5dip" /> </shape> </item> <item android:id="@android:id/secondaryProgress"> <clip> <shape> <solid android:color="#9f4ef1" /> <size android:height="3dp" /> <corners android:radius="1.5dip" /> </shape> </clip> </item> <item android:id="@android:id/progress"> <clip> <shape> <solid android:color="#0add2c" /> <size android:height="3dp" /> <corners android:radius="1.5dip" /> </shape> </clip> </item></layer-list>
這是正常的xml布局樣式,這樣的布局我們需要用java純代碼實現,如下:
Drawable[] drawables = new Drawable[3] GradientDrawable roundRect = new GradientDrawable() roundRect.setShape(GradientDrawable.RECTANGLE) roundRect.setColor(Color.parseColor(ViewUtils.getInstance().progressColor1)) roundRect.setSize(1,FormatUtils.dip2px(1,context)) roundRect.setCornerRadius(FormatUtils.dip2px(1.5f,context)) drawables[0] = roundRect roundRect = new GradientDrawable() roundRect.setShape(GradientDrawable.RECTANGLE) roundRect.setColor(Color.parseColor(ViewUtils.getInstance().progressColor3)) roundRect.setSize(1,FormatUtils.dip2px(1,context)) roundRect.setCornerRadius( FormatUtils.dip2px(1.5f,context)) ClipDrawable clipDrawable = new ClipDrawable(roundRect, Gravity.LEFT, VERTICAL) drawables[1] =clipDrawable roundRect = new GradientDrawable() roundRect.setShape(GradientDrawable.RECTANGLE) roundRect.setColor(Color.parseColor(ViewUtils.getInstance().colorProgress)) roundRect.setSize(1,FormatUtils.dip2px(1,context)) roundRect.setCornerRadius(FormatUtils.dip2px(1.5f,context)) clipDrawable = new ClipDrawable(roundRect, Gravity.LEFT, VERTICAL) drawables[2] = clipDrawable LayerDrawable layerDrawable = new LayerDrawable(drawables) layerDrawable.setId(0,android.R.id.background) layerDrawable.setId(1,android.R.id.secondaryProgress) layerDrawable.setId(2,android.R.id.progress)
然後直接SeekBar.setProgressDrawable就可以。
第二個問題是,SeekBar高度問題,這個才是最坑的,研究了很多,SeekBar如果用xml布局會有兩個方法android:maxHeight="4dp"和android:minHeight="4dp",但是如果是java寫,就只有progressBar.setMinimumHeight(FormatUtils.dip2px(1,context));,用來設置最小高度,這樣的話就有一個問題,如果你SeekBar設置seekBar.setThumb( bitmapDrawable);哪麼SeekBar的進度條高度也會變得和Thumb一樣高,會撐滿。這裡有兩個解決辦法:
一是在6.0以上的手機適用,就是在上面設置layerDrawable代碼後面再加兩句
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { layerDrawable.setLayerHeight(0,FormatUtils.dip2px(2,context)) layerDrawable.setLayerHeight(1,FormatUtils.dip2px(2,context)) layerDrawable.setLayerHeight(2,FormatUtils.dip2px(2,context)) layerDrawable.setLayerGravity(0,Gravity.CENTER_VERTICAL) layerDrawable.setLayerGravity(1,Gravity.CENTER_VERTICAL) layerDrawable.setLayerGravity(2,Gravity.CENTER_VERTICAL) }
整體是這樣:
public static Drawable genSeekProgressDrawable(Context context) { Drawable[] drawables = new Drawable[3] GradientDrawable roundRect = new GradientDrawable() roundRect.setShape(GradientDrawable.RECTANGLE) roundRect.setColor(Color.parseColor(ViewUtils.getInstance().progressColor1)) roundRect.setSize(1,FormatUtils.dip2px(1,context)) roundRect.setCornerRadius(FormatUtils.dip2px(1.5f,context)) drawables[0] = roundRect roundRect = new GradientDrawable() roundRect.setShape(GradientDrawable.RECTANGLE) roundRect.setColor(Color.parseColor(ViewUtils.getInstance().progressColor3)) roundRect.setSize(1,FormatUtils.dip2px(1,context)) roundRect.setCornerRadius( FormatUtils.dip2px(1.5f,context)) ClipDrawable clipDrawable = new ClipDrawable(roundRect, Gravity.LEFT, VERTICAL) drawables[1] =clipDrawable roundRect = new GradientDrawable() roundRect.setShape(GradientDrawable.RECTANGLE) roundRect.setColor(Color.parseColor(ViewUtils.getInstance().colorProgress)) roundRect.setSize(1,FormatUtils.dip2px(1,context)) roundRect.setCornerRadius(FormatUtils.dip2px(1.5f,context)) clipDrawable = new ClipDrawable(roundRect, Gravity.LEFT, VERTICAL) drawables[2] = clipDrawable LayerDrawable layerDrawable = new LayerDrawable(drawables) layerDrawable.setId(0,android.R.id.background) layerDrawable.setId(1,android.R.id.secondaryProgress) layerDrawable.setId(2,android.R.id.progress) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { layerDrawable.setLayerHeight(0,FormatUtils.dip2px(2,context)) layerDrawable.setLayerHeight(1,FormatUtils.dip2px(2,context)) layerDrawable.setLayerHeight(2,FormatUtils.dip2px(2,context)) layerDrawable.setLayerGravity(0,Gravity.CENTER_VERTICAL) layerDrawable.setLayerGravity(1,Gravity.CENTER_VERTICAL) layerDrawable.setLayerGravity(2,Gravity.CENTER_VERTICAL) } return layerDrawable }
二是適配所有的手機,這樣的話我沒有找到好的方法,只能用反射去修改SeekBar的父類的父類progressBar的最大高度,mMaxHeight的值,這個就是設置SeekBar的最大高度的值,xml代碼android:maxHeight="4dp"其實改變的就是這個的值。
代碼也很簡單:
try { Class<?> superclass = seekBar.getClass().getSuperclass().getSuperclass(); Field mMaxHeight = superclass.getDeclaredField("mMaxHeight"); mMaxHeight.setAccessible(true); mMaxHeight.set(seekBar,FormatUtils.dip2px(2,context)); } catch (Exception e) { e.printStackTrace(); }
其實最好的方法就是兩個一起用,6.0以下用反射,6.0以上用layerDrawable的方法去實現。這是我個人研究的辦法,網上也沒有實現的辦法,找了很久。如果有更好的求告知啊!!!!!