天天看點

Android 自定義幀動畫Android 自定義幀動畫

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 類

    狀态一覽:
    /**
     * 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
    }           
    一個Button用于啟動子線程,可以先判斷子線程的狀态,再決定是否啟動

繼續閱讀