SeekBar是用来调节参数值的,系统默认的一般都不太适合我们,需要我们自定义,
里面也有一个RxJava背压的具体应用
废话不多说,看图
packagecom.example.helang.seekbar;
importandroid.content.Context;
importandroid.graphics.Bitmap;
importandroid.graphics.Canvas;
importandroid.graphics.Color;
importandroid.graphics.Matrix;
importandroid.graphics.Paint;
importandroid.graphics.RectF;
importandroid.graphics.drawable.BitmapDrawable;
importandroid.graphics.drawable.Drawable;
importandroid.support.annotation.Nullable;
importandroid.util.AttributeSet;
importandroid.view.MotionEvent;
importandroid.view.View;
importjava.util.concurrent.TimeUnit;
importio.reactivex.Observable;
importio.reactivex.ObservableEmitter;
importio.reactivex.ObservableOnSubscribe;
importio.reactivex.android.schedulers.AndroidSchedulers;
importio.reactivex.functions.Consumer;
/**
* 自定义拖动seekBar
*/
publicclassCustomSeekBarextendsView{
privatestaticfinalString TAG ="CustomSeekBar";
privatestaticfinalintradius =65;//中间圆形进度条的半径
privatestaticfinalintthumbSize =200;
privateintbackgroundLineSize =10;//背景线的宽度
privateintforegroundLineSize =18;//进度的宽度
privateintlineSize;//整条背景线的长度
privatefloattouchY;
privateBitmap thumbBitmap;
privatePaint paint;
privatePaint circlePaint;//绘制进度条的paint
privateRectF backgroundLineRect =newRectF();//背景矩形
privateRectF foregroundLineRect =newRectF();//进度矩形
privatefloatcurrentDegrees =0;//当前的进度,百分比例,不带百分号
privateOnProgressListener onProgressListener;
publicvoidsetOnProgressListener(OnProgressListener onProgressListener){
this.onProgressListener = onProgressListener;
}
publicCustomSeekBar(Context context){
this(context,null);
}
publicCustomSeekBar(Context context, @Nullable AttributeSet attrs){
this(context, attrs,0);
}
publicCustomSeekBar(Context context, @Nullable AttributeSet attrs,intdefStyleAttr){
super(context, attrs, defStyleAttr);
initBitmap();
initPaint();
}
/**
* init bitmap
*/
privatevoidinitBitmap(){
thumbBitmap = drawableToBitmap(thumbSize,getResources().getDrawable(R.drawable.circle));
}
/**
* init paint
*/
privatevoidinitPaint(){
paint =newPaint();
paint.setStyle(Paint.Style.FILL);
paint.setTextSize(10);
//初始化圆形进度条的Paint
circlePaint =newPaint();
circlePaint.setAntiAlias(true);// 抗锯齿
circlePaint.setDither(true);// 防抖动
circlePaint.setStrokeWidth(10);
circlePaint.setShader(null);// 清除上一次的shader
circlePaint.setStyle(Paint.Style.STROKE);// 设置绘制的圆为空心
circlePaint.setShadowLayer(10,10,10, Color.RED);
circlePaint.setColor(Color.BLUE);// 设置圆弧的颜色
circlePaint.setStrokeCap(Paint.Cap.ROUND);// 把每段圆弧改成圆角的
}
@Override
protectedvoidonLayout(booleanchanged,intleft,inttop,intright,intbottom){
super.onLayout(changed, left, top, right, bottom);
}
@Override
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protectedvoidonDraw(Canvas canvas){
super.onDraw(canvas);
drawLine(canvas);
drawThumb(canvas);
drawCircleProgress(canvas);
}
/**
* draw circle
*@paramcanvas
*/
privatevoiddrawCircleProgress(Canvas canvas){
RectF oval =newRectF(thumbSize/2-radius, thumbSize/2-radius,
thumbSize/2+radius, thumbSize/2+radius);// 圆的外接正方形
floatalphaAngle = currentDegrees *360.0f/100*1.0f;// 计算每次画圆弧时扫过的角度,这里计算要注意分母要转为float类型,否则alphaAngle永远为0
canvas.drawArc(oval, -90, alphaAngle,false, circlePaint);
}
/**
* draw thumb
*@paramcanvas
*/
privatevoiddrawThumb(Canvas canvas){
//添加旋转,Matrix是Bitmap旋转的关键,用于bitmap一些补间动画的操作
canvas.translate((getWidth()-thumbSize)/2,(100-currentDegrees)/100*lineSize);
Matrix matrix =newMatrix();
matrix.setRotate(currentDegrees*10,thumbSize/2,thumbSize/2);
canvas.drawBitmap(thumbBitmap,matrix,null);//旋转背景
}
/**
* draw lines
*@paramcanvas
*/
privatevoiddrawLine(Canvas canvas){
//绘制背景线
backgroundLineRect.set((getWidth()-backgroundLineSize)/2,thumbSize/2,
(getWidth()+backgroundLineSize)/2, getParentHeight()-thumbSize/2);
lineSize = getParentHeight() - thumbSize;//去掉被thumb挡住的一部分长度
paint.setColor(Color.rgb(61,82,89));
canvas.drawRoundRect(backgroundLineRect, backgroundLineSize/2, backgroundLineSize/2, paint);
//绘制进度线
paint.setColor(Color.rgb(90,189,220));//进度线的颜色
foregroundLineRect.set((getWidth()-foregroundLineSize)/2,
(getParentHeight()-thumbSize)*(100-currentDegrees)/100+thumbSize/2,
(getWidth()+foregroundLineSize)/2,getParentHeight()-thumbSize/2);
canvas.drawRoundRect(foregroundLineRect,foregroundLineSize/2,foregroundLineSize/2,paint);
}
/**
* get ParentHeight
*@return
*/
privateintgetParentHeight(){
returngetHeight();
}
@Override
publicbooleandispatchTouchEvent(MotionEvent event){
returnsuper.dispatchTouchEvent(event);
}
@Override
publicbooleanonTouchEvent(MotionEvent event){
if(!isEnabled())
returntrue;
switch(event.getAction()) {
caseMotionEvent.ACTION_DOWN:
touchY = event.getRawY();//记录开始的Y值
break;
caseMotionEvent.ACTION_MOVE:
currentDegrees += (touchY-event.getRawY())*1f/(getParentHeight())*100.0f;//当前进度值(100为满)
if(currentDegrees >100){//超出去的不计算,默认为100
currentDegrees =100;
}
if(currentDegrees<0){//超出去的不计算,默认为0
currentDegrees =0;
}
if(observableEmitter !=null){//使用背压发送
observableEmitter.onNext(1);
}else{//直接发送
sendProgress();
}
touchY = event.getRawY();
invalidate();
break;
caseMotionEvent.ACTION_CANCEL:
break;
caseMotionEvent.ACTION_UP:
break;
}
returntrue;
}
privateObservableEmitter observableEmitter;
/**
*增加背压,防止发射拖动的事件过快,导致内存溢出
*/
publicvoidaddBackPressure(){
Observable.create(newObservableOnSubscribe() {
@Override
publicvoidsubscribe(ObservableEmitter emitter)throwsException{
observableEmitter = emitter;
}
}).sample(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(newConsumer() {
@Override
publicvoidaccept(Integer integer)throwsException{
sendProgress();
}
});
}
/**
* 发送进度
*/
privatevoidsendProgress(){
if(onProgressListener !=null){
onProgressListener.onProgress(currentDegrees);
}
}
/**
* 设置当前进度
*@paramcurrentDegrees
*/
publicvoidsetCurrentDegrees(floatcurrentDegrees){
this.currentDegrees = currentDegrees;
invalidate();
}
publicinterfaceOnProgressListener{
voidonProgress(floatprogress);
}
/**
* make a drawable to a bitmap
*@paramdrawable drawable you want convert
*@returnconverted bitmap
*/
privateBitmapdrawableToBitmap(intsize, Drawable drawable){
Bitmap bitmap =null;
if(drawableinstanceofBitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
bitmap = bitmapDrawable.getBitmap();
if(bitmap !=null&& bitmap.getHeight() >0) {
Matrix matrix =newMatrix();
floatscaleHeight = size *1.0f/ bitmapDrawable.getIntrinsicHeight();
matrix.postScale(scaleHeight, scaleHeight);
bitmap = Bitmap.createBitmap(bitmap,0,0, bitmap.getWidth(), bitmap.getHeight(), matrix,true);
returnbitmap;
}
}
bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas =newCanvas(bitmap);
drawable.setBounds(0,0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
returnbitmap;
}
}
Demo地址:https://github.com/helang1991/SeekBar
喜欢的就加个Star,谢谢