- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是一名经验丰富的开发人员,在因病休假 2 年后(6 次中风,濒临死亡,但重建了一切!),我刚刚回到 Android。不管怎样,我正在玩弄一个自定义的子类 ImageView。我的 onTouch 和 onDraw 运行良好。我在主要 Activity 中为加速度计添加了一个监听器,因此我也可以用它移动我的 Sprite 。
向左倾斜使我的 Sprite 按预期向左移动,就像向上一样。如果我向右倾斜,它仍然会向左移动。同样,如果我向下倾斜,它仍会向上移动。
我确定我看不到东西,因为我已经盯着它看太久了,所以我希望有一双新眼睛!
谢谢
李
package com.tilleytech.wubl.view;
/**
* Created by Leigh on 09/03/2015.
*/
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import com.tilleytech.wubl.R;
import com.tilleytech.wubl.WUBLApplication;
import com.tilleytech.wubl.object.Point;
import com.tilleytech.wubl.util.Util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class DrawView extends ImageView implements OnTouchListener {
public static enum DIRECTION {LEFT, RIGHT, UP, DOWN};
private static final String TAG = "DrawView";
private Bitmap player = null;
private Bitmap saucer = null;
private Bitmap saucer2 = null;
private Bitmap saucer3 = null;
private int saucerLeft=1100;
private int saucer2Left=1400;
private int saucer3Left=1250;
//boundary of our view
private static final int XMIN = 0;
private static final int XBOUNDARY=1080;
private static final int YMIN=0;
private static final int YBOUNDARY=1920;
List<Point> points = new ArrayList<Point>();
Paint paint = new Paint();
public DrawView(Context context) {
super(context);
init(context);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
/* paint.setColor(Color.WHITE);
paint.setAntiAlias(true);*/
player = Util.decodeSampledBitmapFromResource(getResources(), R.drawable.player, 80, 93);
saucer = Util.decodeSampledBitmapFromResource(getResources(), R.drawable.saucer, 100, 73);
saucer2 = Util.decodeSampledBitmapFromResource(getResources(), R.drawable.saucer2, 100, 73);
saucer3 = Util.decodeSampledBitmapFromResource(getResources(), R.drawable.saucer3, 100, 73);
setWillNotDraw(false);
}
@Override
public void onDraw(Canvas canvas) {
//test out some UFOs in here for now
if(saucer2Left<-150) {
saucerLeft=1100;
saucer2Left= 1400;
saucer3Left=1250;
}
canvas.drawBitmap(saucer, saucerLeft--, 10, null);
canvas.drawBitmap(saucer2, saucer2Left--, 10, null);
canvas.drawBitmap(saucer3, saucer3Left--, 125, null);
//We have 20 points which will create a trail effect
WUBLApplication.logMessage("Whiz through our points drawing to canvas.", TAG, WUBLApplication.LogLevel.Debug);
synchronized (points) {
for (Point point : points) { //set in onTouch
canvas.drawBitmap(player, point.getX(), point.getY(), null);
}
}
}
public boolean onTouch(View view, MotionEvent event) {
int eventAction = event.getAction();
switch (eventAction) {
case MotionEvent.ACTION_DOWN:
// finger touches the screen
break;
case MotionEvent.ACTION_MOVE:
// finger moves on the screen
Point point = new Point(event.getX(), event.getY());
addPoint(point);
synchronized (points) {
if (points.size() > 20) {
points.remove(0);
}
}
break;
case MotionEvent.ACTION_UP:
// finger leaves the screen
cleanUpPoints();
break;
}
//Force a repaint
invalidate();
return true;
}
public void cleanUpPoints() {
synchronized (points) {
int counter = 1;
int max = points.size()-1;
Iterator<Point> it = points.iterator();
while (it.hasNext() & counter <= max) {
it.next();
it.remove();
counter++;
}
}
}
public void addPoint(Point point) {
//WUBLApplication.logMessage("addPoint: " + point.toString(), TAG, WUBLApplication.LogLevel.Debug);
synchronized (points){
points.add(point);
}
}
public Point getPoint(int index) {
Point point=null;
if(index>-1) {
synchronized (points) {
if (!points.isEmpty()) {
point = points.get(index);
}
}
}
return point;
}
public Point getLastPoint() {
Point point=null;
//WUBLApplication.logMessage("getLastPoint before synch block", TAG, WUBLApplication.LogLevel.Debug);
synchronized (points) {
//WUBLApplication.logMessage("Points isEmpty: " + points.isEmpty(), TAG, WUBLApplication.LogLevel.Debug);
if (!points.isEmpty()) {
point = points.get(points.size() - 1);
}
}
return point;
}
public void clearPoints() {
synchronized (points){
points.clear();
}
}
public int getPointsSize(){
int result=0;
synchronized (points){
result=points.size();
}
return result;
}
public void moveSprite(DIRECTION direction, float change) {
//Called from accelerometer listener in activity using this view
WUBLApplication.logMessage("moveSprite with direction: " + direction.toString(), TAG, WUBLApplication.LogLevel.Debug);
//Get the last point and shift from here
Point lastKnownPoint = getLastPoint();
switch (direction) {
case LEFT: {
WUBLApplication.logMessage("moveSprite inside LEFT", TAG, WUBLApplication.LogLevel.Debug);
if (lastKnownPoint != null) {
float lastX = lastKnownPoint.getX();
float lastY = lastKnownPoint.getY();
if (lastX - change > XMIN && lastX - change < XBOUNDARY) {
WUBLApplication.logMessage("LEFT: subtract from x", TAG, WUBLApplication.LogLevel.Debug);
lastX -= change;
addPoint(new Point(lastX, lastY));
}
}
break;
}
case RIGHT: {
WUBLApplication.logMessage("moveSprite inside RIGHT", TAG, WUBLApplication.LogLevel.Debug);
if (lastKnownPoint != null) {
float lastX = lastKnownPoint.getX();
float lastY = lastKnownPoint.getY();
if (lastX + change > XMIN && lastX + change < XBOUNDARY) {
WUBLApplication.logMessage("RIGHT: add to x", TAG, WUBLApplication.LogLevel.Debug);
lastX += change;
addPoint(new Point(lastX, lastY));
}
}
break;
}
case UP: {
WUBLApplication.logMessage("moveSprite inside UP", TAG, WUBLApplication.LogLevel.Debug);
if (lastKnownPoint != null) {
float lastX = lastKnownPoint.getX();
float lastY = lastKnownPoint.getY();
WUBLApplication.logMessage("UP: Add to y", TAG, WUBLApplication.LogLevel.Debug);
if (lastY + change > YMIN && lastY + change < YBOUNDARY) {
lastY += change;
addPoint(new Point(lastX, lastY));
}
}
break;
}
case DOWN: {
WUBLApplication.logMessage("moveSprite inside DOWN", TAG, WUBLApplication.LogLevel.Debug);
if (lastKnownPoint != null) {
float lastX = lastKnownPoint.getX();
float lastY = lastKnownPoint.getY();
if (lastY - change > YMIN && lastY - change < YBOUNDARY) {
WUBLApplication.logMessage("DOWN: subtract from y", TAG, WUBLApplication.LogLevel.Debug);
lastY -= change;
addPoint(new Point(lastX, lastY));
}
}
break;
}
}
invalidate();
}
}
和 Activity 类:
package com.tilleytech.wubl.activity;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import com.tilleytech.wubl.R;
import com.tilleytech.wubl.WUBLApplication;
import com.tilleytech.wubl.view.DrawView;
/**
* Created by Leigh on 09/03/2015.
*/
public class DrawingViewActivity extends Activity implements SensorEventListener {
DrawView drawView;
private SensorManager sensorManager;
private Sensor accelerometer;
private final static String TAG = DrawingViewActivity.class.getSimpleName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_drawingview);
drawView = (DrawView)findViewById(R.id.drawingview);
listenAccelerometer();
drawView.requestFocus();
}
protected void listenAccelerometer() {
WUBLApplication.logMessage("Request sensor service", TAG, WUBLApplication.LogLevel.Debug);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
// success! we have an accelerometer
WUBLApplication.logMessage("Link to accelerometer", TAG, WUBLApplication.LogLevel.Debug);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
} else {
// fai! we dont have an accelerometer!
WUBLApplication.logMessage("No accelerometer found!", TAG, WUBLApplication.LogLevel.Debug);
}
}
//onResume() register the accelerometer for listening the events
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
//onPause() unregister the accelerometer for stop listening the events
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
int speed = 6;
if (Math.abs(x) > Math.abs(y)) {
if (x < 0) {
//right
WUBLApplication.logMessage("accelerometer right", TAG, WUBLApplication.LogLevel.Debug);
float xChange = speed * x;
drawView.moveSprite(DrawView.DIRECTION.RIGHT, xChange);
}
if (x > 0) {
//left
WUBLApplication.logMessage("accelerometer left", TAG, WUBLApplication.LogLevel.Debug);
float xChange = speed * x;
drawView.moveSprite(DrawView.DIRECTION.LEFT, xChange);
}
} else {
if (y < 0) {
//up
WUBLApplication.logMessage("accelerometer up", TAG, WUBLApplication.LogLevel.Debug);
float yChange = speed * y;
drawView.moveSprite(DrawView.DIRECTION.UP, yChange);
}
if (y > 0) {
//down
WUBLApplication.logMessage("accelerometer down", TAG, WUBLApplication.LogLevel.Debug);
float yChange = speed * y;
drawView.moveSprite(DrawView.DIRECTION.DOWN, yChange);
}
}
if (x > (-2) && x < (2) && y > (-2) && y < (2)) {
//centre
drawView.cleanUpPoints();
//nothing, hold
}
}
@Override
protected void onStop()
{
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
}
最佳答案
所以我最近才回到 Android 的东西,我不敢相信我在 2015 年发布了这个!
反正我今天看了看,已经解决了。从本质上讲,您需要意识到您需要考虑 z、y 和 z 轴的工作方式以及您要实现的目标。
这是 x、y 和 z 平面如何相对于加速度计工作的漂亮图片:
我做错的是将 x 和 y 的实际值(在这个例子/问题中不关心 z)传递到我的自定义 ImageView,然后递减或递增左/右或上/下。
所以我的加速度计代码可以正常工作(左/右/上/下的 logcat)但我的图像移动没有。
我记录了实际值,然后我意识到如果 x 或 y 小于 0,则需要将 Math.abs 值传递给已经根据 a 决定递减或递增的函数特定方向(我在 SensorEventListener 的 onChanged 事件实现中检测到左/右/上/下。在这种情况下,我的自定义子类 ImageView DrawView 决定递减或递增。
这是一个粗略的原型(prototype),所以这两个类实际上是紧密耦合的,但我仍然认为有些人可能会发现这段代码很有用。
同样值得注意的是,低于 2 的值只是噪声;如果您尝试使用传感器,您会从日志记录中注意到它们非常敏感并且一直在发射!
package com.tilleytech.wubl.activity;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import com.tilleytech.wubl.R;
import com.tilleytech.wubl.WUBLApplication;
import com.tilleytech.wubl.view.DrawView;
/**
* Created by Leigh on 09/03/2015.
* Updated 19/06/2017
*/
public class DrawingViewActivity extends Activity implements SensorEventListener {
DrawView drawView;
private SensorManager sensorManager;
private Sensor accelerometer;
private final static String TAG = DrawingViewActivity.class.getSimpleName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_drawingview);
drawView = (DrawView)findViewById(R.id.drawingview);
listenAccelerometer();
drawView.requestFocus();
}
protected void listenAccelerometer() {
WUBLApplication.logMessage("Request sensor service", TAG, WUBLApplication.LogLevel.Debug);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
// success! we have an accelerometer
WUBLApplication.logMessage("Link to accelerometer", TAG, WUBLApplication.LogLevel.Debug);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
} else {
// fai! we dont have an accelerometer!
WUBLApplication.logMessage("No accelerometer found!", TAG, WUBLApplication.LogLevel.Debug);
}
}
//onResume() register the accelerometer for listening the events
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
//onPause() unregister the accelerometer for stop listening the events
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
float x = event.values[0]; //HORIZONTAL
float y = event.values[1]; //VERTICAL
float z = event.values[2]; //INTO SCREEN
//Just noise
if (x > (-2) && x < (2) && y > (-2) && y < (2)) {
//centre
drawView.cleanUpPoints();
//nothing, hold
}
else {
int speed = 6;
if (Math.abs(x) > Math.abs(y)) {
//HORIZONTAL PLANE
if (x < 0) {
//right
WUBLApplication.logMessage("accelerometer RIGHT x: " + x + " y: " + y, TAG, WUBLApplication.LogLevel.Debug);
//As we have the actual value we need to abs it so that it doesn't subtract!
float xChange = speed * Math.abs(x);
drawView.moveSprite(DrawView.DIRECTION.RIGHT, xChange);
} else if (x > 0) {
//left
WUBLApplication.logMessage("accelerometer LEFT x: " + x + " y: " + y, TAG, WUBLApplication.LogLevel.Debug);
float xChange = speed * x;
drawView.moveSprite(DrawView.DIRECTION.LEFT, xChange);
}
} else {
//VERTICAL PLANE
if (y > 0) {
//up
WUBLApplication.logMessage("accelerometer UP x: " + x + " y: " + y, TAG, WUBLApplication.LogLevel.Debug);
float yChange = speed * y;
drawView.moveSprite(DrawView.DIRECTION.UP, yChange);
} else if (y < 0) {
//down
WUBLApplication.logMessage("accelerometer DOWN x: " + x + " y: " + y, TAG, WUBLApplication.LogLevel.Debug);
//As we have the actual value we need to abs it so that it doesn't subtract!
float yChange = speed * Math.abs(y);
drawView.moveSprite(DrawView.DIRECTION.DOWN, yChange);
}
}
}
//Clean trail
drawView.cleanUpPoints();
}
@Override
protected void onStop()
{
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
}
还有另外一个类,子类ImageView、DrawView:
package com.tilleytech.wubl.view;
/**
* Created by Leigh on 09/03/2015.
* Updated 19/06/2017
*/
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.support.v7.widget.AppCompatImageView;
import com.tilleytech.wubl.R;
import com.tilleytech.wubl.WUBLApplication;
import com.tilleytech.wubl.object.Point;
import com.tilleytech.wubl.util.Util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class DrawView extends AppCompatImageView implements OnTouchListener {
public static enum DIRECTION {LEFT, RIGHT, UP, DOWN};
private final static String TAG = DrawView.class.getSimpleName();
private Bitmap player = null;
private Bitmap saucer = null;
private Bitmap saucer2 = null;
private Bitmap saucer3 = null;
//boundary of our view
private static final int XMIN = 0;
private static final int XBOUNDARY=1080;
private static final int YMIN=0;
private static final int YBOUNDARY=1920;
List<Point> points = new ArrayList<Point>();
Paint paint = new Paint();
private int saucerLeft=1100;
private int saucer2Left=1400;
private int saucer3Left=1250;
public DrawView(Context context) {
super(context);
init(context);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
/* paint.setColor(Color.WHITE);
paint.setAntiAlias(true);*/
player = Util.decodeSampledBitmapFromResource(getResources(), R.drawable.player, 80, 93);
saucer = Util.decodeSampledBitmapFromResource(getResources(), R.drawable.saucer, 100, 73);
saucer2 = Util.decodeSampledBitmapFromResource(getResources(), R.drawable.saucer2, 100, 73);
saucer3 = Util.decodeSampledBitmapFromResource(getResources(), R.drawable.saucer3, 100, 73);
setWillNotDraw(false);
}
@Override
public void onDraw(Canvas canvas) {
//test out some UFOs in here for now
if(saucer2Left<-150) {
saucerLeft=1100;
saucer2Left= 1400;
saucer3Left=1250;
}
canvas.drawBitmap(saucer, saucerLeft--, 10, null);
canvas.drawBitmap(saucer2, saucer2Left--, 10, null);
canvas.drawBitmap(saucer3, saucer3Left--, 125, null);
//We have 20 points which will create a trail effect
WUBLApplication.logMessage("Whiz through our points drawing to canvas.", TAG, WUBLApplication.LogLevel.Debug);
synchronized (points) {
for (Point point : points) { //set in onTouch
canvas.drawBitmap(player, point.getX(), point.getY(), null);
}
}
}
public boolean onTouch(View view, MotionEvent event) {
int eventAction = event.getAction();
switch (eventAction) {
case MotionEvent.ACTION_DOWN:
// finger touches the screen
break;
case MotionEvent.ACTION_MOVE:
// finger moves on the screen
Point point = new Point(event.getX(), event.getY());
addPoint(point);
synchronized (points) {
if (points.size() > 20) {
points.remove(0);
}
}
break;
case MotionEvent.ACTION_UP:
// finger leaves the screen
cleanUpPoints();
break;
}
//Force a repaint
invalidate();
return true;
}
public void cleanUpPoints() {
synchronized (points) {
int counter = 1;
int max = points.size()-1;
Iterator<Point> it = points.iterator();
while (it.hasNext() & counter <= max) {
it.next();
it.remove();
counter++;
}
}
}
public void addPoint(Point point) {
//WUBLApplication.logMessage("addPoint: " + point.toString(), TAG, WUBLApplication.LogLevel.Debug);
synchronized (points){
points.add(point);
}
}
public Point getPoint(int index) {
Point point=null;
if(index>-1) {
synchronized (points) {
if (!points.isEmpty()) {
point = points.get(index);
}
}
}
return point;
}
public Point getLastPoint() {
Point point=null;
//WUBLApplication.logMessage("getLastPoint before synch block", TAG, WUBLApplication.LogLevel.Debug);
synchronized (points) {
//WUBLApplication.logMessage("Points isEmpty: " + points.isEmpty(), TAG, WUBLApplication.LogLevel.Debug);
if (!points.isEmpty()) {
point = points.get(points.size() - 1);
}
}
return point;
}
public void clearPoints() {
synchronized (points){
points.clear();
}
}
public int getPointsSize(){
int result=0;
synchronized (points){
result=points.size();
}
return result;
}
public void moveSprite(DIRECTION direction, float change) {
//Called from accelerometer listener in activity using this view
WUBLApplication.logMessage("moveSprite with direction: " + direction.toString(), TAG, WUBLApplication.LogLevel.Debug);
//Get the last point and shift from here
Point lastKnownPoint = getLastPoint();
if (lastKnownPoint != null) {
float lastX = lastKnownPoint.getX();
float lastY = lastKnownPoint.getY();
switch (direction) {
case LEFT: {
WUBLApplication.logMessage("moveSprite inside LEFT", TAG, WUBLApplication.LogLevel.Debug);
//if (lastX - change > XMIN && lastX - change < XBOUNDARY) {
WUBLApplication.logMessage("LEFT: subtract from x", TAG, WUBLApplication.LogLevel.Debug);
lastX -= change;
addPoint(new Point(lastX, lastY));
//}
}
break;
case RIGHT: {
WUBLApplication.logMessage("moveSprite inside RIGHT", TAG, WUBLApplication.LogLevel.Debug);
//if (lastX + change > XMIN && lastX + change < XBOUNDARY) {
WUBLApplication.logMessage("RIGHT: add to x", TAG, WUBLApplication.LogLevel.Debug);
lastX += change;
addPoint(new Point(lastX, lastY));
//}
}
break;
case UP: {
WUBLApplication.logMessage("moveSprite inside UP", TAG, WUBLApplication.LogLevel.Debug);
//if (lastY - change > YMIN && lastY - change < YBOUNDARY) {
WUBLApplication.logMessage("UP: add to y", TAG, WUBLApplication.LogLevel.Debug);
lastY += change;
addPoint(new Point(lastX, lastY));
//}
}
break;
case DOWN: {
WUBLApplication.logMessage("moveSprite inside DOWN", TAG, WUBLApplication.LogLevel.Debug);
//if (lastY + change > YMIN && lastY + change < YBOUNDARY) {
WUBLApplication.logMessage("DOWN: subtract from y", TAG, WUBLApplication.LogLevel.Debug);
lastY -= change;
addPoint(new Point(lastX, lastY));
//}
}
break;
}//switch
invalidate();
}
}
}
我希望这对试用加速度计的人有所帮助。
我会在我认为合适的时候发回更新。
感谢您的宝贵时间。
李
关于Android 测试 onTouch、onDraw 和加速度计,但有些图形不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29038218/
安卓游戏用什么比较好: 一个带有渲染线程的SurfaceView 或 一个 SurfaceView,带有调用 SurfaceView 函数的线程 doDraw() 谢谢。 最佳答案 SurfaceVi
我花了一整天的时间调试各种将自定义 ViewGroup 添加到另一个自定义 ViewGroup 的方法,但几乎要疯了,因为它们都不起作用,而且没有官方文档或显示如何完成的示例... 基本上,我有 2
我正在尝试创建一个简单的应用程序,绘制一个简单的图形,然后单击按钮后对图形进行一些仿射变换。你能帮我完成 onClick 方法旋转吗?万分感谢。问题是,如果可能的话,我不知道如何从 CanvasVie
我有一个简单的图形应用程序,可以在屏幕上绘制一些内容。之前,我在 onDraw() 中调用 invalidate() 时没有进行检查,没有任何问题。在我的应用程序中, onDraw() 每秒被调用多次
这个问题已经有答案了: Is Java "pass-by-reference" or "pass-by-value"? (91 个回答) 已关闭 9 年前。 我提到了this question但它没有
我有以下代码: @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setCo
我的自定义 View 的 onDraw() 没有被触发。为什么?我正在使用 2.3.3。 View 创建时不应该自动绘制吗? onMeasure() 方法被触发,我得到正确的屏幕宽度和高度。 pack
我正在处理我的 ondraw 方法无法正常工作的应用程序......在我的应用程序中,我正在使用 framelayout ...所以我用了三级...1)活跃度2)图像选择3)绘图 我的图像选择工作正常
我有一个 SurfaceView,我喜欢在其中绘制一堆文本并绘制 72px x 72px 的 png 图像。图像始终绘制在 SurfaceView 上,但每 2 秒在不同的位置绘制一次。 (从该图
在我的自定义绘制 View 中,我使用了 Canvas.drawPaint(Paint) 方法。但 Android Studio 中的预览显示此消息: The graphics preview in
我创建了一个调用 DrawView extends View 的 Activity ,我在 Canvas 上绘制类似于二叉树的东西。 Canvas 尺寸大于屏幕尺寸,onDraw 函数绘制整个 Can
我试图在按下 drawCircle() 时调用 onDraw()。我知道它正在被调用(通过 xml 中的 onClick),因为我收到消息:“drawCircle pressed”。然而,问题是 in
我用一个新类覆盖了 RelativeLayout 类: public class myRelative extends RelativeLayout{ //... //this function is
我在使用 Android 应用程序时遇到问题。 我有一个线程不断迭代列表或形状,更新它们的位置,有时还会从列表中删除一个项目。在线程的 while 循环结束时,它调用 postInvalidate()
我有一个应用程序可以根据人的生日绘制行星和星座。我在自定义 View 中使用 onDraw() 方法,该方法被添加到 XML 中的 FrameLayout。问题是,当我离开页面并调整日期时,该 Act
我正在尝试在 CScrollView 派生类中显示图像: C++ CScrollView, how to scroll an image? 所以我想覆盖OnDraw,将代码从OnPaint 移动到On
我想向 itemView 添加动画,但是它们仅在项目当前正在移动时运行。例如,项目开始淡出,直到 alpha 为 0,但如果项目停止移动,动画就会暂停,项目只会淡出一半。之后,该项目需要再次开始移动才
对于 Android canvas 游戏,我使用以下(最小化)方法请求重绘 SurfaceView: private void refreshView() { c = surf
我正在使用 Android 2.2 构建游戏。主游戏 Activity 使用自定义 SurfaceView: class GameView extends SurfaceView 据我了解,onDra
我的自定义按钮有问题。 onDraw() 被一次又一次地调用,我不明白为什么。 public class CircleButton extends Button { static final
我是一名优秀的程序员,十分优秀!