android - 如何在 android Activity 中绘制温度计?

标签 android jquery-mobile user-interface android-activity 2d

我正在创建一个设备管理应用程序。我想在 Activity 中显示温度计并使用实时数据更新温度值。我得到了实时数据部分,但我不知道如何绘制温度计。有什么图书馆可以用来解决我的问题吗?

最佳答案

这是温度计 View

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

public class Thermometer extends View {

    private float outerCircleRadius, outerRectRadius;
    private Paint outerPaint;
    private float middleCircleRadius, middleRectRadius;
    private Paint middlePaint;
    private float innerCircleRadius, innerRectRadius;
    private Paint innerPaint;
    private Paint degreePaint, graduationPaint;

    private static final int GRADUATION_TEXT_SIZE = 16; // in sp
    private static float DEGREE_WIDTH = 30;
    private static final int NB_GRADUATIONS = 8;
    public static final float MAX_TEMP = 50, MIN_TEMP = -30;
    private static final float RANGE_TEMP = 80;
    private static final int NB_GRADUATIONS_F = 8;
    private static final float MAX_TEMP_F = 120, MIN_TEMP_F = -30;
    private static final float RANGE_TEMP_F = 150;
    private int nbGraduations = NB_GRADUATIONS;
    private float maxTemp = MAX_TEMP;
    private float minTemp = MIN_TEMP;
    private float rangeTemp = RANGE_TEMP;
    private float currentTemp = MIN_TEMP;
    private Rect rect = new Rect();

    public Thermometer(Context context) {
        super(context);
        init(context, null);
    }

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

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

    public void setCurrentTemp(float currentTemp) {
        if (currentTemp > maxTemp) {
            this.currentTemp = maxTemp;
        } else if (currentTemp < minTemp) {
            this.currentTemp = minTemp;
        } else {
            this.currentTemp = currentTemp;
        }

        invalidate();
    }

    public float getMinTemp() {
        return minTemp;
    }

    public void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Thermometer);
        outerCircleRadius = typedArray.getDimension(R.styleable.Thermometer_radius, 20f);
        int outerColor = typedArray.getColor(R.styleable.Thermometer_outerColor, Color.GRAY);
        int middleColor = typedArray.getColor(R.styleable.Thermometer_middleColor, Color.WHITE);
        int innerColor = typedArray.getColor(R.styleable.Thermometer_innerColor, Color.RED);

        typedArray.recycle();

        outerRectRadius = outerCircleRadius / 2;
        outerPaint = new Paint();

        outerPaint.setColor(outerColor);
        outerPaint.setStyle(Paint.Style.FILL);

        middleCircleRadius = outerCircleRadius - 5;
        middleRectRadius = outerRectRadius - 5;
        middlePaint = new Paint();
        middlePaint.setColor(middleColor);
        middlePaint.setStyle(Paint.Style.FILL);

        innerCircleRadius = middleCircleRadius - middleCircleRadius / 6;
        innerRectRadius = middleRectRadius - middleRectRadius / 6;
        innerPaint = new Paint();
        innerPaint.setColor(innerColor);
        innerPaint.setStyle(Paint.Style.FILL);

        DEGREE_WIDTH = middleCircleRadius / 8;

        degreePaint = new Paint();
        degreePaint.setStrokeWidth(middleCircleRadius / 16);
        degreePaint.setColor(outerColor);
        degreePaint.setStyle(Paint.Style.FILL);

        graduationPaint = new Paint();
        graduationPaint.setColor(outerColor);
        graduationPaint.setStyle(Paint.Style.FILL);
        graduationPaint.setAntiAlias(true);
        graduationPaint.setTextSize(Utils.convertDpToPixel(GRADUATION_TEXT_SIZE, getContext()));

    }

    public void changeUnit(boolean isCelsius) {
        if (isCelsius) {
            nbGraduations = NB_GRADUATIONS;
            maxTemp = MAX_TEMP;
            minTemp = MIN_TEMP;
            rangeTemp = RANGE_TEMP;
        } else {
            nbGraduations = NB_GRADUATIONS_F;
            maxTemp = MAX_TEMP_F;
            minTemp = MIN_TEMP_F;
            rangeTemp = RANGE_TEMP_F;
        }

        invalidate();
    }

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

        int height = getHeight();
        int width = getWidth();

        int circleCenterX = width / 2;
        float circleCenterY = height - outerCircleRadius;
        float outerStartY = 0;
        float middleStartY = outerStartY + 5;


        float innerEffectStartY = middleStartY + middleRectRadius + 10;
        float innerEffectEndY = circleCenterY - outerCircleRadius - 10;
        float innerRectHeight = innerEffectEndY - innerEffectStartY;
        float innerStartY = innerEffectStartY + (maxTemp - currentTemp) / rangeTemp * innerRectHeight;

        RectF outerRect = new RectF();
        outerRect.left = circleCenterX - outerRectRadius;
        outerRect.top = outerStartY;in
        outerRect.right = circleCenterX + outerRectRadius;
        outerRect.bottom = circleCenterY;

        canvas.drawRoundRect(outerRect, outerRectRadius, outerRectRadius, outerPaint);
        canvas.drawCircle(circleCenterX, circleCenterY, outerCircleRadius, outerPaint);

        RectF middleRect = new RectF();
        middleRect.left = circleCenterX - middleRectRadius;
        middleRect.top = middleStartY;
        middleRect.right = circleCenterX + middleRectRadius;
        middleRect.bottom = circleCenterY;

        canvas.drawRoundRect(middleRect, middleRectRadius, middleRectRadius, middlePaint);
        canvas.drawCircle(circleCenterX, circleCenterY, middleCircleRadius, middlePaint);

        canvas.drawRect(circleCenterX - innerRectRadius, innerStartY, circleCenterX + innerRectRadius, circleCenterY, innerPaint);
        canvas.drawCircle(circleCenterX, circleCenterY, innerCircleRadius, innerPaint);

        float tmp = innerEffectStartY;
        float startGraduation = maxTemp;
        float inc = rangeTemp / nbGraduations;

        while (tmp <= innerEffectEndY) {
            canvas.drawLine(circleCenterX - outerRectRadius - DEGREE_WIDTH, tmp, circleCenterX - outerRectRadius, tmp, degreePaint);
            String txt = ((int) startGraduation) + "°";
            graduationPaint.getTextBounds(txt, 0, txt.length(), rect);
            float textWidth = rect.width();
            float textHeight = rect.height();

            canvas.drawText(((int) startGraduation) + "°", circleCenterX - outerRectRadius - DEGREE_WIDTH - textWidth - DEGREE_WIDTH * 1.5f,
                    tmp + textHeight / 2, graduationPaint);
            tmp += (innerEffectEndY - innerEffectStartY) / nbGraduations;
            startGraduation -= inc;
        }
    }
}

来源:@ssaurel的这篇文章在 medium.com

如果你想使用库 This library可以帮到你

示例 gif

gif

另一个图书馆:github.com

关于android - 如何在 android Activity 中绘制温度计?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13510513/

相关文章:

c# - jQuery 手机 : Dialog popup scrolling

javascript - MediaElement.js 音频标签没有动态添加样式

java - 我可以只为 JButton 类的一个子集设置 ButtonUI 吗?

java - Blackberry 上的“设置计时器”字段是什么字段类型?

python - 在 Kivy 中构建一个简单的进度条或加载动画?

在某些设备上转到主屏幕时 Android 服务停止

android - 使用 retrofit 在 mvvm 中处理 Rxjava 的错误

android - 错误 : resource android:attr/fontVariationSettings not found

android - 如何使 RecyclerView 网格项具有相同的高度和宽度?

javascript - 清除动态可折叠列表,empty() html ("") 不起作用