超详细Android自定义View开发指南:打造可定制轴线颜色、标签字体大小的垂直轴线视图,让你的应用不落俗套!

在Android开发中,自定义View是一个比较常见的需求。本文将详细介绍如何创建一个垂直轴线视图VerticalAxisView,以及如何进行相关属性设置和绘制。
下面是效果图
在这里插入图片描述
在这里插入图片描述

一、需求分析

本次需求是创建一个垂直轴线视图,包括以下功能:

  1. 可以设置轴线的颜色;
  2. 可以设置刻度数量;
  3. 可以设置最大值和最小值;
  4. 可以设置标签字体大小;
  5. 可以选择标签在轴线左侧还是右侧,并针对不同方向进行相应绘制。

二、实现步骤

  1. 创建VerticalAxisView类并继承自View;
  2. 定义一些默认属性,如:默认刻度数量、默认最小值、默认最大值、默认颜色值、默认文本颜色、默认文本大小等;
  3. 在构造方法中初始化画笔,并调用init()方法进行初始化;
  4. 实现onDraw()方法,在该方法中进行绘制轴线、刻度和标签等;
  5. 提供外部可调用的方法,如:setTickCount()、setMinValue()、setMaxValue()、setAxisColor()和setTextSize()等;
  6. 最后,在XML布局文件中进行引用。
    下面是具体实现代码:
public class VerticalAxisView extends View {

    private static final int DEFAULT_TICK_COUNT = 6;
    private static final float DEFAULT_MIN_VALUE = 0f;
    private static final float DEFAULT_MAX_VALUE = 100f;
    private static final String DEFAULT_COLOR_VALUE = "#000000";
    private static final int DEFAULT_TEXT_SIZE = 12;
    //0:文本在轴线左侧,1:文本在轴线右侧,没有用枚举了
    private static final int DEFAULT_DIRECTION = 0;

    private Paint mAxisPaint = new Paint();
    private Paint mTickPaint = new Paint();
    private Paint mTextPaint = new Paint();

    private int mTickCount = DEFAULT_TICK_COUNT;
    private float mMinValue = DEFAULT_MIN_VALUE;
    private float mMaxValue = DEFAULT_MAX_VALUE;
    private float mValueRange = mMaxValue - mMinValue;
    private float mTickSpacing = mValueRange / (mTickCount - 1);
    //文本在轴线左侧还是右侧
    private int drawDirection = DEFAULT_DIRECTION;

    public VerticalAxisView(Context context) {
        super(context);
        init();
    }

    public VerticalAxisView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public VerticalAxisView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        // 初始化画轴线画笔
        mAxisPaint.setColor(Color.parseColor(DEFAULT_COLOR_VALUE));
        mAxisPaint.setStrokeWidth(1);
        mAxisPaint.setAntiAlias(true);
        // 初始化刻度线画笔
        mTickPaint.setColor(Color.parseColor(DEFAULT_COLOR_VALUE));
        mTickPaint.setStrokeWidth(1);
        mTickPaint.setAntiAlias(true);
        // 初始化刻度文本画笔
        mTextPaint.setColor(Color.parseColor(DEFAULT_COLOR_VALUE));
        mTextPaint.setTextSize(DEFAULT_TEXT_SIZE);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextAlign(Paint.Align.RIGHT);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth();
        int height = getHeight();
        float tickLength = width / 9f;
        float textPadding = 8;
        float startY = height - (mMaxValue - mMinValue) / mValueRange * (height - 2 * textPadding - 40) - textPadding - 20;
        float endY = height - textPadding - 20;
        if (drawDirection == 0) {
            // 绘制轴线
            canvas.drawLine(width - tickLength, startY, width - tickLength, endY, mAxisPaint);
            // 绘制刻度和标签
            for (int i = 0; i < mTickCount; i++) {
                float tickValue = mMinValue + i * mTickSpacing;
                float tickPosition = height - ((tickValue - mMinValue) / mValueRange) * (height - 2 * textPadding - 40) - textPadding - 20;
                canvas.drawLine(width - tickLength, tickPosition, width, tickPosition, mTickPaint);
                Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
                float baseline = tickPosition - (fontMetrics.top + fontMetrics.bottom) / 2;
                // 数值要格式化一位小数
                String tickValueStr = String.format("%.1f", tickValue);
                    canvas.drawText(tickValueStr, width - 2 * tickLength, baseline, mTextPaint);
                    }
                    }else {
                    // 绘制轴线,起始位置为0+刻度线的宽度
                    canvas.drawLine(tickLength, startY, tickLength, endY, mAxisPaint);
                    // 绘制刻度和标签,刻度在轴线的左侧,标签在轴线的右侧
                    for (int i = 0; i < mTickCount; i++) {
                    float tickValue = mMinValue + i * mTickSpacing;
                    float tickPosition = height - ((tickValue - mMinValue) / mValueRange) * (height - 2 * textPadding - 40) - textPadding - 20;
                    canvas.drawLine(0, tickPosition, tickLength, tickPosition, mTickPaint);
                    Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
                    float baseline = tickPosition - (fontMetrics.top + fontMetrics.bottom) / 2;
                    // 数值要格式化一位小数
                    String tickValueStr = String.format("%.1f", tickValue);
                    //文本x:轴线的右侧+文本与轴线的间距+文本的宽度
                    float textWidth = mTextPaint.measureText(tickValueStr);
                    canvas.drawText(tickValueStr, tickLength + textPadding + textWidth, baseline, mTextPaint);
                    }
                    }



                    }

                    /**
                    * 设置刻度数量
                    *
                    * @param count
                    */
                    public void setTickCount(int count) {
                    mTickCount = count;
                    mTickSpacing = mValueRange / (mTickCount - 1);
                    invalidate();
                    }

                    /**
                    * 设置最小值
                    *
                    * @param minValue
                    */
                    public void setMinValue(float minValue) {
                    mMinValue = minValue;
                    mValueRange = mMaxValue - mMinValue;
                    mTickSpacing = mValueRange / (mTickCount - 1);
                    invalidate();
                    }

                    /**
                    * 设置最大值
                    *
                    * @param maxValue
                    */
                    public void setMaxValue(float maxValue) {
                    mMaxValue = maxValue;
                    mValueRange = mMaxValue - mMinValue;
                    mTickSpacing = mValueRange / (mTickCount - 1);
                    invalidate();
                    }
                    /**
                    * 设置轴线颜色
                    *
                    * @param color
                    */
                    public void setAxisColor(String color){
                    mAxisPaint.setColor(Color.parseColor(color));
                    mTickPaint.setColor(Color.parseColor(color));
                    mTextPaint.setColor(Color.parseColor(color));
                    invalidate();
                    }
                    /**
                    *  设置标签字体大小
                    */
                    public void setTextSize(int size){
                    mTextPaint.setTextSize(size);
                    invalidate();
                    }
                    }

三、使用方法

在XML布局文件中引用VerticalAxisView:

<com.example.VerticalAxisView
    android:id="@+id/vertical_axis_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent" />

在Java代码中获取VerticalAxisView并进行相关属性设置:
java

VerticalAxisView verticalAxisView = (VerticalAxisView) findViewById(R.id.vertical_axis_view);
// 设置刻度数量
verticalAxisView.setTickCount(5);

// 设置最大值和最小值
verticalAxisView.setMinValue(0f);
verticalAxisView.setMaxValue(100f);

// 设置轴线颜色
verticalAxisView.setAxisColor("#0000ff");

// 设置标签字体大小
verticalAxisView.setTextSize(16);

四、注意事项

  1. 在绘制刻度和标签时,要根据当前值与最小值的差值以及总值范围来计算出位置;
  2. 文本在轴线左侧和右侧时,位置计算方法不同,需要分别处理;
  3. 在修改属性后,需要调用invalidate()方法来触发View的重绘。

五、总结

自定义View是Android开发中比较常见的需求之一,在实现时需要注意计算位置和属性变更后的重绘等问题。本文主要介绍了如何创建一个垂直轴线视图,并提供了设置刻度数量、最大值和最小值、轴线颜色以及标签字体大小等相关属性的方法,希望对大家学习自定义View有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值