我有8个圆形放置在表盘上的图像,类似于速度表,第一个图像位于类似于0的位置,而最后一个图像位于类似于200的位置或速度表的最后一个值。
现在我想旋转固定在底座的针并从第一张图像移动到最后一张。当针旋转时,当图像在图像上移动时,图像会发生变化。
针从第一张图像移动到最后一张图像并移回第一张图像。
已删除传感器的代码,因为我不想要并删除背景和主要块添加了一个名为reverse()
的新方法,用于反转运动无法找到我错误的地方。它只执行循环一次并出来。
public final class Thermometer extends View
{
private static final String TAG = Thermometer.class.getSimpleName();
private Handler handler;
// drawing tools
private Paint scalePaint;
private RectF scaleRect;
private Paint logoPaint;
private Bitmap logo;
private Matrix logoMatrix;
private float logoScale;
private Paint handPaint;
private Path handPath;
private Paint handScrewPaint;
private Paint backgroundPaint;
// end drawing tools
private Bitmap background; // holds the cached static part
// scale configuration
private static final int totalNicks = 100;
private static final float degreesPerNick = 360.0f / totalNicks;
private static final int centerDegree = 40; // the one in the top center (12
// o'clock)
private static final int minDegrees = -30;
private static final int maxDegrees = 110;
// hand dynamics -- all are angular expressed in F degrees
private boolean handInitialized = false;
private float handPosition = minDegrees;
private float handTarget = minDegrees;
private float handVelocity = 0.0f;
private float handAcceleration = 0.0f;
private long lastHandMoveTime = -1L;
public Thermometer(Context context)
{
super(context);
init();
}
public Thermometer(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public Thermometer(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
@Override
protected void onRestoreInstanceState(Parcelable state)
{
Bundle bundle = (Bundle) state;
Parcelable superState = bundle.getParcelable("superState");
super.onRestoreInstanceState(superState);
handInitialized = bundle.getBoolean("handInitialized");
handPosition = bundle.getFloat("handPosition");
handTarget = bundle.getFloat("handTarget");
handVelocity = bundle.getFloat("handVelocity");
handAcceleration = bundle.getFloat("handAcceleration");
lastHandMoveTime = bundle.getLong("lastHandMoveTime");
}
@Override
protected Parcelable onSaveInstanceState()
{
Parcelable superState = super.onSaveInstanceState();
Bundle state = new Bundle();
state.putParcelable("superState", superState);
state.putBoolean("handInitialized", handInitialized);
state.putFloat("handPosition", handPosition);
state.putFloat("handTarget", handTarget);
state.putFloat("handVelocity", handVelocity);
state.putFloat("handAcceleration", handAcceleration);
state.putLong("lastHandMoveTime", lastHandMoveTime);
return state;
}
private void init()
{
handler = new Handler();
initDrawingTools();
}
private void initDrawingTools()
{
// the linear gradient is a bit skewed for realism
logoPaint = new Paint();
logoPaint.setFilterBitmap(true);
logo = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.logo);
logoMatrix = new Matrix();
logoScale = (1.0f / logo.getWidth()) * 0.3f;
logoMatrix.setScale(logoScale, logoScale);
handPaint = new Paint();
handPaint.setAntiAlias(true);
handPaint.setColor(0xff392f2c);
handPaint.setShadowLayer(0.01f, -0.005f, -0.005f, 0x7f000000);
handPaint.setStyle(Paint.Style.FILL);
handPath = new Path();
handPath.moveTo(0.5f, 0.5f + 0.2f);
handPath.lineTo(0.5f - 0.010f, 0.5f + 0.2f - 0.007f);
handPath.lineTo(0.5f - 0.002f, 0.5f - 0.32f);
handPath.lineTo(0.5f + 0.002f, 0.5f - 0.32f);
handPath.lineTo(0.5f + 0.010f, 0.5f + 0.2f - 0.007f);
handPath.lineTo(0.5f, 0.5f + 0.2f);
handPath.addCircle(0.5f, 0.5f, 0.025f, Path.Direction.CW);
handScrewPaint = new Paint();
handScrewPaint.setAntiAlias(true);
handScrewPaint.setColor(0xff493f3c);
handScrewPaint.setStyle(Paint.Style.FILL);
backgroundPaint = new Paint();
backgroundPaint.setFilterBitmap(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
Log.d(TAG, "Width spec: " + MeasureSpec.toString(widthMeasureSpec));
Log.d(TAG, "Height spec: " + MeasureSpec.toString(heightMeasureSpec));
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int chosenWidth = chooseDimension(widthMode, widthSize);
int chosenHeight = chooseDimension(heightMode, heightSize);
int chosenDimension = Math.min(chosenWidth, chosenHeight);
setMeasuredDimension(chosenDimension, chosenDimension);
}
private int chooseDimension(int mode, int size)
{
if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY)
{
return size;
}
else
{ // (mode == MeasureSpec.UNSPECIFIED)
return getPreferredSize();
}
}
// in case there is no size specified
private int getPreferredSize()
{
return 300;
}
private void drawScale(Canvas canvas)
{
canvas.drawOval(scaleRect, scalePaint);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
for (int i = 0; i < totalNicks; ++i)
{
float y1 = scaleRect.top;
float y2 = y1 - 0.020f;
canvas.drawLine(0.5f, y1, 0.5f, y2, scalePaint);
if (i % 5 == 0)
{
int value = nickToDegree(i);
if (value >= minDegrees && value <= maxDegrees)
{
String valueString = Integer.toString(value);
canvas.drawText(valueString, 0.5f, y2 - 0.015f, scalePaint);
}
}
canvas.rotate(degreesPerNick, 0.5f, 0.5f);
}
canvas.restore();
}
private int nickToDegree(int nick)
{
int rawDegree = ((nick < totalNicks / 2) ? nick : (nick - totalNicks)) * 2;
int shiftedDegree = rawDegree + centerDegree;
return shiftedDegree;
}
private float degreeToAngle(float degree)
{
return (degree - centerDegree) / 2.0f * degreesPerNick;
}
private void drawLogo(Canvas canvas)
{
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(0.5f - logo.getWidth() * logoScale / 2.0f,0.5f - logo.getHeight() * logoScale / 2.0f);
int color = 0x00000000;
float position = getRelativeTemperaturePosition();
if (position < 0)
{
color |= (int) ((0xf0) * -position); // blue
}
else
{
color |= ((int) ((0xf0) * position)) << 16; // red
}
Log.d(TAG, "*** " + Integer.toHexString(color));
LightingColorFilter logoFilter = new LightingColorFilter(0xff338822,color);
logoPaint.setColorFilter(logoFilter);
canvas.drawBitmap(logo, logoMatrix, logoPaint);
canvas.restore();
}
private void drawHand(Canvas canvas)
{
if (handInitialized)
{
float handAngle = degreeToAngle(handPosition);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(handAngle, 0.5f, 0.5f);
canvas.drawPath(handPath, handPaint);
canvas.restore();
canvas.drawCircle(0.5f, 0.5f, 0.01f, handScrewPaint);
}
}
private void drawBackground(Canvas canvas)
{
if (background == null)
{
Log.w(TAG, "Background not created");
}
else
{
canvas.drawBitmap(background, 0, 0, backgroundPaint);
}
}
@Override
protected void onDraw(Canvas canvas)
{
drawBackground(canvas);
float scale = (float) getWidth();
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(scale, scale);
drawLogo(canvas);
drawHand(canvas);
canvas.restore();
moveHand();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
Log.d(TAG, "Size changed to " + w + "x" + h);
regenerateBackground();
}
private void regenerateBackground()
{
// free the old bitmap
if (background != null)
{
background.recycle();
}
background = Bitmap.createBitmap(getWidth(), getHeight(),Bitmap.Config.ARGB_8888);
Canvas backgroundCanvas = new Canvas(background);
float scale = (float) getWidth();
backgroundCanvas.scale(scale, scale);
}
private boolean handNeedsToMove()
{
return Math.abs(handPosition - handTarget) > 0.01f;
}
private void moveHand()
{
setHandTarget(maxDegrees);
if (!handNeedsToMove())
{
return;
}
if (lastHandMoveTime != -1L)
{
long currentTime = System.currentTimeMillis();
float delta = (currentTime - lastHandMoveTime) / 1500.0f;
float direction = Math.signum(handVelocity);
if (Math.abs(handVelocity) < 90.0f)
{
handAcceleration = 5.0f * (handTarget - handPosition);
}
else
{
handAcceleration = 0.0f;
}
handPosition += handVelocity * delta;
handVelocity += handAcceleration * delta;
if ((handTarget - handPosition) * direction < 0.01f * direction)
{
handPosition = handTarget;
handVelocity = 0.0f;
handAcceleration = 0.0f;
lastHandMoveTime = -1L;
}
else
{
Log.i("inside ","direction else loop");
lastHandMoveTime = System.currentTimeMillis();
}
invalidate();
}
else
{
Log.i("inside ","direction first final else loop");
lastHandMoveTime = System.currentTimeMillis();
moveHand();
}
if(handPosition==maxDegrees)
{
reverse();
}
}
public void reverse()
{
handAcceleration=1.0f;
Log.i("Hand Velocity",Float.toString(handVelocity));
Log.i("Inside","next loop");
setHandTarget(minDegrees);
if (!handNeedsToMove())
{
return;
}
if (lastHandMoveTime != -1L)
{
long currentTime = System.currentTimeMillis();
float delta = (currentTime -lastHandMoveTime) / 1500.0f;
float direction = Math.signum(handVelocity);
if (Math.abs(handVelocity) <90.0f)
{
handAcceleration = 5.0f * (handPosition+handTarget);
Log.i("Hand Acceleration",Float.toString(handAcceleration));
}
else
{
handAcceleration = 0.0f;
}
handPosition -= handVelocity * delta;
handVelocity -= handAcceleration *delta;
if ((handPosition + handTarget) * direction < 0.01f * direction)
{
handPosition = handTarget;
handVelocity = 0.0f;
handAcceleration = 0.0f;
lastHandMoveTime =-1L;
}
else
{
lastHandMoveTime = System.currentTimeMillis();
}
invalidate();
}
else
{
lastHandMoveTime = System.currentTimeMillis();
reverse();
}
}
private float getRelativeTemperaturePosition()
{
if (handPosition < centerDegree)
{
return -(centerDegree - handPosition)/ (float) (centerDegree - minDegrees);
}
else
{
return (handPosition - centerDegree)/ (float) (maxDegrees - centerDegree);
}
}
private void setHandTarget(float temperature)
{
if (temperature < minDegrees)
{
temperature = minDegrees;
}
else if (temperature > maxDegrees)
{
temperature = maxDegrees;
}
handTarget = temperature;
handInitialized = true;
invalidate();
}
}
答案 0 :(得分:0)
只需将手部位置初始化到最大程度,然后在moveHand()
方法setHandTarget(minDegrees)
中将逆时针旋转初始化它对我有效。
对于顺时针旋转,请执行相反的操作。
答案 1 :(得分:0)
我已经解决了在主要活动中显示和移动插入的问题:
View termometro = (View)findViewById(R.id.termometro);
termometro.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
它与硬件加速有关