Android工作室onDraw未使用更新的值



我目前遇到了一个问题,已经解决了好几天了。

我的目标是创建一个使用加速度计传感器的大理石迷宫游戏。我关注了一些在线资源,当我刚刚创建了一个BallView,它在我的"活动"中扩展了View并以编程方式创建了这个视图时,我就能够让它发挥作用。

然而,我也需要在视图的左下角有一个按钮,我发现这无法在自定义视图中完成。我在网上搜索了一下,找到了一个创建MarbleView的解决方案,该解决方案用一个单独的类扩展了视图。然后,我把这个自定义视图和我的按钮一起放在我的xml文件中,并用我的活动对它们进行扩展。

我看到了膨胀的结果:我的大理石迷宫和一个按钮;然而,现在的问题是视图不再更新大理石的位置。我注意到球x,y的位置在updateBall((中更新,但在onDraw((没有更新,尽管这两个位置都是从同一个大理石模型参考更新的。我认为这与线程有关,但就是不知道如何修复它。

MarbleModel使用x、y、z轴上的加速度计算更新后的球位置。它还为视图绘制边界和障碍。

我的原始代码在没有按钮的情况下工作:

public class MarbleActivity extends AppCompatActivity implements SensorEventListener2 {
private Point pixelSize;
private float xPos, yPos;
private Bitmap ball;
private MarbleModel marbleModel;
private SensorManager sensorManager;
@SuppressLint("SourceLockedOrientationActivity")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
pixelSize = new Point();
Display display = getWindowManager().getDefaultDisplay();
display.getSize(pixelSize);
intent = getIntent();
gameLocation = intent.getStringExtra(GAME_LOCATION);
// instantiate MarbleGame with phone screen parameters
marbleModel = new MarbleModel(pixelSize.x, pixelSize.y);
xPos = marbleModel.getXPos();
yPos = marbleModel.getYPos();

BallView ballView = new BallView(this);
setContentView(ballView);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}

@Override
protected void onStart() {
super.onStart();
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_GAME);
}
@Override
protected void onStop() {
sensorManager.unregisterListener(this);
super.onStop();
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float xAcc = sensorEvent.values[0];
float yAcc = -sensorEvent.values[1];
float zAcc = sensorEvent.values[2];
marbleModel.updateParameters(xAcc, yAcc, zAcc);
updateBall();
}
}
@Override
public void onFlushCompleted(Sensor sensor) {
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private void updateBall() {
xPos = marbleModel.getXPos();
yPos = marbleModel.getYPos();
}
private class BallView extends View {
public BallView(Context context) {
super(context);
Bitmap ballSrc = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
final int dstWidth = marbleModel.getRadius() * 2;
final int dstHeight = marbleModel.getRadius() * 2;
ball = Bitmap.createScaledBitmap(ballSrc, dstWidth, dstHeight, true);
getRootView().setBackgroundColor(Color.parseColor("#C9E4CA"));
}

@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(ball, xPos, yPos, null);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize((int) (pixelSize.y * 0.05));
for (Rect border : marbleModel.getBorders()) {
canvas.drawRect(border, paint);
}
for (Rect barrier: marbleModel.getBarriers()) {
canvas.drawRect(barrier, paint);
}
canvas.save();
canvas.rotate(90);
canvas.drawText("Roll The Ball To Target",
(float) (0.08 * pixelSize.y), -(float) (0.84 * pixelSize.x), paint);
canvas.restore();
invalidate();
}
}
}

包含按钮但球位置的代码无法更新。

(MarbleView被我的MainActivity夸大了(

public class MarbleView extends View implements SensorEventListener2 {
private MarbleModel marbleModel;
private float xPos, yPos;
private Bitmap ball;
private float xAcc, yAcc, zAcc = 0f;
private int width;
private int height;
private SensorManager sensorManager;
public MarbleView(Context context) {
super(context);
init(null, context);
}
public MarbleView(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs, context);
}
public MarbleView(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, context);
}
public MarbleView(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs, context);
}
private void init (AttributeSet attrs, Context context) {
Bitmap ballSrc = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
width = metrics.widthPixels;
height = metrics.heightPixels;
// instantiate MarbleGame with phone screen parameters
marbleModel = new MarbleModel(width, height);
xPos = marbleModel.getXPos();
yPos = marbleModel.getYPos();
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
final int dstWidth = marbleModel.getRadius() * 2;
final int dstHeight = marbleModel.getRadius() * 2;
ball = Bitmap.createScaledBitmap(ballSrc, dstWidth, dstHeight, true);
getRootView().setBackgroundColor(Color.parseColor("#C9E4CA"));
}
public void updateBall(float xAcc, float yAcc, float zAcc) {
this.xAcc = xAcc;
this.yAcc = yAcc;
this.zAcc = zAcc;
marbleModel.updateParameters(xAcc, yAcc, zAcc);
Log.i("updateball", String.valueOf(yAcc));

xPos = marbleModel.getXPos();
yPos = marbleModel.getYPos();
}
@Override
protected void onDraw(Canvas canvas) {
Log.i("ondraw", String.valueOf(yAcc));
canvas.drawBitmap(ball, xPos, yPos, null);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize((int) (height * 0.05));
for (Rect border : marbleModel.getBorders()) {
canvas.drawRect(border, paint);
}
for (Rect barrier: marbleModel.getBarriers()) {
canvas.drawRect(barrier, paint);
}
canvas.save();
canvas.rotate(90);
canvas.drawText("Roll The Ball To Target",
(float) (0.08 * height), -(float) (0.84 * width), paint);
canvas.restore();
invalidate();
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float xAcc = sensorEvent.values[0];
float yAcc = -sensorEvent.values[1];
float zAcc = sensorEvent.values[2];
updateBall(xAcc, yAcc, zAcc);
Log.i("on sensor changed", String.valueOf(yAcc));
}
}
@Override
public void onFlushCompleted(Sensor sensor) {
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}

感谢所有的帮助!

ok,所以我意外地发现这是因为我实例化了两次自定义视图:BallView-BallView=new BallView(this(和xml文件中的另一个。我基本上做的是删除BallView实例化,并将BallView-BallView=findViewbyId(R.id.ball_view(。我还修改了一些其他代码,使onDraw不会调用invalidate((。

我的代码有效:

public class MarbleActivity2 extends AppCompatActivity implements SensorEventListener2 {
private MarbleView marbleView;
private SensorManager sensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Point pixelSize = new Point();
Display display = getWindowManager().getDefaultDisplay();
display.getSize(pixelSize);
setContentView(R.layout.activity_marble2);
marbleView = findViewById(R.id.marbleView);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
@Override
protected void onStart() {
super.onStart();
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_GAME);
}
@Override
protected void onStop() {
sensorManager.unregisterListener(this);
super.onStop();
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float xAcc = sensorEvent.values[0];
float yAcc = -sensorEvent.values[1];
float zAcc = sensorEvent.values[2];
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
marbleView.updateBall(xAcc, yAcc, zAcc);
marbleView.postInvalidate();
}
}, 333);
}
}
@Override
public void onFlushCompleted(Sensor sensor) {
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
public class MarbleView extends View {
private MarbleModel marbleModel;
private float xPos, yPos;
private Bitmap ball;
private float xAcc, yAcc, zAcc = 0f;
private int width;
private int height;
public MarbleView(Context context) {
super(context);
init(null, context);
}
public MarbleView(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs, context);
}
public MarbleView(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, context);
}
public MarbleView(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs, context);
}
private void init (AttributeSet attrs, Context context) {
Bitmap ballSrc = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
width = metrics.widthPixels;
height = metrics.heightPixels;
// instantiate MarbleGame with phone screen parameters
marbleModel = new MarbleModel(width, height);
xPos = marbleModel.getXPos();
yPos = marbleModel.getYPos();
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
final int dstWidth = marbleModel.getRadius() * 2;
final int dstHeight = marbleModel.getRadius() * 2;
ball = Bitmap.createScaledBitmap(ballSrc, dstWidth, dstHeight, true);
getRootView().setBackgroundColor(Color.parseColor("#C9E4CA"));
}
public void updateBall(float xAcc, float yAcc, float zAcc) {
this.xAcc = xAcc;
this.yAcc = yAcc;
this.zAcc = zAcc;
marbleModel.updateParameters(xAcc, yAcc, zAcc);
Log.i("updateball", String.valueOf(yAcc));
xPos = marbleModel.getXPos();
yPos = marbleModel.getYPos();
postInvalidate();
}
@Override
protected void onDraw(Canvas canvas) {
Log.i("ondraw", String.valueOf(yAcc));
canvas.drawBitmap(ball, xPos, yPos, null);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize((int) (height * 0.05));
canvas.drawText("ver 2.01", 500, 1700, paint);
for (Rect border : marbleModel.getBorders()) {
canvas.drawRect(border, paint);
}
for (Rect barrier: marbleModel.getBarriers()) {
canvas.drawRect(barrier, paint);
}
canvas.save();
canvas.rotate(90);
canvas.drawText("Roll The Ball To Target",
(float) (0.08 * height), -(float) (0.84 * width), paint);
canvas.restore();
}
}

最新更新