【发布时间】:2018-01-18 03:49:07
【问题描述】:
我们正在尝试学习如何使用动态动画,这段代码来自 Github Code 我们尝试了很多更改,但代码什么也没显示。 我们将发布三个类的,链接中不包含 XML 文件
我的问题是任何人都可以看到代码中缺少什么或可能有问题。 是的,我们已将其包含在 build.gradle 中
implementation "com.android.support:support-dynamic-animation:26.1.0"
这里是主要活动
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
/**
* This app demonstrates how to use a SurfaceView to render an image from a
* separate thread.
* In addition, it shows how you can use clipping for animation,
* and implements a basic game loop. This is not intended as a production
* quality app. Rather, it demonstrates the basics
* of these techniques, so you can dive deeper on your own.
*
* Note that SurfaceView offers trade-offs you must consider:
*
* * Offers a lover level drawing surface with more control without the need
* for learning OpenGL or the NDK.
* * You can draw on it same as a canvas.
* * Draw from a separate thread, not the UI thread.
* * Does not have built-in hardware acceleration, e.g. for
transformations.
* Monitor performance carefully, especially if you are doing animations.
*
* Game play:
*
* The user is presented with a dark surface with a white circle.
* This represents a wall shone at with a flashlight cone. Touching the
* surface hides an android image. The light cone then follows continuous
* motion. If the image of an android is discovered, the screen lights up and
* the word "WIN!" appears. To restart lift finger and touch screen again.
*
* The following limitations are imposed to keep the code focused.
*
* * No startup screen or any other functionality other than game play.
* * No saving of state, game, or user data.
* * No acrobatics to handle edge cases.
*/
public class MainActivity extends AppCompatActivity {
private GameView mGameView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Lock orientation into landscape.
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// Create a GameView and bind it to this activity.
// You don't need a ViewGroup to fill the screen, because the system
// has a FrameLayout to which this will be added.
mGameView = new GameView(this);
// Android 4.1 and higher simple way to request fullscreen.
mGameView.setSystemUiVisibility(SYSTEM_UI_FLAG_FULLSCREEN);
setContentView(mGameView);
}
/**
* Pauses game when activity is paused.
*/
@Override
protected void onPause() {
super.onPause();
mGameView.pause();
}
/**
* Resumes game when activity is resumed.
*/
@Override
protected void onResume() {
super.onResume();
mGameView.resume();
}
还有 FlashlightCone 类
/**
* Cone of flashlight that the user moves around the view.
*/
public class FlashlightCone {
private int mX;
private int mY;
private int mRadius;
public FlashlightCone(int viewWidth, int viewHeight) {
mX = viewWidth / 2;
mY = viewHeight / 2;
// Adjust the radius for the narrowest view dimension.
mRadius = ((viewWidth <= viewHeight) ? mX / 3 : mY / 3);
}
/**
* Update the coordinates of the flashlight cone.
*
* @param newX Changed value for x coordinate.
* @param newY Changed value for y coordinate.
*/
public void update(int newX, int newY) {
mX = newX;
mY = newY;
}
public int getX() {
return mX;
}
public int getY() {
return mY;
}
public int getRadius() {
return mRadius;
}
还有游戏视图
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* This class demonstrates the following interactive game basics:
*
* * Manages a rendering thread that draws to a SurfaceView.
* * Basic game loop that sleeps to conserve resources.
* * Processes user input to update game state.
* * Uses clipping as a means of animation.
*
* Note that these are basic versions of these techniques.
* Non-fatal edge cases are not handled.
* Error handling is minimal. No logging. App assumes and uses a single
thread.
* Additional thread management would otherwise be necessary. See code
comments.
*/
public class GameView extends SurfaceView implements Runnable {
private boolean mRunning;
private Thread mGameThread = null;
private Path mPath;
private Context mContext;
private FlashlightCone mFlashlightCone;
private Paint mPaint;
private Bitmap mBitmap;
private RectF mWinnerRect;
private int mBitmapX;
private int mBitmapY;
private int mViewWidth;
private int mViewHeight;
private SurfaceHolder mSurfaceHolder;
public GameView(Context context) {
this(context, null);
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mSurfaceHolder = getHolder();
mPaint = new Paint();
mPaint.setColor(Color.DKGRAY);
mPath = new Path();
}
/**
* We cannot get the correct dimensions of views in onCreate because
* they have not been inflated yet. This method is called every time the
* size of a view changes, including the first time after it has been
* inflated.
*
* @param w Current width of view.
* @param h Current height of view.
* @param oldw Previous width of view.
* @param oldh Previous height of view.
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mViewWidth = w;
mViewHeight = h;
mFlashlightCone = new FlashlightCone(mViewWidth, mViewHeight);
// Set font size proportional to view size.
mPaint.setTextSize(mViewHeight / 5);
mBitmap = BitmapFactory.decodeResource(
mContext.getResources(), R.drawable.android);
setUpBitmap();
}
/**
* Runs in a separate thread.
* All drawing happens here.
*/
public void run() {
Canvas canvas;
while (mRunning) {
// If we can obtain a valid drawing surface...
if (mSurfaceHolder.getSurface().isValid()) {
// Helper variables for performance.
int x = mFlashlightCone.getX();
int y = mFlashlightCone.getY();
int radius = mFlashlightCone.getRadius();
// Lock the canvas. Note that in a more complex app, with
// more threads, you need to put this into a try/catch block
// to make sure only one thread is drawing to the surface.
// Starting with O, you can request a hardware surface with
// lockHardwareCanvas().
// See https://developer.android.com/reference/android/view/
// SurfaceHolder.html#lockHardwareCanvas()
canvas = mSurfaceHolder.lockCanvas();
// Fill the canvas with white and draw the bitmap.
canvas.save();
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(mBitmap, mBitmapX, mBitmapY, mPaint);
// Add clipping region and fill rest of the canvas with black.
mPath.addCircle(x, y, radius, Path.Direction.CCW);
canvas.clipPath(mPath, Region.Op.DIFFERENCE);
canvas.drawColor(Color.BLACK);
// If the x, y coordinates of the user touch are within a
// bounding rectangle, display the winning message.
if (x > mWinnerRect.left && x < mWinnerRect.right
&& y > mWinnerRect.top && y < mWinnerRect.bottom) {
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(mBitmap, mBitmapX, mBitmapY, mPaint);
canvas.drawText(
"WIN!", mViewWidth / 3, mViewHeight / 2, mPaint);
}
// Clear the path data structure.
mPath.rewind();
// Restore the previously saved (default) clip and matrix state.
canvas.restore();
// Release the lock on the canvas and show the surface's
// contents on the screen.
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
/**
* Updates the game data.
* Sets new coordinates for the flashlight cone.
*
* @param newX New x position of touch event.
* @param newY New y position of touch event.
*/
private void updateFrame(int newX, int newY) {
mFlashlightCone.update(newX, newY);
}
/**
* Calculates a randomized location for the bitmap
* and the winning bounding rectangle.
*/
private void setUpBitmap() {
mBitmapX = (int) Math.floor(
Math.random() * (mViewWidth - mBitmap.getWidth()));
mBitmapY = (int) Math.floor(
Math.random() * (mViewHeight - mBitmap.getHeight()));
mWinnerRect = new RectF(mBitmapX, mBitmapY,
mBitmapX + mBitmap.getWidth(),
mBitmapY + mBitmap.getHeight());
}
/**
* Called by MainActivity.onPause() to stop the thread.
*/
public void pause() {
mRunning = false;
try {
// Stop the thread == rejoin the main thread.
mGameThread.join();
} catch (InterruptedException e) {
}
}
/**
* Called by MainActivity.onResume() to start a thread.
*/
public void resume() {
mRunning = true;
mGameThread = new Thread(this);
mGameThread.start();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
// Invalidate() is inside the case statements because there are
// many other motion events, and we don't want to invalidate
// the view for those.
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setUpBitmap();
// Set coordinates of flashlight cone.
updateFrame((int) x, (int) y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
// Updated coordinates for flashlight cone.
updateFrame((int) x, (int) y);
invalidate();
break;
default:
// Do nothing.
}
return true;
}
【问题讨论】:
-
这是用 26 和分钟 23 构建的
-
显示什么?
-
@RadekJ 屏幕显示为白色,logcat 中没有错误,应用程序似乎正在运行 我们尝试了 John Hortans 书中的类似应用程序 Learn Java by building android games with the same results
标签: android android-canvas surfaceview