gpt4 book ai didi

android - 自定义 ProgressBar 成为温度计

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:03:36 27 4
gpt4 key购买 nike

如何自定义 ProgressBar 使其看起来像温度计?可以改变颜色。

Thermometer bleu full Thermometer bleu empty Thermometer red full Thermometer red empty

我的建议是将 progressBar 旋转 90° 使其垂直,然后让它覆盖空温度计的图像,但这是一个糟糕且困惑的解决方案。

我认为最好是扩展 View 或 ProgressBar 类并自定义绘制方法,但我不知道如何绘制温度计,任何帮助将不胜感激。

最佳答案

我为一个项目创建了这样的东西 Thermometer Widget

    package com.janslab.thermometer.widgets;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.Scroller;

import com.janslab.thermometer.R;



public class DummyThermometer extends View {

private Paint mInnerCirclePaint;
private Paint mOuterCirclePaint;
private Paint mFirstOuterCirclePaint;

//thermometer arc paint
private Paint mFirstOuterArcPaint;


//thermometer lines paints
private Paint mInnerLinePaint;
private Paint mOuterLinePaint;
private Paint mFirstOuterLinePaint;


//thermometer radii
private int mOuterRadius;
private int mInnerRadius;
private int mFirstOuterRadius;


//thermometer colors
private int mThermometerColor = Color.rgb(200, 115, 205);

//circles and lines variables
private float mLastCellWidth;
private int mStageHeight;
private float mCellWidth;
private float mStartCenterY; //center of first cell
private float mEndCenterY; //center of last cell
private float mStageCenterX;
private float mXOffset;
private float mYOffset;

// I 1st Cell I 2nd Cell I 3rd Cell I
private static final int NUMBER_OF_CELLS = 3; //three cells in all ie.stageHeight divided into 3 equal cells

//animation variables
private float mIncrementalTempValue;
private boolean mIsAnimating;
private Animator mAnimator;


public DummyThermometer(Context context) {
this(context, null);
}

public DummyThermometer(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public DummyThermometer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

if (attrs != null) {

final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Thermometer, defStyle, 0);

mThermometerColor = a.getColor(R.styleable.Thermometer_therm_color, mThermometerColor);

a.recycle();
}

init();
}


private void init() {

mInnerCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mInnerCirclePaint.setColor(mThermometerColor);
mInnerCirclePaint.setStyle(Paint.Style.FILL);
mInnerCirclePaint.setStrokeWidth(17f);


mOuterCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mOuterCirclePaint.setColor(Color.WHITE);
mOuterCirclePaint.setStyle(Paint.Style.FILL);
mOuterCirclePaint.setStrokeWidth(32f);


mFirstOuterCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFirstOuterCirclePaint.setColor(mThermometerColor);
mFirstOuterCirclePaint.setStyle(Paint.Style.FILL);
mFirstOuterCirclePaint.setStrokeWidth(60f);


mFirstOuterArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFirstOuterArcPaint.setColor(mThermometerColor);
mFirstOuterArcPaint.setStyle(Paint.Style.STROKE);
mFirstOuterArcPaint.setStrokeWidth(30f);


mInnerLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mInnerLinePaint.setColor(mThermometerColor);
mInnerLinePaint.setStyle(Paint.Style.FILL);
mInnerLinePaint.setStrokeWidth(17f);

mOuterLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mOuterLinePaint.setColor(Color.WHITE);
mOuterLinePaint.setStyle(Paint.Style.FILL);


mFirstOuterLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFirstOuterLinePaint.setColor(mThermometerColor);
mFirstOuterLinePaint.setStyle(Paint.Style.FILL);


}


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);

mStageCenterX = getWidth() / 2;

mStageHeight = getHeight();

mCellWidth = mStageHeight / NUMBER_OF_CELLS;

//center of first cell
mStartCenterY = mCellWidth / 2;


//move to 3rd cell
mLastCellWidth = (NUMBER_OF_CELLS * mCellWidth);

//center of last(3rd) cell
mEndCenterY = mLastCellWidth - (mCellWidth / 2);


// mOuterRadius is 1/4 of mCellWidth
mOuterRadius = (int) (0.25 * mCellWidth);

mInnerRadius = (int) (0.656 * mOuterRadius);

mFirstOuterRadius = (int) (1.344 * mOuterRadius);

mFirstOuterLinePaint.setStrokeWidth(mFirstOuterRadius);

mOuterLinePaint.setStrokeWidth(mFirstOuterRadius / 2);

mFirstOuterArcPaint.setStrokeWidth(mFirstOuterRadius / 4);

mXOffset = mFirstOuterRadius / 4;
mXOffset = mXOffset / 2;

//get the d/f btn firstOuterLine and innerAnimatedline
mYOffset = (mStartCenterY + (float) 0.875 * mOuterRadius) - (mStartCenterY + mInnerRadius);
mYOffset = mYOffset / 2;

}


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

drawFirstOuterCircle(canvas);

drawOuterCircle(canvas);

drawInnerCircle(canvas);

drawFirstOuterLine(canvas);

drawOuterLine(canvas);

animateInnerLine(canvas);

drawFirstOuterCornerArc(canvas);

}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

//take care of paddingTop and paddingBottom
int paddingY = getPaddingBottom() + getPaddingTop();

//get height and width
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);

height += paddingY;

setMeasuredDimension(width, height);
}


private void drawInnerCircle(Canvas canvas) {
drawCircle(canvas, mInnerRadius, mInnerCirclePaint);
}

private void drawOuterCircle(Canvas canvas) {
drawCircle(canvas, mOuterRadius, mOuterCirclePaint);
}


private void drawFirstOuterCircle(Canvas canvas) {
drawCircle(canvas, mFirstOuterRadius, mFirstOuterCirclePaint);
}


private void drawCircle(Canvas canvas, float radius, Paint paint) {
canvas.drawCircle(mStageCenterX, mEndCenterY, radius, paint);
}

private void drawOuterLine(Canvas canvas) {

float startY = mEndCenterY - (float) (0.875 * mOuterRadius);
float stopY = mStartCenterY + (float) (0.875 * mOuterRadius);

drawLine(canvas, startY, stopY, mOuterLinePaint);
}


private void drawFirstOuterLine(Canvas canvas) {

float startY = mEndCenterY - (float) (0.875 * mFirstOuterRadius);
float stopY = mStartCenterY + (float) (0.875 * mOuterRadius);

drawLine(canvas, startY, stopY, mFirstOuterLinePaint);
}


private void drawLine(Canvas canvas, float startY, float stopY, Paint paint) {
canvas.drawLine(mStageCenterX, startY, mStageCenterX, stopY, paint);
}


//simulate temperature measurement for now
private void animateInnerLine(Canvas canvas) {

if (mAnimator == null)
measureTemperature();


if (!mIsAnimating) {

mIncrementalTempValue = mEndCenterY + (float) (0.875 * mInnerRadius);

mIsAnimating = true;

} else {

mIncrementalTempValue = mEndCenterY + (float) (0.875 * mInnerRadius) - mIncrementalTempValue;

}

if (mIncrementalTempValue > mStartCenterY + mInnerRadius) {
float startY = mEndCenterY + (float) (0.875 * mInnerRadius);
drawLine(canvas, startY, mIncrementalTempValue, mInnerCirclePaint);

} else {

float startY = mEndCenterY + (float) (0.875 * mInnerRadius);
float stopY = mStartCenterY + mInnerRadius;
drawLine(canvas, startY, stopY, mInnerCirclePaint);
mIsAnimating = false;
stopMeasurement();

}

}


private void drawFirstOuterCornerArc(Canvas canvas) {

float y = mStartCenterY - (float) (0.875 * mFirstOuterRadius);

RectF rectF = new RectF(mStageCenterX - mFirstOuterRadius / 2 + mXOffset, y + mFirstOuterRadius, mStageCenterX + mFirstOuterRadius / 2 - mXOffset, y + (2 * mFirstOuterRadius) + mYOffset);

canvas.drawArc(rectF, -180, 180, false, mFirstOuterArcPaint);

}


public void setThermometerColor(int thermometerColor) {
this.mThermometerColor = thermometerColor;

mInnerCirclePaint.setColor(mThermometerColor);

mFirstOuterCirclePaint.setColor(mThermometerColor);

mFirstOuterArcPaint.setColor(mThermometerColor);

mInnerLinePaint.setColor(mThermometerColor);

mFirstOuterLinePaint.setColor(mThermometerColor);

invalidate();
}


//simulate temperature measurement for now
private void measureTemperature() {
mAnimator = new Animator();
mAnimator.start();
}


private class Animator implements Runnable {
private Scroller mScroller;
private final static int ANIM_START_DELAY = 1000;
private final static int ANIM_DURATION = 4000;
private boolean mRestartAnimation = false;

public Animator() {
mScroller = new Scroller(getContext(), new AccelerateDecelerateInterpolator());
}

public void run() {
if (mAnimator != this)
return;

if (mRestartAnimation) {
int startY = (int) (mStartCenterY - (float) (0.875 * mInnerRadius));
int dy = (int) (mEndCenterY + mInnerRadius);
mScroller.startScroll(0, startY, 0, dy, ANIM_DURATION);
mRestartAnimation = false;
}

boolean isScrolling = mScroller.computeScrollOffset();
mIncrementalTempValue = mScroller.getCurrY();

if (isScrolling) {
invalidate();
post(this);
} else {
stop();
}


}

public void start() {
mRestartAnimation = true;
postDelayed(this, ANIM_START_DELAY);
}

public void stop() {
removeCallbacks(this);
mAnimator = null;
}

}


private void stopMeasurement() {
if (mAnimator != null)
mAnimator.stop();
}


@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();

measureTemperature();

}

@Override
protected void onDetachedFromWindow() {
stopMeasurement();

super.onDetachedFromWindow();
}

@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
switch (visibility) {
case View.VISIBLE:

measureTemperature();

break;

default:

stopMeasurement();

break;
}
}


}

attrs.xml文件

    <?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Thermometer">

<attr name="therm_color" format="color" />

</declare-styleable>

</resources>

关于android - 自定义 ProgressBar 成为温度计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28769244/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com