代码如下
package com.example.fall; import com.example.fall.BlocksFall.OnFallFinishListener; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.KeyEvent; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub if (keyCode==KeyEvent.KEYCODE_BACK) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Are you sure you want to exit?") .setCancelable(false) .setPositiveButton("YES", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); exitClick(); } }); AlertDialog alert = builder.create(); alert.show(); } return true; } protected void exitClick() { BlocksFall blocksFall=new BlocksFall(); blocksFall.setFallFinishListener(new OnFallFinishListener() { @Override public void OnFallFinish(Activity act) { finish(); } }); blocksFall.startFall(MainActivity.this); } }
<pre style="font-family: 宋体; font-size: 9pt; background-color: rgb(255, 255, 255);"><pre name="code" class="java">package com.example.fall; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Camera; import android.graphics.Canvas; import android.graphics.Matrix; import android.provider.Settings; import android.view.View; import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; import java.util.Random; /** * 注意, startFall(final Activity act)中的activity要在AndroidManifest文件中声明为透明, * 例如 android:theme="@android:style/Theme.Translucent.NoTitleBar" * @author Young * */ public class BlocksFall { private Block[][] blocks; /** * blocks列数 */ private int COL = 5; /** * blocks行数 */ private int ROW = 20; /** * 动画持续时间 毫秒 */ private int DURING=1200; private Activity act=null; private OnFallFinishListener fallFinishListener; private FallView fallView; public void setFallFinishListener(OnFallFinishListener fallFinishListener) { this.fallFinishListener=fallFinishListener; } public void startFall(final Activity act) { this.act=act; FrameLayout rootViewGroup=(FrameLayout) act.getWindow().getDecorView(); rootViewGroup.getChildAt(0).setDrawingCacheEnabled(true); //获取屏幕中显示的内容 Bitmap screenBitmap=rootViewGroup.getChildAt(0).getDrawingCache(); //创建一张RGB565图片,并把屏幕内容绘制在上面,然后调用System.gc()可以减少20M内存开销 final Bitmap bitmap = Bitmap.createBitmap(screenBitmap.getWidth(),screenBitmap.getHeight(), Bitmap.Config.RGB_565); Canvas canvas=new Canvas(bitmap); canvas.drawBitmap(screenBitmap,0,0,null); screenBitmap=null; rootViewGroup.getChildAt(0).setDrawingCacheEnabled(false); System.gc(); rootViewGroup.getChildAt(0).setVisibility(View.INVISIBLE); fallView=new FallView(act); rootViewGroup.addView(fallView); blocks = new Block[ROW][COL]; int blockW = bitmap.getWidth() / COL; final int blockH = bitmap.getHeight() / ROW; for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { Block block = new Block(); // 2 、4 控制blocks间缝隙 block.bitmap = Bitmap.createBitmap(bitmap, j * blockW+2, i * blockH+2, blockW-4, blockH-4); block.startY = i * blockH; block.currentY =block.startY; block.x = j * blockW; blocks[i][j] = block; } } final Random random=new Random(System.currentTimeMillis()); //保证前一半时间所有的block都已经开始坠落 ValueAnimator animator = ValueAnimator.ofInt( ROW-1,-ROW).setDuration(DURING); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener(new AnimatorUpdateListener() { int y = 0; @SuppressLint("NewApi") @Override public void onAnimationUpdate(ValueAnimator animation) { int value=(Integer) animation.getAnimatedValue(); if (value!=y&&value>-1) { y=value; for (int j=y;j<ROW;j++){//如果没有该层for,可能导致某一层blocks一直停留在屏幕上 if (blocks[j][0].isFalling==false){ for (int i = 0; i < COL; i++) { blocks[j][i].isFalling = true; blocks[j][i].startTime = System.currentTimeMillis(); Matrix matrix=new Matrix(); Camera camera=new Camera(); camera.rotateZ(random.nextFloat()*360); camera.getMatrix(matrix); Bitmap tmp=blocks[j][i].bitmap; blocks[j][i].bitmap=Bitmap.createBitmap(tmp,0,0,tmp.getWidth(),tmp.getHeight(),matrix,false); tmp.recycle(); // System.gc(); } }else break; } } for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { //更新已经开始坠落的blocks的y轴距离 if (blocks[i][j].isFalling) { float t =2.0f* (System.currentTimeMillis() - blocks[i][j].startTime) / animation.getDuration(); blocks[i][j].currentY = blocks[i][j].startY +bitmap.getHeight() * t *t; } } } fallView.invalidate(); } }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); blocks=null; fallView=null; System.gc(); if (fallFinishListener!=null) { fallFinishListener.OnFallFinish(act); } } }); animator.start(); } /** * 用于绘制blocks,覆盖在用户控件的上方 * @author Young * */ private class FallView extends View { public FallView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (blocks == null) { return; } for (int i = 0; i < blocks.length; i++) { for (int j = 0; j < blocks[0].length; j++) { canvas.drawBitmap(blocks[i][j].bitmap, blocks[i][j].x, blocks[i][j].currentY, null); } } } } public interface OnFallFinishListener { public void OnFallFinish(Activity act); } private class Block { Bitmap bitmap; float startY; float x; float currentY; long startTime; boolean isFalling; } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.fall" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.fall.MainActivity" android:label="@string/app_name" android:theme="@android:style/Theme.Translucent.NoTitleBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>