自定义控件是进阶高级必须掌握的知识点。自定义控件可以做到系统自带的控件做不到的效果。学习自定义控件也可以加深对View的理解。之后会写一系列博客,从图形绘制到控件的交互一步步分析如何做出自定义控件。这里先放一个例子,
源码在我的github:https://github.com/SingleShadowBlade/MySeekBar
欢迎star
这个是自定义控件,有详细注释
public class DoubleSeekBar extends View {
private int preX,preY;private int currentX,currentX2,currentY;//进度条左右位置private Bitmap bitmap1,bitmap2,bitmap3;private Canvas canvas;private Paint paint;private int mScollBarWidth,mScollBarHeight; //控件宽度=滑动条宽度+滑动块宽度private int thumbTop,thunbBootom;//滑块顶部与底部高private int offset;//控件的偏移量private int progressLow,progressHigh;private OnSeekBarChangeListener mBarChangeListener;public DoubleSeekBar(Context context, AttributeSet attrs) { super(context, attrs); paint=new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStyle(Paint.Style.STROKE); paint.setColor(Color.RED); paint.setStrokeWidth(20); bitmap1= BitmapFactory.decodeResource(getResources(),R.mipmap.back); bitmap2= BitmapFactory.decodeResource(getResources(),R.mipmap.red); bitmap3= BitmapFactory.decodeResource(getResources(),R.mipmap.thumb); }//默认执行,计算view的宽高,在onDraw()之前protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = measureWidth(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); mScollBarWidth = width-offset; mScollBarHeight=20; currentX=offset; currentX2=width-offset; offset=20; thumbTop=40; thunbBootom=100; progressLow =0; progressHigh=100; setMeasuredDimension(width, height); }private int measureWidth(int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); // 声明一个临时变量来存储计算出的测量值int resultWidth = 0; //wrap_contentif (specMode == MeasureSpec.AT_MOST) { } //fill_parent或者精确值else if (specMode == MeasureSpec.EXACTLY) { } return specSize; }private int measureHeight(int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); int defaultHeight = 100; //wrap_contentif (specMode == MeasureSpec.AT_MOST) { } //fill_parent或者精确值else if (specMode == MeasureSpec.EXACTLY) { // defaultHeight = specSize-getPaddingLeft()-getPaddingRight();defaultHeight = specSize; } return defaultHeight; }//处理控件位置// @Override// public void layout(int l, int t, int r, int b) {// super.layout(l, t, r, b);// } //处理手势@Overridepublic boolean onTouchEvent(MotionEvent event) { int x= (int) event.getX(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: preX=x; break; case MotionEvent.ACTION_MOVE: if(preX>mScollBarWidth/2){ if(x>mScollBarWidth){ currentX2=mScollBarWidth; }else{ currentX2=x; } //右滑块进度progressHigh=(currentX2)*100/mScollBarWidth;
//// Log.e("tag","currentX2"+currentX2);// Log.e("tag","mScollBarWidth"+mScollBarWidth);// Log.e("tag","progressHigh"+progressHigh);}else {
if(x<offset){ currentX=offset; }else{ currentX=x; } //左滑块进度progressLow = (currentX-offset)*100/mScollBarWidth;
// Log.e("tag","currentX"+currentX);// Log.e("tag","mScollBarWidth"+mScollBarWidth);// Log.e("tag","progressLow"+progressLow);}
if(mBarChangeListener!=null){ mBarChangeListener.onProgressChanged(this,progressLow,progressHigh); } break; case MotionEvent.ACTION_UP: invalidate(); break; } return true; }@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); //绘制背景Rect rectBack=new Rect(offset+getPaddingLeft(),0,mScollBarWidth-getPaddingRight(),mScollBarHeight); canvas.drawBitmap(bitmap1,null,rectBack,paint); //绘制前景Rect rectRed=new Rect(currentX+getPaddingLeft(),0,currentX2-getPaddingRight(),mScollBarHeight); canvas.drawBitmap(bitmap2,null,rectRed,paint); //绘制左滑块Rect rect1=new Rect(currentX-offset+getPaddingLeft(),thumbTop,currentX+offset+getPaddingLeft(),thunbBootom); canvas.drawBitmap(bitmap3,null,rect1,paint); //绘制右滑块、getPaddingRight()设置paddingRight,其他同理Rect rect2=new Rect(currentX2-offset-getPaddingRight(),thumbTop,currentX2+offset-getPaddingRight(),thunbBootom); canvas.drawBitmap(bitmap3,null,rect2,paint); invalidate(); }public void setOnSeekBarChangeListener(OnSeekBarChangeListener mListener) { this.mBarChangeListener = mListener; }//回调函数,在滑动时实时调用,改变输入框的值public interface OnSeekBarChangeListener { //滑动前public void onProgressBefore(); //滑动时public void onProgressChanged(DoubleSeekBar seekBar, int progressLow, int progressHigh); //滑动后public void onProgressAfter();}
}
使用方法:
<com.gjl.myseekbar.DoubleSeekBarandroid:id="@+id/dsb"android:layout_width="300dp"android:layout_height="50dp"/>
MainActivity
public class MainActivity extends AppCompatActivity implements DoubleSeekBar.OnSeekBarChangeListener {
private DoubleSeekBar dsb;private TextView tv_low,tv_high;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dsb = (DoubleSeekBar) findViewById(R.id.dsb); dsb.setOnSeekBarChangeListener(this); tv_low= (TextView) findViewById(R.id.tv_low); tv_high= (TextView) findViewById(R.id.tv_high); }@Overridepublic void onProgressBefore() { }@Overridepublic void onProgressChanged(DoubleSeekBar seekBar, int progressLow, int progressHigh) { Log.e("tag","progressLow"+progressLow); Log.e("tag","progressHigh"+progressHigh); tv_low.setText(""+progressLow); tv_high.setText(""+progressHigh); }@Overridepublic void onProgressAfter() { }
}
共同学习,写下你的评论
评论加载中...
作者其他优质文章