如何使用SurfaceView實現(xiàn)魚兒游動動畫
本文實例為大家分享了使用SurfaceView實現(xiàn)動畫的具體代碼,供大家參考,具體內(nèi)容如下
與自定義view繪圖進行對比:
1.view繪圖沒有雙緩沖機制,而surfaceview有
2.view繪圖更新時,要全部更新整張圖片,而surfaceview可以更新部分區(qū)域
3.新線程無法直接更新view繪圖,需要handler配合。
魚兒游動的動畫:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.liuyan.testbutfly.FishView android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
java代碼:
public class FishView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder holder;
private UpdateViewThread updatethread;
private boolean hasSurface;
private Bitmap back;
private Bitmap[] fishs;
private int fishIndex = 0;//繪制第幾張魚
//魚的初始位置
private float fishx = 778;
private float fishy = 500;
private float fishSpeed = 6; //魚的游動速度
//魚的游動角度
private int fishAngle = new Random().nextInt(60);
Matrix matrix = new Matrix();
public FishView(Context context) {
super(context);
Log.i("mydate" , "開始");
//獲取surfaceview的surfaceholder,并將該類的實例作為其callback
holder = getHolder();
holder.addCallback(this);//以自身作為callback,回調(diào)方法
hasSurface = false;
back = BitmapFactory.decodeResource(context.getResources() , R.drawable.fishbg);//背景
int[] id = new int[]{R.drawable.fish0 , R.drawable.fish1 , R.drawable.fish2 ,R.drawable.fish3 ,R.drawable.fish4 ,R.drawable.fish5 ,R.drawable.fish6 ,R.drawable.fish7 ,R.drawable.fish8, R.drawable.fish9};
fishs = new Bitmap[10];
//初始化 魚游動的10張圖
for (int i = 0 ; i < 10 ; i++){
try {
fishs[i] = BitmapFactory.decodeResource(context.getResources() , id[i]);
} catch (Exception e){
e.printStackTrace();
}
}
Log.i("mydate" , "結(jié)束");
}
public FishView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.i("mydate" , "開始");
//獲取surfaceview的surfaceholder,并將該類的實例作為其callback
holder = getHolder();
holder.addCallback(this);//以自身作為callback,回調(diào)方法
hasSurface = false;
back = BitmapFactory.decodeResource(context.getResources() , R.drawable.fishbg);//背景
int[] id = new int[]{R.drawable.fish0 , R.drawable.fish1 , R.drawable.fish2 ,R.drawable.fish3 ,R.drawable.fish4 ,R.drawable.fish5 ,R.drawable.fish6 ,R.drawable.fish7 ,R.drawable.fish8, R.drawable.fish9};
fishs = new Bitmap[10];
//初始化 魚游動的10張圖
for (int i = 0 ; i < 10 ; i++){
try {
// int fishId = (Integer) R.drawable.class.getField("fish" + i).get(null);//反射機制獲取圖片
// Log.i("mydate" , " "+ fishId);
fishs[i] = BitmapFactory.decodeResource(context.getResources() , id[i]);
} catch (Exception e){
e.printStackTrace();
}
}
Log.i("mydate" , "結(jié)束");
}
public void resume(){
//創(chuàng)建和啟動 圖片更新線程
if (updatethread == null){
updatethread = new UpdateViewThread();
if (hasSurface == true){
updatethread.start();
}
}
}
public void pause(){
//停止 圖像更新線程
if (updatethread != null){
updatethread.requestExitAndWait();
updatethread = null;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) { //surfaceview被創(chuàng)建時回調(diào)該方法
hasSurface = true;
resume(); //開啟線程更新
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {//surfaceview改變時回調(diào)該方法
if (updatethread != null){
updatethread.onWindowResize(width , height);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {//surfaceview銷毀時回調(diào)該方法
hasSurface = false;
pause(); //停止線程更新
}
class UpdateViewThread extends Thread{
//定義圖像是否更新完成的標(biāo)志
private boolean done;
public UpdateViewThread() {
super();
done = false;
}
@Override
public void run() {
SurfaceHolder surfaceholder = holder;
//循環(huán)繪制,直到線程停止
while (!done){
Canvas canvas = surfaceholder.lockCanvas();//鎖定surfaceview,準(zhǔn)備繪制
//繪制背景
canvas.drawBitmap(back , 0 , 0 , null);
//魚游出屏幕外,重新初始化魚的位置
if (fishx < 0 ){
fishx = 778;
fishy = 500;
fishAngle = new Random().nextInt(60);
}
if (fishy < 0){
fishx = 778;
fishy = 500;
fishAngle = new Random().nextInt(60);
}
//用matrix控制魚的旋轉(zhuǎn)角度和位置
matrix.reset();
matrix.setRotate(fishAngle);//下面的位置計算看圖片的解釋如下:
matrix.postTranslate(fishx -= fishSpeed * Math.cos(Math.toRadians(fishAngle)) , fishy -= fishSpeed * Math.sin(Math.toRadians(fishAngle)));
canvas.drawBitmap(fishs[fishIndex++%fishs.length] , matrix , null);
surfaceholder.unlockCanvasAndPost(canvas);//解鎖canvas,渲染繪制圖像
try {
Thread.sleep(60);
} catch (Exception e){
e.printStackTrace();
}
}
}
public void requestExitAndWait() {
//將繪制線程 標(biāo)記為完成 ,并合并到主線程中
done = true;
try {
join();
} catch (Exception e){
e.printStackTrace();
}
}
public void onWindowResize(int width, int height) {
//處理surfaceview的大小改變事件
}
}
}
位置計算圖片解釋如下:
Math.toRadians(fishAngle)
先理解這句代碼的意思:將0-360的角度制角度轉(zhuǎn)化為pi弧度制角度

魚兒不停的游動,坐標(biāo)改變其實就是:
當(dāng)前的x坐標(biāo) - 速度*cos角度 , 當(dāng)前的y坐標(biāo) - 速度*sin角度
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
android studio 安裝完成ButterKnife插件卻無法使用(解決方案)
這篇文章主要介紹了android studio 安裝完成ButterKnife插件卻無法使用問題,本文通過圖文并茂的形式給大家分享解決方法,對大家有非常好的幫助,需要的朋友可以參考下2020-03-03
一鍵移除ButterKnife并替換為ViewBinding的舊項目拯救
這篇文章主要為大家介紹了一鍵移除ButterKnife并替換為ViewBinding的舊項目拯救詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02
Android開發(fā)使用Drawable繪制圓角與圓形圖案功能示例
這篇文章主要介紹了Android開發(fā)使用Drawable繪制圓角與圓形圖案功能,結(jié)合具體實例形式分析了Drawable繪制圓角矩形的實現(xiàn)步驟與使用方法,需要的朋友可以參考下2017-10-10
Android實現(xiàn)QQ側(cè)滑(刪除、置頂?shù)?功能
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)QQ側(cè)滑刪除、置頂?shù)裙δ?,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
Android使用ViewPager實現(xiàn)啟動引導(dǎo)頁效果
這篇文章主要為大家詳細(xì)介紹了Android使用ViewPager實現(xiàn)啟動引導(dǎo)頁效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-04-04
Android Broadcast原理分析之registerReceiver詳解
這篇文章主要介紹了Android Broadcast原理分析之registerReceiver詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Android Studio實現(xiàn)仿微信APP門戶界面詳解及源碼
這篇文章帶你通過Android studio來實現(xiàn)微信APP的門戶界面,主要說明框架的各部分功能與實現(xiàn)過程,下文包含了整個開發(fā)過程,以及解決問題的思路并再末尾提供了源碼鏈接2021-10-10
Android中DrawerLayout+ViewPager滑動沖突的解決方法
這篇文章主要為大家詳細(xì)介紹了Android中DrawerLayout+ViewPager滑動沖突的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06

