- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
如何自定义 ProgressBar 使其看起来像温度计?可以改变颜色。
我的建议是将 progressBar 旋转 90° 使其垂直,然后让它覆盖空温度计的图像,但这是一个糟糕且困惑的解决方案。
我认为最好是扩展 View 或 ProgressBar 类并自定义绘制方法,但我不知道如何绘制温度计,任何帮助将不胜感激。
最佳答案
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/
我的应用程序中有一个 ProgressBar 小部件,无论我做什么,它总是显示为粗橙色(2.x 样式)而不是细蓝色(4.x 样式) . 项目构建目标设置为 Google API 4.0.3(API 级
private static ProgressDialog pDialog; pDialog = new ProgressDialog(activity); pDialog.setIndetermin
我试图让 TalkBack 阅读进度条上的进度,但运气不佳。关于如何获取该信息以便 TalkBack 可以说出来的任何想法。 谢谢 公共(public)类 MainActivity 扩展 Activi
进度条总是返回null public void calcola(View view) { final Dialog myDialog = new Dialog(this);
我正在尝试用选取框样式测试进度条,但没有成功 private void Form1_Load(object sender, EventArgs e) { Applica
我使用以下 Ruby 片段下载 a 8.9MB file . require 'open-uri' require 'net/http' require 'uri' def http_download
我为操作栏按钮尝试了两种不同的进度条样式,通过 refreshMenuItem.setActionView(R.layout.actionbar_indeterminate_progress); ac
每当我输入 fragment 时,我都会看到几秒钟的空白,然后 WebView 中的网页就会出现。 ProgressBar 好像没有显示。 这是我的 XML 文件,用于 WebView 和 Progr
我的包依赖于一个名为 progressbar 的包。有一个bug in progressbar 2.3导致Python>3.3安装失败,因此我安装了latest git repo from this
任何默认的 ProgressBar 都有一个 ClipDrawable 级别,例如,一个绿色的 Drawable 在我的设备上填充灰色背景,在其他设备上填充黄色。 我的问题:当进度小于最大值时,是否可
这是随意的原型(prototype)代码,因此我尝试了我认为应该有效的方法,如果没有,则在谷歌上搜索,然后在仔细阅读类似问题后在这里提问。 我的 Shell 中有以下标记看法:
要在执行查询时显示 ProgressBar,我使用以下代码: if not Query1.Prepared then Query1.Prepare; Query1.Open; ProgressBa
我有三个类,例如 View 、逻辑、 Controller 。 class View{ Progressbutton pb; void start animation(){
我正在用 C#/WPF(.Net 框架 4.0)编写一个应用程序。我遇到的一件事是如何在应用程序非常繁忙时更新控件(如果可能)。我想我只是在努力尝试我在网上找到的东西来让它工作(而且在极少数情况下它会
要在执行查询时显示 ProgressBar,我使用以下代码: if not Query1.Prepared then Query1.Prepare; Query1.Open; ProgressBa
已关闭。此问题不符合 Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 已关闭 3 年前。 奥 git _a
我创建了一个 ping 程序来 ping 5 服务器。如何在进度运行时让进度条运行。当 ping 完成时,进度条将为 100% private void btnGetstatusActionPer
我想在流程完成后在 PrimeFaces 上隐藏一个进度条。我认为没有必要在不工作时显示进度条。 html代码:
我想添加JProgressBar,它将在下载文件的程序中填充。 第三个问题是如何使进度条在 setValue 中添加正确的金额(例如:当它下载最后一个文件时,JPB 将完成)。 请注意,要下载的文件数
给定一个变量 N,反射(reflect)秒数,我想要一个 jQueryUI Progressbar顺利地从空更新到反射(reflect)该时间段内的完成。 换句话说,我想要一个显示进度条的functi
我是一名优秀的程序员,十分优秀!