1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > android自定义控件之可以表示画笔大小的调整画笔size 的SeekBar

android自定义控件之可以表示画笔大小的调整画笔size 的SeekBar

时间:2022-01-18 13:45:25

相关推荐

android自定义控件之可以表示画笔大小的调整画笔size 的SeekBar

作为一个也算是写过代码的人(虽然是个菜鸟),一直想写下自己的博客,之前由于上班的原因(其实是因为本人太懒)一直没机会写。现在辞完职休息了一个多星期后,就动手写写博客装装逼吧,也是对自己过去一年工作的总结。第一次写博客还是有点小激动的,写得不好也是情有可原(那能怎么办,我水平就这样)。废话说了一大堆,接下来就进入正文吧。

当时项目中有个涂鸦画笔的功能,需要有个seekbar去动态调整涂鸦画笔的大小,同时还要能从seekbar表示出当前画笔的大小。效果图如下:

图中有绿色圆和绿色区域的控件就为自定义的seekbar控件。绿色圆的大小可以表示出当前涂鸦画笔的大小。滑动过的区域设置为绿色,未滑动过的区域设置为灰色。

下面介绍该控件的实现原理:

如图,图中黑色矩形框为自定义控件时的画布的大小,假设画布的宽高分别为W,H。让红色圆的上部 ( B点 )、下部(C点)分别于与画布的上边缘、下边缘相切,那么红色圆的直径就为H,可以算出红色圆的圆心坐标为(W-H/2,H/2),画出不移动的最大圆。A、B、C的坐标分别为(0,H/2)、(W-H/2,0)、(W-H/2,H)。然后新建路径backgroundPath,画三角形ABC,这时可以设置画路径backgroundPath的画笔的颜色,这就是未滑过区域的颜色。代码如下:

backgroundPath.reset();backgroundPath.moveTo(mHeight/2,mHeight/2);backgroundPath.lineTo(r,0);backgroundPath.lineTo(r,mHeight);backgroundPath.close();canvas.drawPath(backgroundPath,backgroundPaint);

这就画出了基本的控件框架。接下来就是要画移动的黄色圆,这需要动态计算黄色圆的半径。

上图中的黄色圆是分别于直线AB、AC相切的,所以当我们左右移动黄色圆的时候黄色圆的圆心即G点的X坐标发生改变且其值是知道的(其实就是seekbar的值),所以G点坐标为(X,H/2)。由图形的几何关系很明显可以看出三角形AEG和三角形ADB是等比关系,所以可以算出黄色圆的半径EG =AG/AB*BD(可以在三角形ABD 中根据勾股定理先算出AB 的长度)。这样知道了黄色圆的圆心坐标和半径,动态画出黄色圆就行了。

最后是画出黄色圆滑动过的区域。跟上面的画backgroundPath路径一样,画三角形AEF这时设置的画笔颜色就是滑动过区域的颜色。到此这个自定义的seekbar就画完了。还有很重要的一步是给这个seekbar控件设置滑动监听事件,可以根据自己的需要实现自己的监听事件,这里就不在继续写下去了,毕竟不同的项目有不同需求,需要实现的监听也不一样。

就这第一篇博客就写完了,当然这个控件还有很多可以完善的地方,比如可以加上其他一些属性,然后配置一下,让其在使用的时候可以直接在xml布局文件中直接设置属性值,就像使用android原生控件一样(具体方法我也不太记得了,到时要用到的时候问下度娘应该也挺快可以弄好的)。在最后会给出我当时写的源码,如果你在翻博客的时候翻到了这片博客,且对你有点用处的话给我点个赞,或者评论下让我听听您的高见。

/*** Created by lyh on /11/7.*/public class MySeekBarView extends View {private Paint mPaint;//移动的外圈圆的画笔private Paint pressPaint;//滑动时的圆和滑动过的区域的画笔private Paint backgroundPaint;//背景圆的画笔private int mWidth;//控件的宽private int mHeight;//空间的高private Path pressPath;//用于控制滑动过的区域的颜色private Path backgroundPath;//用于控制背景颜色private int mMax = 200;//默认的最大值private int mMin = 0;//默认的最小值private int mProgress = 0;//当前的进度条大小private OnProgressChangedListener mProgressListener;//滑动监听接口public MySeekBarView(Context context) {super(context);init();}public MySeekBarView(Context context, AttributeSet attrs) {super(context, attrs);init();}public MySeekBarView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init(){mPaint = new Paint();mPaint.setColor(0xa8ffffff);mPaint.setDither(true);mPaint.setAntiAlias(true);mPaint.setStyle(Paint.Style.FILL);pressPaint = new Paint();pressPaint.setDither(true);pressPaint.setAntiAlias(true);pressPaint.setStyle(Paint.Style.FILL);pressPaint.setColor(0xff24c092);backgroundPaint = new Paint();backgroundPaint.setDither(true);backgroundPaint.setAntiAlias(true);backgroundPaint.setStyle(Paint.Style.FILL);backgroundPaint.setColor(0xff7a7979);pressPath = new Path();backgroundPath = new Path();}//设置移动外圈圆的颜色public void setmPaintColor(int color){mPaint.setColor(color);}//设置滑动过的区域的颜色public void setPressPaintColor(int color){pressPaint.setColor(color);}//设置背景区域的颜色public void setBackgroundPaint(int color){backgroundPaint.setColor(color);}public void setMax(int max){if (max>mMax|max<mMin){return;}mMax = max;}public int getMax(){return mMax;}public void setMin(int min){if (min>mMax|min<mMin){return;}mMin = min;}public int getMin(){return mMin;}public void setProgress(int progress){if (progress<mMin){mProgress = mMin;}else if (progress>mMax){mProgress = mMax;}else{mProgress = progress;}x = (int)((mProgress*1f/mMax) * (r-mHeight/2)) + mHeight/2;r1 = getR(x);if(mProgressListener != null) {mProgressListener.onProgressChanged(this, mProgress, false);}invalidate();}public int getProgress(){if (mMax!=0){mProgress = (int) ((x-mHeight/2)*1f/(r-mHeight/2) *mMax);}return mProgress;}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:x = (int) event.getX();checkX();r1 = getR(x);if (mProgressListener!=null){mProgressListener.onStartTrackingTouch(this);}break;case MotionEvent.ACTION_MOVE:x = (int) event.getX();checkX();r1 = getR(x);if (mProgressListener!=null){mProgressListener.onProgressChanged(this,getProgress(),true);}break;case MotionEvent.ACTION_UP:x = (int) event.getX();checkX();r1 = getR(x);setProgress(getProgress());//点击时也改变进度值if (mProgressListener!=null){mProgressListener.onStopTrackingTouch(this);}break;}invalidate();return true;}//限定x的范围private void checkX() {if (x <= mHeight/2){x = mHeight/2;}if (x > r){x = r;}if (x > r){x = r;}}//获得移动的圆的半径private int getR(int x){// int r = x*mHeight/2/this.r;int r = (int) ((x-mHeight/2)*1f/(mWidth-mHeight/2-mHeight/2) * mHeight/2);return r;}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);requestLayout();invalidate();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}private int r =mHeight/2+1;//进度条的大小,默认设为不等于零,防止有些地方控件还没显示出来先调用了setProgress()方法导致除数为零异常private int r1;//移动时的圆的半径,可变private int x;//移动时的x坐标(距控件最左边的距离)@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);mHeight = bottom-top;mWidth = right-left;r = Math.abs(mWidth-mHeight/2);x = (int) (mProgress*1f/mMax*(r-mHeight/2)) + mHeight/2;r1 = getR(x);pressPath.moveTo(0,mHeight/2);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));canvas.drawCircle(r,mHeight/2,mHeight/2,backgroundPaint);//外圈的背景圆if(backgroundPath!=null){//背景区域backgroundPath.reset();backgroundPath.moveTo(mHeight/2,mHeight/2);backgroundPath.lineTo(r,0);backgroundPath.lineTo(r,mHeight);backgroundPath.close();canvas.drawPath(backgroundPath,backgroundPaint);}if (pressPath!=null){//滑动过的区域pressPath.reset();pressPath.moveTo(mHeight/2,mHeight/2);pressPath.lineTo(x,mHeight/2-r1);pressPath.lineTo(x,mHeight/2+r1);pressPath.close();canvas.drawPath(pressPath,pressPaint);}if (r1==mHeight/2){canvas.drawCircle(x,mHeight/2,r1,pressPaint);//滑动时大小变化的圆canvas.drawCircle(x,mHeight/2,mHeight/2,mPaint);//滑动时大小不变得外圈圆}else{canvas.drawCircle(x,mHeight/2,mHeight/2,mPaint);//滑动时大小不变得外圈圆canvas.drawCircle(x,mHeight/2,r1,pressPaint);//滑动时大小变化的圆}}//设置滑动监听public void setOnProgressChangedListener(OnProgressChangedListener onProgressChangedListener){this.mProgressListener = onProgressChangedListener;}/*** 滑动监听接口*/public interface OnProgressChangedListener {void onProgressChanged(MySeekBarView mySeekBar, int progress, boolean fromUser);void onStartTrackingTouch(MySeekBarView mySeekBar);void onStopTrackingTouch(MySeekBarView mySeekBar);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。