@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
private int measureHeight(int heightMeasure) {
int measureMode = View.MeasureSpec.getMode(heightMeasure);
int measureSize = View.MeasureSpec.getSize(heightMeasure);
int result = (int) (bottomPadding + longLineHeight 2);
switch (measureMode) {
case View.MeasureSpec.EXACTLY:
result = Math.max(result, measureSize);
break;
case View.MeasureSpec.AT_MOST:
result = Math.min(result, measureSize);
break;
default:
break;
}
height = result;
return result;
}
</code></pre> </td>
</tr>
</tbody>
</table>
onDraw() 繪制
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.setDrawFilter(pfdf);
drawBg(canvas);
drawIndicator(canvas);
drawRuler(canvas);
}
|
繪制做了三件事情:
- 繪制背景色
- 繪制指示器
- 繪制刻度
只看下怎么畫刻度,難點在于怎么確定刻度的坐標。首先高度的坐標是一樣的,刻度指示器是在屏幕正中,指示某個值,那么該刻度值的x坐標就是確定的。根據這個值去畫其他坐標,包括長刻度和短刻度。
首先要確定每個長刻度(和短刻度,如果有的話)的坐標寬度和單位,確定基礎單位和基礎單位寬度(如果有短刻度以短刻度為基礎單位)。那么
第i個刻度x坐標 = 中間刻度x坐標 + i 基礎單位寬度
</code></pre> </td>
</tr>
</tbody>
</table>
其中i的取值范圍在正負屏幕可繪制多少個基礎單位,第0位就是屏幕正中的刻度值。以該值為基礎一次畫出可以在屏幕中顯示的剩余刻度,如果是長刻度單位的整數倍就畫長刻度,刻度值只在長刻度下畫。 這樣就有一個問題,正中刻度值必須是可以整除基礎單位,比如,長刻度 = 1,中間兩個短刻度,這樣基礎單位值就是0.5,currentValue = 0.3,那么下一個值就是0.8,但是這樣顯示并不是我們想要的,我們想要0、0.5、1、1.5這樣的值。所以就是在初始化的時候格式化這些值,使得所有可顯示的值都可以整除基礎單位值,也就是余數為0。 由于使用float計算,所以要用到float精確計算,否則取余操作會出現不等于0的誤差導致畫不出長刻度。
//精度支持2位小數
private float format(float vallue) {
float result = 0;
if (getBaseUnit() < 0.1) {
//0.01
result = ArithmeticUtil.round(vallue, 2);
//float精確計算 取余
if (ArithmeticUtil.remainder(result, getBaseUnit(), 2) != 0) {
result += 0.01;
result = format(result);
}
} else if (getBaseUnit() < 1) {
//0.1
result = ArithmeticUtil.round(vallue, 1);
if (ArithmeticUtil.remainder(result, getBaseUnit(), 1) != 0) {
result += 0.1;
result = format(result);
}
} else if (getBaseUnit() < 10) {
//1
result = ArithmeticUtil.round(vallue, 0);
if (ArithmeticUtil.remainder(result, getBaseUnit(), 0) != 0) {
result += 1;
result = format(result);
}
}
return result;
}
|
處理滑動操作
滑動處理比較簡單,以初始化為基礎,每次move操作累加x坐標,以此值繪制偏移量,停止滑動時以基礎單位寬度為基準四舍五入,開始動畫滑動到相應的刻度值上。 主要方法
private void drawRuler(Canvas canvas) {
if (moveX < maxRightOffset) {
moveX = maxRightOffset;
}
if (moveX > maxLeftOffset) {
moveX = maxLeftOffset;
}
int halfCount = (int) (width / 2 / getBaseUnitWidth());
float moveValue = (int) (moveX / getBaseUnitWidth()) getBaseUnit();
currentValue = originValue - moveValue;
//剩余偏移量
offset = moveX - (int) (moveX / getBaseUnitWidth()) getBaseUnitWidth();
for (int i = -halfCount - 1; i <= halfCount + 1; i++) {
float value = ArithmeticUtil.addWithScale(currentValue, ArithmeticUtil.mulWithScale(i, getBaseUnit(), 2), 2);
//只繪出范圍內的圖形
if (value >= startValue && value <= endValue) {
//畫長的刻度
float startx = width / 2 + offset + i * getBaseUnitWidth();
if (startx > 0 && startx < width) {
if (microUnitCount != 0) {
if (ArithmeticUtil.remainder(value, unit, 2) == 0) {
drawLongLine(canvas, i, value);
} else {
//畫短線
drawShortLine(canvas, i);
}
} else {
//畫長線
drawLongLine(canvas, i, value);
}
}
}
}
//通知結果
notifyValueChange();
}
</code></pre> </td>
</tr>
</tbody>
</table>
關于刻度的單位,需要給出長刻度單位和中間的短刻度個數,這樣中間的短刻度單位就確定了,所以理論上不管中間有幾個短刻度計算都是一樣的。我在里面封裝了三個常用的,2、5、10三種。 支持的styleable
<declare-styleable name="BooheeRulerView">
<attr name="ruler_bg_color" format="color|reference"/>
<attr name="ruler_line_color" format="color|reference"/>
<attr name="ruler_text_size" format="dimension"/>
<attr name="ruler_text_color" format="color|reference"/>
<attr name="ruler_width_per_unit" format="dimension"/>
</declare-styleable>
|


代碼在這里
總結
實現的效果比較單一,沒有做太多的擴展,有時間再完善下。
via:http://w4lle.github.io/2016/05/15/Android%E8%87%AA%E5%AE%9A%E4%B9%89View%E4%B9%8B%E5%88%BB%E5%BA%A6%E5%B0%BA/
本文由用戶 gl7080 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
| | | | | |
| |
| |
|
| | | |
| |
|
sesese色
| |