我是Android开发和培训目的的初学者,我创建了一个简单的Android应用程序。这个应用程序是一个" findWaldo"喜欢玩家可以放大,平移和点击图像视图的游戏。它在touchEventListener中使用简单的onTouch函数来管理事件和基本的数学运算。
我在3台物理设备上运行此应用程序:
Galaxy Tab 3 7.0 Kitkat(API19):app流畅而快速
UMI Plus E(高性能设备)棉花糖(API23):应用非常慢(跳过约30帧)
Galaxy A5 2014 Marshmallow(API 23):应用非常慢(大约40帧跳过)
我的问题是:为什么我的应用程序在相当老的Android操作系统(Kitkat)上正常运行,但在最近的操作系统(Marshmallow)上却没有?是否有任何良好的实践或解决方案可以避免这种情况?
这是我的代码:
Game.java
公共类游戏扩展了AppCompatActivity {
/* Define variables */
private RelativeLayout layout; /* activity layout */
private int[] images = {R.drawable.image1, R.drawable.image2}; /* Images list */
private float[][][] waldoC = {
{
{596f, 626f},
{652f, 710f}
},
{
{1100f, 290f},
{1200, 380f}
}
}; /* min and max coordinates of waldo click zone */
private int currentImage; /* index of displayed image */
private Matrix matrix = new Matrix(); /* Matrix to scale image */
private Matrix savedMatrix = new Matrix(); /* saved matrix during translate or scale */
private Float previousDist = 1f; /* Image scale */
private ImageView image; /* Image view used to display image */
private final static int NONE = 0; /* none event state */
private final static int PAN = 1; /* panning event state */
private final static int ZOOM = 2; /* zooming event state */
private int mEventState; /* event state */
private float mStartX; /* start position x for translating */
private float mStartY; /* start position y for translating */
private float mMidX; /* middle of two fingers positions x for scaling */
private float mMidY; /* middle of two fingers positions y for scaling */
private float[] values = new float[9]; /* array to get matrix values */
private final Handler delay = new Handler(); /* delay handler */
private boolean disabled = false; /* click enabled */
private Chronometer chronometer; /* chronometer */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
/* Get layout */
layout = (RelativeLayout) findViewById(R.id.layout);
/* New thread to run chronometer */
new Thread(new Runnable() {
@Override
public void run() {
/* Getting chronometer */
chronometer = (Chronometer) findViewById(R.id.chronometer);
chronometer.start(); /* Chronometer start */
}
}).start();
/* Getting image view */
image = (ImageView) findViewById(R.id.imageView);
/* Setting random image */
image.setImageResource(randomImage());
/* Setting on touch listenener to detect pinch zoom */
image.setOnTouchListener(new View.OnTouchListener() {
/* Touch event */
@Override
public boolean onTouch(View view, MotionEvent event) {
/* Getting image view */
ImageView image = (ImageView) view;
/* Checking if touch event are disabled */
if(disabled == true){
return true;
}
/* Detecting panning image events
in switch condition, & is used to bitwise "event get action"
result with "action mask" to get only action
*/
switch(event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: /* screen is touched */
savedMatrix.set(matrix); /* save matrix */
mEventState = PAN; /* change event state to pan */
mStartX = event.getX(); /* save start x and y positions */
mStartY = event.getY();
matrix.getValues(values); /* get matrix values in values array */
isClick(event, values[2], values[5], values[0]); /* call to click check */
break;
case MotionEvent.ACTION_UP: /* screen is no more touched */
case MotionEvent.ACTION_POINTER_UP:
mEventState = NONE; /* change event state to none */
break;
case MotionEvent.ACTION_MOVE: /* move detected */
if(mEventState == PAN) { /* if event state is pan */
matrix.set(savedMatrix); /* matrix takes values of saved matrix */
matrix.postTranslate(event.getX() - mStartX, event.getY() - mStartY);
/* post concats translations on x and y */
}
else if(mEventState == ZOOM) { /* zoom detected */
float newDist = spacing(event); /* call to spacing */
matrix.set(savedMatrix); /* matrix takes values of saved matrix */
float scale = newDist / previousDist; /* determine scale */
focus(event); /* call to focus */
matrix.postScale(scale, scale, mMidX, mMidY); /* post concats
to scale */
}
break;
case MotionEvent.ACTION_POINTER_DOWN: /* if multi touch is detected */
previousDist = spacing(event); /* call to spacing */
mEventState = ZOOM; /* change event state to zoom */
savedMatrix.set(matrix); /* save matrix */
break;
}
image.setImageMatrix(matrix); /* set matrix to image view */
return true;
}
});
}
/* determine spacing between two fingers positions */
private float spacing(MotionEvent event) {
double x = event.getX(0) - event.getX(1);
double y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
/* determine focus point with 2 fingers positions */
private void focus(MotionEvent event) {
mMidX = (event.getX(0) + event.getX(1))/2;
mMidY = (event.getY(0) + event.getY(1))/2;
}
/* Randomize image */
private int randomImage(){
Random r = new Random(); /* new random */
currentImage = r.nextInt(images.length); /* generate random index
in range of numebr of images */
return images[currentImage]; /* returns image */
}
/* Check if touch event is a click to test waldo position */
private void isClick(MotionEvent event, final float translateX, final float translateY, final float scale){
final Handler delay = new Handler(); /* delay handler */
final MotionEvent e = event; /* create a final var for run function */
/* wait for 1 second */
delay.postDelayed(new Runnable(){
@Override
public void run() {
if((e.getX() > mStartX - 10f && e.getX() < mStartX + 10f)) {
/* if event does not move more than 10px, call to findWaldo */
findWaldo(mStartX, mStartY, translateX, translateY, scale);
}
}
}, 1000);
}
/* Check if click is on Waldo or not */
private void findWaldo(float x, float y, float translateX, float translateY, float scale){
Log.d("POSITION", Float.toString(x - translateX) + " " + Float.toString(y - translateY));
/* if x and y minus their translation correspond to Waldo area coordinates time scale */
if((x - translateX >= waldoC[currentImage][0][0] * scale && x - translateX <= waldoC[currentImage][1][0] * scale)
&& (y - translateY >= waldoC[currentImage][0][1] * scale && y - translateY <= waldoC[currentImage][1][1] * scale)) {
/* if waldo was found */
ProgressBar spinner = new ProgressBar(this); /* create new spinner */
spinner.setX(x - 100f); /* set spinner position around clicked position */
spinner.setY(y);
spinner.getIndeterminateDrawable().setColorFilter(Color.GREEN, PorterDuff.Mode.MULTIPLY);
/* change spinner color to green */
layout.addView(spinner, 200, 200); /* add spinner to view with size of 200 */
disableTouch(true); /* call to disable touch */
chronometer.stop(); /* stop chronometer and end thread */
hallOfFame((String) chronometer.getText()); /* call to hall fo fame */
}
else { /* if waldo was no found */
final ProgressBar spinner = new ProgressBar(this); /* create new spinner */
spinner.setX(x - 100f); /* set spinner position around clicked position */
spinner.setY(y);
spinner.getIndeterminateDrawable().setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY);
/* change spinner color to red */
layout.addView(spinner, 200, 200); /* add spinner to view with size of 200 */
disableTouch(true); /* call to disable touch */
/* 2 seconds cooldown caused by player's error */
delay.postDelayed(new Runnable() {
@Override
public void run() {
layout.removeView(spinner); /* remove spinner */
disableTouch(false); /* call to disable touch */
}
}, 2000);
}
}
/* disable or enable touch events */
private void disableTouch(boolean value){
disabled = value;
}
/* end the game */
private void hallOfFame(String time){
Intent i = new Intent(getApplicationContext(), HallOfFame.class); /* new intent */
i.putExtra("time", time); /* pass time to hall of fame actvity */
startActivity(i); /* starts hall of fame activity */
finish(); /* finish game activity */
}
}
activity_game.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout"
tools:context="com.test.findwaldo.Game">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:text="@string/gameTitle"
android:textSize="20dp"
android:textColor="@color/colorPrimary"
android:gravity="center"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true" />
<Chronometer
android:id="@+id/chronometer"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_below="@+id/title"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:gravity="center"
android:textSize="30dp"
android:textColor="@color/colorPrimaryLight"/>
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@mipmap/ic_launcher"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_below="@+id/chronometer"
android:layout_alignParentStart="true"
android:scaleType="matrix"/>
</RelativeLayout>
非常感谢您的帮助。