Android自定義View之刻度尺滑動功能(一)

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/isee361820238/article/details/53954078

在Android開發中,有時候難免會遇到需要繪製圖形圖像的功能需求,針對這類需求,我們可以採用分解功能點,先易後難,逐個擊破的策略。這裏以可滑動的刻度尺功能爲例,進行自定義View的探討和學習。

首先,繪製一個刻度尺有最基本的幾個要素:最大刻度、最小刻度、底部橫線、每一個刻度的大小等,當然我們還需要繪製文字,刻度尺起始位置,刻度尺也需要有顏色等。這些自定義屬性我們可以直接寫在attrs.xml文件中。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RulerView">
        <!--最大刻度-->
        <attr name="max_value" format="dimension" />
        <!--最小刻度-->
        <attr name="min_value" format="dimension" />
        <!--刻度字體大小-->
        <attr name="scale_text_size" format="dimension" />
        <!--刻度字體顏色-->
        <attr name="scale_text_color" format="color" />
        <!--底部橫線的顏色-->
        <attr name="scale_bottom_line_color" format="color" />
        <!--遊標顏色-->
        <attr name="cursor_color" format="color" />
        <!--標尺開始顯示位置-->
        <attr name="start_location" format="dimension" />
        <!--一屏顯示Item-->
        <attr name="one_screen_item_count" format="integer" />
        <!--一個刻度的大小-->
        <attr name="one_scale_value" format="integer" />
    </declare-styleable>
</resources>

接下來,我們就在自定義控件中進行引用,並初始化一些需要用到的數據:

public class RulerView extends View {
    private static final String TAG = "RulerView";

    public static final int DEFAULT_BOTTOM_LINE_COLOR = 0xFFB3B2B2;
    public static final int DEFAULT_CURSOR_COLOR = 0XF3FF4081;
    public static final int DEFAULT_SCALE_TEXT_COLOR = 0xFF000000;
    public static final int DEFAULT_TEXT_SIZE = 24;
    public static final int DEFAULT_MAX_SCALE_VALUE = 20000;
    public static final int DEFAULT_ONE_SCREEN_ITEM_COUNT = 5 * 10;
    public static final int DEFAULT_ONE_SCALE_VALUE = 100;

    private int bottomLineColor;
    private int cursorColor;
    private int scaleTextColor;
    private int scaleTextSize;
    private int maxScaleValue; // 最大的刻度值

    private int oneScreenItemCount; // 一屏顯示的刻度數量
    private int oneScaleValue; // 一個刻度的大小
    private float oneScaleWidth; // 一個刻度的寬度
    private float scaleHeight; // 一個刻度的高度
    private int scaleCount; // 刻度數量

    private int currLocation;

    private float viewWidth;
    private float viewHeight;
    private float screenWidth;

    private Paint bottomLinePaint;
    private Paint scalePaint;
    private Paint textPaint;
    private Paint cursorPaint;

    public RulerView(Context context) {
        super(context);
    }

    public RulerView(Context context, AttributeSet attrs) {
        super(context, attrs);

        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(dm);
        screenWidth = dm.widthPixels;
        Log.d(TAG, "ScreenWidth = " + screenWidth); //1440

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RulerView);
        bottomLineColor = typedArray.getColor(R.styleable.RulerView_scale_bottom_line_color, DEFAULT_BOTTOM_LINE_COLOR);
        cursorColor = typedArray.getColor(R.styleable.RulerView_cursor_color, DEFAULT_CURSOR_COLOR);
        scaleTextColor = typedArray.getColor(R.styleable.RulerView_scale_text_color, DEFAULT_SCALE_TEXT_COLOR);
        scaleTextSize = typedArray.getDimensionPixelSize(R.styleable.RulerView_scale_text_size, DEFAULT_TEXT_SIZE);
        maxScaleValue = typedArray.getDimensionPixelOffset(R.styleable.RulerView_max_value, DEFAULT_MAX_SCALE_VALUE);
        oneScreenItemCount = typedArray.getInteger(R.styleable.RulerView_one_screen_item_count, DEFAULT_ONE_SCREEN_ITEM_COUNT);
        oneScaleValue = typedArray.getInteger(R.styleable.RulerView_one_scale_value, DEFAULT_ONE_SCALE_VALUE);
        currLocation = typedArray.getDimensionPixelOffset(R.styleable.RulerView_start_location, 0);

        typedArray.recycle();

        oneScaleWidth = screenWidth / oneScreenItemCount; // 1440 / (5 * 10)
        scaleCount = maxScaleValue / oneScaleValue; //刻度總數量 200
        viewWidth = scaleCount * oneScaleWidth; //刻度尺總寬度

        Log.d(TAG, "RulerView--oneScaleWidth = " + oneScaleWidth); //28
        Log.d(TAG, "RulerView--viewWidth = " + viewWidth); //5600

        // init paint
        initPaint();

    }

}

畫筆的初始化:

private void initPaint() {
    bottomLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    bottomLinePaint.setStrokeWidth(3);
    bottomLinePaint.setColor(bottomLineColor);

    scalePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    scalePaint.setStrokeWidth(3);

    textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    textPaint.setTextSize(scaleTextSize);
    textPaint.setColor(scaleTextColor);

    cursorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    cursorPaint.setStrokeWidth(4);
    cursorPaint.setColor(cursorColor);
}

在真正繪製前,我們還需要知道該控件的高度以及刻度尺的高度,這裏我們在onMeasure()方法中進行獲取:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    viewHeight = MeasureSpec.getSize(heightMeasureSpec);
    scaleHeight = viewHeight / 4;
    Log.d(TAG, "onMeasure--viewHeight = " + viewHeight); //320
}

最後,我們在onDraw()方法中進行我們的繪製:

@Override
protected void onDraw(Canvas canvas) {
    drawBottomLine(canvas);
    drawScale(canvas);
    drawCursor(canvas);
    }

繪製底部的橫線

private void drawBottomLine(Canvas canvas) {
    canvas.drawLine(0, viewHeight, viewWidth, viewHeight, bottomLinePaint);
}

繪製刻度以及刻度值

private void drawScale(Canvas canvas) {
    //計算遊標開始繪製的位置
    float startLocation = (screenWidth / 2) - ((oneScaleWidth * (currLocation / oneScaleValue)));
    for (int i = 0; i <= scaleCount; i++) {
        float location = startLocation + i * oneScaleWidth;
        if (i % 10 == 0) {
            canvas.drawLine(location, viewHeight - scaleHeight, location, viewHeight, scalePaint);
            String drawStr = oneScaleValue * i + "";
            Rect bounds = new Rect();
            textPaint.getTextBounds(drawStr, 0, drawStr.length(), bounds);
            //drawText的第三個參數表示:文本繪製的Y方向的基線位置
            canvas.drawText(drawStr, location - bounds.width() / 2, viewHeight - (scaleHeight + 10), textPaint);
        } else {
            canvas.drawLine(location, viewHeight - scaleHeight / 2, location, viewHeight, scalePaint);
        }
    }
}

繪製遊標

private void drawCursor(Canvas canvas) {
    canvas.drawLine(screenWidth / 2, viewHeight / 6, screenWidth / 2, viewHeight, cursorPaint);
}

至此,遊標功能初具模樣了,在接下來的一篇文章中將實現滑動效果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章