要写自定义View,没有目标可不行,所以去一些不错的设计网站看了一圈,决定挑个简单的先试试水。
源码上传在GitHub上:
http://www.github.com/JangGwa/VolumeView
相关的设计网站和学习网站也可以在我的learningnote项目里看看
总体思路
1.View的测量
2.Canvas绘图技巧
3.触摸事件的计算
4.接口回调
- 自定义view属性
自定义view的属性我们进行设置后要引入我们的命名空间
//自定义属性,定义公共属性名
<attr name="titleSize" format="dimension"></attr>
<attr name="titleColor" format="color"></attr>
//自定义控件的主题样式
<declare-styleable name="LearningView">
<attr name="titleSize"></attr>
<attr name="titleColor"></attr>
</declare-styleable>
- 获取自定义view的属性
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.LearningView, defStyleAttr,0);
textColor = a.getColor(R.styleable.LearningView_titleColor, Color.RED);
textSize = a.getDimensionPixelSize(R.styleable.LearningView_titleSize,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 30,
getResources().getDisplayMetrics()));
a.recycle();
- 画渐变色的圆
渐变色使用的是SweepGradient
int[] colors = {
0xFFE5BD7D, 0xFFFAAA64, 0xFFFFFFFF,
0xFF6AE2FD,0xFF8CD0E5, 0xFFA3CBCB,
0xFFBDC7B3, 0xFFD1C299, 0xFFE5BD7D}
- 画线和文字
for (int i = 0; i < 120; i++) {
//圆心正顶部直线的Y坐标
top = mCenter - mRadius - circleWidth / 2;
// 去除底部不包含的区域 只旋转不划线
if (i <= 45 || i >= 75) {
if (i % 15 == 0) {
//整点时Y轴向外延伸
top = top - 25;
}
canvas.drawLine(mCenter, mCenter - mRadius + 30, mCenter, top, mLinePaint);
}
//旋转 canvas.rotate(3, mCenter, mCenter);}
//画文字+50代表这个字距离圆外边的距离//x代表文字的中心距离圆心的距离 这是原点中心正左边字的长度
int x = mRadius + circleWidth / 2 + 45;
//斜边int c = mRadius + circleWidth / 2 + 45;
x = (int) Math.sqrt((c * c / 2));
canvas.drawText(startDegrees + "", mCenter - x, mCenter + x, mTextPaint);
canvas.drawText((startDegrees + 20) + "", mCenter - c, mCenter + 10, mTextPaint);
canvas.drawText((startDegrees + 35) + "", mCenter - x, mCenter - x + 10, mTextPaint);
canvas.drawText((startDegrees + 50) + "", mCenter, mCenter - c + 10, mTextPaint);
canvas.drawText((startDegrees + 65) + "", mCenter + x, mCenter - x + 10, mTextPaint);
canvas.drawText((startDegrees + 80) + "", mCenter + c, mCenter + 10, mTextPaint);
canvas.drawText((startDegrees + 100) + "", mCenter + x, mCenter + x, mTextPaint);
- 滑动监听
手指互动需要得到当前手指在象限才好计算度数,可以根据手指移动的x点计算出cos,然后求出对应的角度。
case MotionEvent.ACTION_MOVE:
//判断手指在空白区域不能滑动
if (!isCanMove) { return false; }
float y = event.getY();
float x = event.getX();
float firstX = event.getX();
float firstY = event.getY();
//判断当前手指距离圆心的距离 代表在圆心的右侧
if (x > mCenter) { x = x - mCenter;
} else { x = mCenter - x;}
if (y < mCenter) {
y = mCenter - y; } else {
y = y - mCenter; }
//判断当前手指是否在空白区域
if (Math.sqrt(x * x + y * y) < (mRadius - 40)) {
isCanMove = false;
return false; }
float v = x / (float) Math.sqrt(x * x + y * y);
// 根据cos求角度
double acos = Math.acos(v);
acos = Math.toDegrees(acos);