bounty还有3天到期,回答此问题可获得+50声望奖励,VanessaF希望引起更多关注此问题:由于我还没有收到任何答复或评论,而这个问题对我来说很重要,我不知道如何继续,我将奖励50分的奖金给一个有帮助的答案。我将感谢每一个评论。
我有一个奇怪的问题。我花了相当长的时间在Android中设计了一个自制的画布视图,它应该是一个水箱(即通过R.drawable.hot_water_tank_container
插入的边缘),然后在边缘内还有一个描绘水的蓝色条。
我已经使用这个很多个月了,一切都正常工作。蓝色的酒吧总是显示在水箱边缘内(甚至绘图操作,以减少或增加水酒吧的大小都在边界内)。
现在突然间(在没有故意改变任何东西的情况下),蓝色条不再显示在正确的位置。(自动?)以某种方式减少了。我在许多模拟器和真实的设备上测试了它。同样奇怪的是,在布局编辑器上,自制画布视图看起来完全正确(蓝色条在边框内,尺寸也更大)。
有没有人能想一想为什么会发生这种情况以及如何解决它?
以下是布局编辑器的屏幕截图:
以下是来自模拟器的屏幕截图:
下面是显示片段的XML布局文件:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.game.HotWaterTank
android:id="@+id/hotWaterTank"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.3"
app:layout_constraintHorizontal_bias="0.529"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.895"
app:layout_constraintWidth_percent="0.15" />
<Button
android:id="@+id/button_action"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="Action"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.102"
app:layout_constraintHorizontal_bias="0.373"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.745"
app:layout_constraintWidth_percent="0.13" />
</androidx.constraintlayout.widget.ConstraintLayout>
下面是自制水箱画布视图的Java文件:
package com.example.game;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class HotWaterTank extends View {
private Paint mInnerCirclePaint;
private int innerCircleCenter;
private int hotWaterColor = Color.parseColor("#327bff");
private Bitmap bitmap;
private int left;
private int top;
private int lineEndY;
private int lineStartY;
/*
Set the variables for the positions of the water bar
*/
double positionOfWaterBar = 0.5;
//0.607= empty, - 0.04 = full,
final double value_positionOfWaterBar_Empty = 0.607;
final double value_positionOfWaterBar_Full = -0.04;
final double value_positionOfWaterBar_upperLimit = -0.08;
final double value_positionOfWaterBar_lowerLimit = 0.61;
public HotWaterTank(Context context) {
this(context, null);
}
public HotWaterTank(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HotWaterTank(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (attrs != null) {
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Thermometer, defStyle, 0);
hotWaterColor = a.getColor(R.styleable.Thermometer_therm_color, hotWaterColor);
a.recycle();
}
init();
}
private void init() {
mInnerCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mInnerCirclePaint.setColor(hotWaterColor);
mInnerCirclePaint.setStyle(Paint.Style.FILL);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.hot_water_tank_container);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// init bitmap
int scaledHeight;
int scaledWidth;
int width = getWidth();
int height = getHeight();
if (width > height) {
scaledHeight = (int) (height * 0.5);
scaledWidth = scaledHeight * bitmap.getWidth() / bitmap.getHeight();
} else {
scaledWidth = (int) (width * 0.5);
scaledHeight = scaledWidth * bitmap.getHeight() / bitmap.getWidth();
}
mInnerCirclePaint.setStrokeWidth( (float) (scaledWidth * 0.9));
bitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true);
innerCircleCenter = (left + left + bitmap.getWidth() + (Math.min(width, height) / 72));
left = (getWidth() - bitmap.getWidth()) / 2;
top = (getHeight() - bitmap.getHeight()) / 2;
lineStartY = ((int)(bitmap.getHeight() / 4.6f) + top) + (int) (positionOfWaterBar * bitmap.getHeight());
lineEndY = (top + bitmap.getHeight()) - (int)(bitmap.getHeight() / 7f);
//lineStartY = (int)(4.4*((int)(bitmap.getHeight() / 4.6f) + top));
//lineEndY = (int)(1.0* ((top + bitmap.getHeight()) - (int)(bitmap.getHeight() / 4f)));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawThermometer(canvas);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//takes 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 drawThermometer(Canvas canvas) {
canvas.drawLine(innerCircleCenter , lineStartY, innerCircleCenter, lineEndY, mInnerCirclePaint);
canvas.drawBitmap(bitmap, left, top, new Paint());
}
public void setThermometerColor(int thermometerColor) {
this.hotWaterColor = thermometerColor;
mInnerCirclePaint.setColor(hotWaterColor);
invalidate();
}
public void changeVolumeBar( double percentageChangeOfTheWholeBar) {
double appliedPercentageChangeOfTheWholeBar = percentageChangeOfTheWholeBar / 100;
if (appliedPercentageChangeOfTheWholeBar>1) {
appliedPercentageChangeOfTheWholeBar = 1;
}
if (appliedPercentageChangeOfTheWholeBar <-1) {
appliedPercentageChangeOfTheWholeBar = -1;
}
double absolutValueSpanForTheWholeBar = value_positionOfWaterBar_Full - value_positionOfWaterBar_Empty;
positionOfWaterBar = positionOfWaterBar + appliedPercentageChangeOfTheWholeBar * absolutValueSpanForTheWholeBar;
if (positionOfWaterBar < value_positionOfWaterBar_upperLimit) {
positionOfWaterBar = value_positionOfWaterBar_upperLimit;
}
if(positionOfWaterBar > value_positionOfWaterBar_lowerLimit) {
positionOfWaterBar = value_positionOfWaterBar_lowerLimit;
}
lineStartY = ((int)(bitmap.getHeight() / 4.6f) + top) + (int) (positionOfWaterBar * bitmap.getHeight());
lineEndY = (top + bitmap.getHeight()) - (int)(bitmap.getHeight() / 7f);
}
public void setVolumeBarPosition( double percentageOfTheWholeVolume) {
double appliedVolume = percentageOfTheWholeVolume;
if (appliedVolume < 0) {
appliedVolume = 0;
}
if (appliedVolume >100) {
appliedVolume = 100;
}
double absolutValueSpanForTheWholeBar = value_positionOfWaterBar_Full - value_positionOfWaterBar_Empty;
positionOfWaterBar = value_positionOfWaterBar_Empty + (appliedVolume/100 ) * absolutValueSpanForTheWholeBar;
lineStartY = ((int)(bitmap.getHeight() / 4.6f) + top) + (int) (positionOfWaterBar * bitmap.getHeight());
lineEndY = (top + bitmap.getHeight()) - (int)(bitmap.getHeight() / 7f);
}
}
更新:
我在一个回答中插入了建议:
innerCircleCenter = left + (bitmap.getWidth() / 2)
mInnerCirclePaint.setStrokeWidth((float) (scaledWidth * 0.5))
但结果更糟,正如你在这个场景中看到的:
这里要求的是热水箱容器文件:
2条答案
按热度按时间jckbn6z71#
看起来问题出在
innerCircleCenter
的计算上。我的理解innerCircleCenter
应该是水箱中心的X坐标,但是通过两次添加left
,它稍微向右移动了一点。然后,蓝条的笔画宽度太大,无法容纳在水箱内,所以它被推到了外面。我想你可以这样计算中心:
innerCircleCenter = left + (bitmap.getWidth() / 2)
然后将
mInnerCirclePaint
的笔划宽度修改为比实际宽度小一点,例如mInnerCirclePaint.setStrokeWidth((float) (scaledWidth * 0.5))
9cbw7uwe2#
因为你的
hot_water_tank_container
是一个很大的图像,为了简化计算,我使用AppCompatImageView
作为父代,用xml硬编码android:layout_width
,用java代码硬编码setAdjustViewBounds(true)
。这里的
HotWaterTank
类拍摄: