欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > Android 空气质量刻度

Android 空气质量刻度

2024/10/24 2:35:15 来源:https://blog.csdn.net/u012127961/article/details/142381231  浏览:    关键词:Android 空气质量刻度
效果

在这里插入图片描述

attrs.xml
    <attr name="textSpace" format="dimension|reference" /><attr name="barSpace" format="dimension|reference" /><attr name="scaleHeight" format="dimension|reference" /><attr name="progressHeight" format="dimension|reference" /><attr name="barRadius" format="dimension|reference" /><attr name="barColor" format="color|reference" /><attr name="barOutColor" format="color|reference" /><attr name="textSize" format="dimension|reference" /><attr name="strokeColor" format="color|reference" /><attr name="strokeWidth" format="dimension|reference" /><attr name="max" format="integer|reference" /><attr name="progress" format="integer|reference" /><declare-styleable name="AirQualityBar"><attr name="textSpace" /><attr name="barSpace" /><attr name="scaleHeight" /><attr name="progressHeight" /><attr name="barRadius" /><attr name="barColor" /><attr name="barOutColor" /><attr name="textSize" /><attr name="strokeColor" /><attr name="strokeWidth" /><attr name="max" /><attr name="progress" /></declare-styleable>
使用
    //标签文字private String[] labels = new String[]{"优", "良", "轻度", "中度", "重度","严重"};//数据值private int[] values = new int[]{35, 75, 115, 150,250};//颜色private int[] colors = {Color.parseColor("#0BCB81"),Color.parseColor("#E0DE25"),Color.parseColor("#F9A13A"),Color.parseColor("#F93A3A"),Color.parseColor("#B61455"),Color.parseColor("#B61455"),};//颜色进度private float[] positions = {0f, 0.2f, 0.4f, 0.6f, 0.8f,1.0f};AirQualityBar bar = holder.find(R.id.air_quality_bar);bar.setGradient(colors , positions);bar.setLabels(labels );bar.setValues(values );bar.setMax(360);bar.setProgress(270, true);
源码
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;import cn.anbao.forest.wards.R;/*** 空气质量进度条*/
public class AirQualityBar extends View implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {private Paint paint;//文字间隔private int textSpace = 10;//进度间隔private int barSpace = 4;//刻度高度private int scaleHeight = 4;//进度条高度private int progressHeight = 12;//圆点半径private int barRadius = 6;private int barColor = Color.WHITE;private int barOutColor = Color.parseColor("#80FFFFFF");//文字大小private int textSize = 14;//线条颜色private int strokeColor = Color.parseColor("#687785");//线条宽度private int strokeWidth = 2;//中间Yprivate int centerY;//View宽高private int width, height;//最大值private int max = 100;//进度值private int progress = 0;private int paintProgress;//标签文字private String[] labels = new String[]{"优", "良", "轻度", "中度", "重度","严重"};//数据值private int[] values = new int[]{35, 75, 115, 150,250};//颜色private int[] colors = {Color.parseColor("#0BCB81"),Color.parseColor("#E0DE25"),Color.parseColor("#F9A13A"),Color.parseColor("#F93A3A"),Color.parseColor("#B61455"),Color.parseColor("#B61455"),};private int[] paintColors;//颜色进度private float[] positions = {0f, 0.2f, 0.4f, 0.6f, 0.8f,1.0f};private float[] paintPositions;//进度圆角大小private int progressRadius;private ValueAnimator animator;public AirQualityBar(Context context) {this(context, null);}public AirQualityBar(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public AirQualityBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr, 0);}public AirQualityBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);initAttributeSet(context, attrs, defStyleAttr);}private void initAttributeSet(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {initAnimator();if (attrs != null) {TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.AirQualityBar, defStyleAttr, 0);textSpace = array.getDimensionPixelOffset(R.styleable.AirQualityBar_textSpace, textSpace);barSpace = array.getDimensionPixelOffset(R.styleable.AirQualityBar_barSpace, barSpace);scaleHeight = array.getDimensionPixelOffset(R.styleable.AirQualityBar_scaleHeight, scaleHeight);progressHeight = array.getDimensionPixelOffset(R.styleable.AirQualityBar_progressHeight, progressHeight);barRadius = array.getDimensionPixelOffset(R.styleable.AirQualityBar_barRadius, barRadius);barColor = array.getColor(R.styleable.AirQualityBar_barColor, barColor);barOutColor = array.getColor(R.styleable.AirQualityBar_barOutColor, barOutColor);textSize = array.getDimensionPixelSize(R.styleable.AirQualityBar_textSize, textSize);strokeColor = array.getColor(R.styleable.AirQualityBar_strokeColor, strokeColor);strokeWidth = array.getDimensionPixelOffset(R.styleable.AirQualityBar_strokeWidth, strokeWidth);max = array.getInt(R.styleable.AirQualityBar_max, max);progress = array.getInt(R.styleable.AirQualityBar_progress, progress);array.recycle();}setProgress(progress);paintColors = colors;paintPositions = positions;paintProgress = progress;}private void initAnimator() {if (animator == null) {animator = new ValueAnimator();animator.setDuration(500);animator.addUpdateListener(this);animator.addListener(this);}}@Overridepublic void onAnimationUpdate(@NonNull ValueAnimator valueAnimator) {paintProgress = (int) valueAnimator.getAnimatedValue();findSuitableColorsPositions(paintProgress);invalidate();}@Overridepublic void onAnimationStart(@NonNull Animator animator) {}@Overridepublic void onAnimationEnd(@NonNull Animator animator) {release();}@Overridepublic void onAnimationCancel(@NonNull Animator animator) {}@Overridepublic void onAnimationRepeat(@NonNull Animator animator) {}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);width = getMeasuredWidth();height = getMeasuredHeight();centerY = height / 2;}@Overrideprotected void onDraw(@NonNull Canvas canvas) {super.onDraw(canvas);paint = new Paint();paint.setAntiAlias(true);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(strokeWidth);paint.setTextSize(textSize);paint.setColor(strokeColor);//背景progressRadius = progressHeight / 2;RectF bounds = new RectF(0, centerY - progressRadius, width, centerY + progressRadius);canvas.drawRoundRect(bounds, progressRadius, progressRadius, paint);//进度float percent = getRealProgressValue(paintProgress) * 1.0F / max;paint.setStyle(Paint.Style.FILL);RectF rectF = new RectF(barSpace, centerY - progressRadius + barSpace, barSpace + (width - 2 * barSpace) * percent, centerY + progressRadius - barSpace);//线性渐变颜色if (paintColors.length > 1 && paintPositions.length > 1) {paint.setShader(new LinearGradient(rectF.left, rectF.top, rectF.right, rectF.top, paintColors, paintPositions, Shader.TileMode.CLAMP));} else {paint.setColor(paintColors[0]);}canvas.drawRoundRect(rectF, progressRadius, progressRadius, paint);//进度圆点if (percent > 0) {paint.setShader(null);int horizontal = width - 2 * barSpace;boolean isEnd = percent >= 0.95f;float cx = isEnd ? horizontal * percent - barSpace : horizontal * percent - barSpace/2;float cy = centerY;paint.setColor(barOutColor);canvas.drawCircle(cx + barSpace, cy, barRadius, paint);paint.setColor(barColor);float innerRadius = barRadius * 0.65f;canvas.drawCircle(cx + innerRadius, cy, innerRadius, paint);}//比例刻度drawScale(canvas, labels, values);}/*** 获取真实进度值** @param progress* @return*/private int getRealProgressValue(int progress) {return calculateProgress(values, max, progress);}/*** 计算进度** @param values 数值数组* @param max    最大值* @param value  当前值* @return*/private int calculateProgress(int[] values, int max, int value) {//重组新的数组int[] mixValues = Arrays.copyOf(values, values.length + 1);mixValues[mixValues.length - 1] = max;//每一段长度值int segmentValue = max / (mixValues.length);int progress = 0;for (int i = 0; i < mixValues.length; i++) {int preIndex = i - 1;int preValue = preIndex > -1 ? mixValues[preIndex] : 0;int itemValue = mixValues[i];if (value > preValue && value <= itemValue) {int diffValue = itemValue - preValue;int segmentProgress = (value - preValue) * segmentValue / diffValue;progress = (preIndex < 0 ? 0 : segmentValue * (preIndex + 1)) + segmentProgress;}}return progress;}/*** 获取进度百分比** @return*/public float getPercent() {return getRealProgressValue(progress) * 1.0F / max;}private List<Integer> colorList;private List<Float> positionList;/*** 找到合适的颜色和颜色位置*/private void findSuitableColorsPositions(int progress) {float percent = progress * 1.0F / max;if (positions == null || colors == null) {return;}if (positions.length == 0 || colors.length == 0) {return;}if (colorList == null) {colorList = new ArrayList<>();} else {colorList.clear();}if (positionList == null) {positionList = new ArrayList<>();} else {positionList.clear();}for (int i = 0; i < positions.length; i++) {if (percent > positions[i]) {positionList.add(positions[i]);colorList.add(colors[i]);}}int colorSize = colorList.size();if (colorSize == 0) {return;}paintColors = new int[colorSize];for (int i = 0; i < colorList.size(); i++) {paintColors[i] = colorList.get(i);}int positionSize = positionList.size();if (positionSize == 0) {return;}paintPositions = new float[positionSize];float itemValue = 1.0F / positionSize;for (int i = 0; i < positionList.size(); i++) {paintPositions[i] = itemValue * (i + 1);}}/*** 绘制刻度比例** @param canvas 画布* @param labels 标签* @param values 数值*/private void drawScale(Canvas canvas, String[] labels, int[] values) {paint = new Paint();paint.setAntiAlias(true);paint.setColor(strokeColor);paint.setStrokeWidth(strokeWidth);paint.setTextSize(textSize);//上方int labelSize = labels.length;int labelItemWidth = width / labelSize;for (int i = 0; i < labelSize; i++) {//刻度float startX = labelItemWidth * (i + 1);float startY = centerY - progressRadius;float stopX = labelItemWidth * (i + 1);float stopY = startY - scaleHeight;if (i < labelSize - 1) {canvas.drawLine(startX, startY, stopX, stopY, paint);}//标签String label = labels[i];float x = startX - labelItemWidth / 2 - measureText(paint, label).width() / 2;float y = startY - textSpace;canvas.drawText(labels[i], x, y, paint);}//下方int valueCount = values.length;int valueItemWidth = width / labelSize;for (int i = 0; i < valueCount; i++) {//刻度float startX = valueItemWidth * (i + 1);float startY = centerY + progressRadius;float stopX = valueItemWidth * (i + 1);float stopY = startY + scaleHeight;canvas.drawLine(startX, startY, stopX, stopY, paint);//标签String value = values[i] + "";Rect bounds = measureText(paint, value);float x = startX - bounds.width() / 2;float y = stopY + textSpace + bounds.height() / 2;canvas.drawText(value, x, y, paint);}}/*** 测量Text** @param paint* @param text* @return*/private Rect measureText(Paint paint, String text) {Rect bounds = new Rect();paint.getTextBounds(text, 0, text.length(), bounds);return bounds;}/*** 设置最大值** @param max*/public void setMax(int max) {this.max = max;}public int getProgress() {return progress;}/*** 设置进度** @param progress 进度*/public void setProgress(int progress) {setProgress(progress, true);}/*** 设置进度** @param progress 进度* @param animator 是否动画*/public void setProgress(int progress, boolean animator) {//数据没改变,不用刷新if (getProgress() == progress) {return;}progress = progress < 0 ? 0 : progress;if (progress == 0) {paintProgress = 0;findSuitableColorsPositions(paintProgress);invalidate();return;}this.progress = progress;if (animator) {startAnimator(progress);} else {paintProgress = progress;findSuitableColorsPositions(paintProgress);invalidate();}}/*** 开始动画** @param value 值*/private void startAnimator(int value) {initAnimator();animator.setIntValues(0, value);animator.start();}/*** 设置渐变** @param colors    颜色* @param positions 位置*/public void setGradient(int[] colors, float[] positions) {this.colors = colors;this.positions = positions;invalidate();}/*** 设置标签值** @param labels*/public void setLabels(String[] labels) {this.labels = labels;invalidate();}/*** 设置数值** @param values*/public void setValues(int[] values) {this.values = values;invalidate();}/*** 获取标签值** @return*/public String getLabel() {String label = "";float value = getPercent();int length = labels.length;for (int i = 0; i < length; i++) {float min = i * 1.F / length;float max = (i + 1) * 1.0F / length;if (value >= min && value < max) {label = labels[i];}}return label;}/*** 资源释放*/public void release() {if (animator != null) {animator.cancel();animator.removeAllListeners();animator.removeAllUpdateListeners();animator = null;}}}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com