【自定义View】实现柱状图方法(一)优化:根据雨量增缩雨柱长度

  • Post author:
  • Post category:其他




系列文章目录


【自定义View】实现柱状图方法(一)




前言

我们在之前,已经实现了雨量柱状图的部分需求,但是如果要凸显出柱状图的大中小雨量的话,该如何实现呢?我们只需要在自定义View里面根据雨量阙值(大中小)的点来缩短柱状图的长度即可,但这里有个点需要注意,即y轴的点都得进行偏移。

  1. 大雨显示雨量柱状图

    在这里插入图片描述

  2. 中雨显示雨量柱状图

    ![在这里插入图片描述](https://img-blog.csdnimg.cn/055071765f594a149af49e469b034290.png

  3. 小雨显示雨量柱状图

    在这里插入图片描述



一、Activity的页面增加阙值显示

我们只需在xml文件添加大中小三个TextView即可,然后在Activity声明控件,并根据需求阙值控制可见性

xml增加:

            <TextView
                android:id="@+id/tv_big"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:textSize="12dp"
                android:layout_marginStart="12dp"
                app:layout_constraintTop_toTopOf="@id/rv_rain"
                app:layout_constraintStart_toStartOf="parent"/>
            <TextView
                android:id="@+id/tv_secondary"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:textSize="12dp"
                android:layout_marginStart="12dp"
                app:layout_constraintBottom_toBottomOf="@id/rv_rain"
                app:layout_constraintTop_toTopOf="@id/rv_rain"
                app:layout_constraintStart_toStartOf="parent"/>
            <TextView
                android:id="@+id/tv_small"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:textSize="12dp"
                android:layout_marginStart="12dp"
                app:layout_constraintBottom_toBottomOf="@id/rv_rain"
                app:layout_constraintStart_toStartOf="parent"/>
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_rain"
                android:layout_width="0dp"
                android:layout_height="@dimen/base_dp_48"
                android:layout_marginEnd="12dp"
                android:layout_marginTop="12dp"
                android:layout_marginStart="12dp"
                app:layout_constraintStart_toEndOf="@id/tv_small"
                app:layout_constraintTop_toBottomOf="@id/iv_rain"
                app:layout_constraintEnd_toEndOf="parent"/>

Activity控制:

        val tv_big = findViewById<TextView>(R.id.tv_big)
        val tv_secondary = findViewById<TextView>(R.id.tv_secondary)
        val tv_small = findViewById<TextView>(R.id.tv_small)
        val integers: MutableList<Double> = ArrayList()
        var maxDouble = 0.0
        for (i in 1..39){
            val nextDouble = Random().nextDouble()
            integers.add(nextDouble)
            maxDouble = Math.max(maxDouble, nextDouble)
        }
        val rainPillarAdapter = RainPillarAdapter()
        if (maxDouble<=0.5&&maxDouble>=0.25){
            tv_big.visibility = View.GONE
        }else if(maxDouble<=0.25){
            tv_big.visibility = View.GONE
            tv_secondary.visibility = View.GONE
        }



二、适配器进行修改,根据数据最大值获取阙值,然后传给自定义View

  1. 我们在setData()方法增加参数最大值
  2. 在私有方法setMaxCapacity()根据最大值设置阙值
    public void setData(List<Double> integers,Double maxCapacity){
        this.integers = integers;
        setMaxCapacity(maxCapacity);
        notifyDataSetChanged();
    }
    private void setMaxCapacity(Double maxCapacity){
        if (maxCapacity<=0.5&& maxCapacity>0.25){
            this.maxCapacity = 0.5;
        }else if (maxCapacity<=0.25){
            this.maxCapacity = 0.25;
        }else if (maxCapacity>0.5){
            this.maxCapacity = 1.0;
        }
    }



三、自定义View根据阙值比例缩短柱长,同时有个关注点,需要进行偏移

  1. 获取阙值,通过阙值获取需要偏移的距离(偏移举例默认为0)
     private float moveRange;// 偏移距离
    // 定义三个阙值及三个标志,大、中、小
    private float bigRainfall = 1f;
    private float averageRainfall = 0.5f;
    private float smallRainfall = 0.25f;
    private void initPaint() {
        startPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        startPaint.setColor(Color.parseColor("#EEEEEE"));
        paint.setColor(Color.parseColor("#3BE0F8"));
    }

    public void setCapacity(float maxCapacity,float authenticCapacity,int color) {
        this.maxCapacity = maxCapacity;
        this.authenticCapacity = authenticCapacity;
        setHeight(maxCapacity);
        paint.setColor(color);
        invalidate();
    }
    private void setHeight(float maxCapacity){
        height = getContext().getResources().getDimension(R.dimen.base_dp_42) * (maxCapacity/bigRainfall);
        moveRange = (getContext().getResources().getDimension(R.dimen.base_dp_42) * (1-(maxCapacity/bigRainfall)))/2f;
    }

  1. 什么是偏移距离,为什么我们需要它?(重点)

    这里我们便可以复习上一篇博客学到的一个知识点:

    坐标y轴是向下为正,那么缩短距离后,我们熟知的top会向下偏移二分之一缩短距离,bottom会上移二分之一缩短距离;而我们要求bottom绘制位置不变,那么就需要获取缩短距离的二分之一,即如下代码
moveRange = (getContext().getResources().getDimension(R.dimen.base_dp_42) * (1-(maxCapacity/bigRainfall)))/2f;

然后调整绘制方法,将偏移距离设置给canvas的绘制方法中

    private void onDrawRect(Canvas canvas) {
        ...
        // 绘制圆柱条的上面和下面两个圆
        canvas.drawCircle(centerX, top+moveRange, weight / 2f, startPaint); // 上面的圆
        canvas.drawCircle(centerX, bottom+moveRange, weight / 2f, startPaint); // 下面的圆
        // 绘制圆柱条的侧面
        canvas.drawRect(left, top+moveRange, right, bottom+moveRange, startPaint);


        // 判断是否存在数据,选择涂色
        if (maxCapacity!=0&&authenticCapacity!=0){
            // 由于坐标系为反的,这里需要将比例求反
            float v = 1f-(authenticCapacity / maxCapacity);
            // 然后将比列去乘原来的柱长,再加上原来的top值。将绘制点下移,也就是y轴正方向
            float topAuthentic =  top+v*(bottom-top);
            canvas.drawCircle(centerX, topAuthentic+moveRange, weight / 2f, paint); // 上面的圆
            canvas.drawCircle(centerX, bottom+moveRange, weight / 2f, paint); // 下面的圆
            canvas.drawRect(left, topAuthentic+moveRange, right, bottom+moveRange, paint);
        }
    }

如此便可以保证自定义View在缩短距离的时候也不会偏移了。



总结

本篇博客只是对上篇博客的自定义View一个扩展,但是因为个人觉得是对上一篇博客学到的知识点一个很好的实践,所以特意独立成一片新博客进行记录。

希望在以后的自定义View路上走的越来越通畅,诸君共勉!



版权声明:本文为weixin_63088467原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。