Android 自定義幀動畫
Android L ; Android Studio
幀動畫
和gif圖檔類似,順序播放準本好的圖檔檔案;圖檔資源在xml檔案中配置好
将圖檔按照預定的順序一張張切換,即成動畫
Android 幀動畫例子
可以把動畫放進子線程中啟動,也可以在主線程直接啟動動畫
主線程更容易控制動畫的啟停;
子線程需要關注線程的狀态,不好控制動畫
主線程的UI不能放進子線程去設定;即子線程不能直接修改主UI;
螢幕旋轉後,activity重新開機;動畫也就停止了;
在 AndroidManifest.xml 設定 configChanges 即可
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
動畫資源
圖檔資源來自Android L Launcher3 res
圖檔全部放在 res/drawable 裡面
配置檔案 transition_stack.xml
oneshot="false"
動畫會一直循環播放下去
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/transition_stack" android:oneshot="false">
<item android:drawable="@drawable/stack_00000" android:duration="30" />
<item android:drawable="@drawable/stack_00001" android:duration="30" />
......
</animation-list>
Java代碼
- 1.取得ImageView
- 2.為ImageView設定背景資源檔案
- 3.把ImageView的背景賦給動畫AnimationDrawable
public class MainActivity extends AppCompatActivity { private ImageView mTransitionIcon; private ImageView mStackIcon; private AnimationDrawable frameAnimation; private AnimationDrawable stackAnimation; private Thread stackThread; private Button stopButton; public boolean action = false; private TextView tvState; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); tvState = (TextView) findViewById(R.id.tv_state); stopButton = (Button) findViewById(R.id.btn_stop); Button btn1 = (Button) findViewById(R.id.btn1); Button btn2 = (Button) findViewById(R.id.btn2); /************************************************* * AnimationDrawable extends DrawableContainer *************************************************/ // 1.取得ImageView mTransitionIcon = (ImageView) findViewById(R.id.settings_transition_image); // 2.為ImageView設定背景資源檔案 mTransitionIcon.setBackgroundResource(R.drawable.transition_none); // 3.把ImageView的背景賦給動畫AnimationDrawable frameAnimation = (AnimationDrawable) mTransitionIcon.getBackground(); mStackIcon = (ImageView) findViewById(R.id.transition_stack); mStackIcon.setBackgroundResource(R.drawable.transition_stack); stackAnimation = (AnimationDrawable) mStackIcon.getBackground(); stackThread = new Thread() { @Override public void run() { stackAnimation.start();// 子線程中開始動畫 } }; btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { action = !action;// 主線程中控制動畫啟動與停止 if (action) { frameAnimation.start(); // 啟動(重新開機)動畫 } else { frameAnimation.stop(); // 停止動畫 } } }); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (stackThread.getState() == (Thread.State.NEW)) stackThread.start();// 放到子線程中開啟動畫 }// 先查詢子線程狀态再啟動,避免Thread報錯導緻app退出 }); stopButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String s = "";// 用于顯示狀态 s = action ? "action! " + stackThread.getState().toString() : "stop!" + stackThread.getState().toString(); tvState.setText(s); } }); } }
Thread 類
狀态一覽:
一個Button用于啟動子線程,可以先判斷子線程的狀态,再決定是否啟動/** * A representation of a thread's state. A given thread may only be in one * state at a time. */ public enum State { /** * The thread has been created, but has never been started. */ NEW, /** * The thread may be run. */ RUNNABLE, /** * The thread is blocked and waiting for a lock. */ BLOCKED, /** * The thread is waiting. */ WAITING, /** * The thread is waiting for a specified amount of time. */ TIMED_WAITING, /** * The thread has been terminated. */ TERMINATED }