系列文章目录
文章目录
前言
我们在之前,已经实现了雨量柱状图的部分需求,但是如果要凸显出柱状图的大中小雨量的话,该如何实现呢?我们只需要在自定义View里面根据雨量阙值(大中小)的点来缩短柱状图的长度即可,但这里有个点需要注意,即y轴的点都得进行偏移。
-
大雨显示雨量柱状图
-
中雨显示雨量柱状图
-
小雨显示雨量柱状图
一、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
- 我们在setData()方法增加参数最大值
- 在私有方法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根据阙值比例缩短柱长,同时有个关注点,需要进行偏移
- 获取阙值,通过阙值获取需要偏移的距离(偏移举例默认为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;
}
-
什么是偏移距离,为什么我们需要它?(重点)
这里我们便可以复习上一篇博客学到的一个知识点:
坐标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 版权协议,转载请附上原文出处链接和本声明。