首页 > 系统 > Android > 正文

android:自定义SeekBar月牙形状

2019-11-09 17:29:26
字体:
来源:转载
供稿:网友

偶然间看到一些动态SeekBar形状类似月牙的,系统自带的不支持thumb的路径扩展。自定义一个吧。样子如下: 这里写图片描述

大体实现思路:

自定义继承View,获取控件基本属性如宽高。计算与圆弧以及Drawable旋钮相关的各种值。绘制2个圆弧以及旋钮。重写onTouchEvent(event)事件,动态设置旋钮位置。

这里的麻烦点主要在于确定两圆弧相交区域和相交点,以及确定旋钮的轨迹。就是麻烦点,并不难,需要耐心 。宽高的计算上,偷了懒,直接获取测量后的宽高。 相关代码:

@Override PRotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getMeasuredWidth(); height = getMeasuredHeight(); square = Math.min(width, height); radius = square / 2; //利用几何知识,计算大圆半径 newRadius = Math.sqrt((radius / 2) * (radius / 2) + (radius + radius * Math.sqrt(3) / 2) * (radius + radius * Math.sqrt(3) / 2)); startX = radius / 2; startY = (float) ((1 + Math.sqrt(3) / 2) * radius); //将按钮点添加到范围内,控制touch事件,可以来回滑动 thumbMaxAngle = (float) (2 * Math.atan(radius / 2 / (startY - radius / 2))); thumbStartAngle = (float) (Math.PI / 2 - thumbMaxAngle / 2); thumbEndAngle = (float) (Math.PI / 2 + thumbMaxAngle / 2); angle = thumbEndAngle; thumbRadius = radius / 2 / Math.sin(thumbMaxAngle / 2); //初始化轨迹球弧形中心坐标 thumbCenterY = radius / 2; //设置小圆弧和大圆弧所在区域 rectF1= new RectF(0, 0, square, square); rectF2 = new RectF((int) (radius - newRadius), (int) -newRadius, (int) (radius + newRadius), (int) newRadius); mShader= new SweepGradient(radius, radius, new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE}, null); }

图形绘制,主要是三部分,这里利用了一个技巧,将View背景设置成白色,同时绘制大圆时将画笔设置成白色,这样绘制出的大圆将看不出来,而且和小圆交叉形成了月牙形状。

@Override protected synchronized void onDraw(Canvas canvas) {// super.onDraw(canvas); paint.setShader(mShader); //先绘制外层小圆弧 canvas.drawArc(rectF1, 60, 60, true, paint); paint.setShader(null); paint.setColor(Color.WHITE); //绘制里层大圆弧 canvas.drawArc(rectF2, 75, 30, true, paint); paint.setShader(null); //根据当前移动坐标计算旋钮的所在点,并绘制 canvas.translate((float) (radius + thumbRadius * Math.cos(angle)), (float) (thumbCenterY + thumbRadius * Math.sin(angle))); mThumb.draw(canvas); }

监听Touch事件:

@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: setPressed(true); touchStartX = event.getX(); touchStartY = event.getY(); break; case MotionEvent.ACTION_MOVE: float endX = event.getX(); float endY = event.getY(); float moveX = endX - touchStartX; float tmp = moveX / radius * thumbMaxAngle; if (angle - tmp > thumbEndAngle) angle = thumbEndAngle; else if (angle - tmp < thumbStartAngle) angle = thumbStartAngle; else angle -= tmp; touchStartX = endX; touchStartY = endY; invalidate(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: setPressed(false); break; } return true; }

核心部分基本是这些。附上下载地址: 源码地址


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表