2月 26

前回に引き続き、技術ネタです。これまでに取得した Andorid に関するノウハウを忘れないうちに記録しちゃいます。

さて、表題に挙げた overridePendingTransition。使った事(聞いた事)ありますか?
overridePendingTransition は Activity 間の遷移にアニメーション効果を加えることができる Activity クラスのメソッドです。API Level 5 で追加されたメソッドなので Android 2.0 以降で使用可能です。

使い方は簡単で startActivity() または finish() の後でこのメソッドをコールするだけです。(後ってとこが重要なので間違えないように!)指定するのは今の画面を閉じるアニメーションと次の画面を開くアニメーションでいずれもリソースで定義したアニメーションのリソースIDを指定します。プログラムで作成したアニメーションを使用できないのが残念ですね。

なお、画面遷移でのアニメーション効果を有効にするためには、システム設定の「画面設定」>「アニメーション表示」で「すべてのアニメーション」にチェックが入っている必要があります。端末の初期状態では「一部のアニメーション」にチェックを入っていることが多いようですがこの状態ではアニメーション効果は有効ではありません。試す前には必ずこの設定が「すべてのアニメーション」になっていることを確認してください。

device-0s.png

使用例

この機能を使えば iPhone の典型的なアプリケーション(進む場合は右方向へのスライド、戻る場合は左方向へのスライド)のような画面遷移を持つ Android アプリケーションを作成することができます。

サンプルコード

ここでは4つの画面(Activity)を持つアプリケーションを例に挙げます。画面の遷移は左右のフリックで行います。画面の遷移は左右のスライドアニメーションで行っています。プログラム中にフラグを設けており、その設定を変更することでフリック動作および画面遷移の方向を左右でなく上下に変更できるようになっています。

device-1s.png device-2s.png

device-3s.png device-4s.png

res/anim/push_left_in.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="100%p"
    android:toXDelta="0"
    android:duration="300"/>

res/anim/push_left_out.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="-100%p"
    android:duration="300"/>

res/anim/push_right_in.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="-100%p"
    android:toXDelta="0"
    android:duration="300"/>

res/anim/push_right_out.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="100%p"
    android:duration="300"/>

res/anim/push_down_in.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="-100%p"
    android:toYDelta="0"
    android:duration="300"/>

res/anim/push_down_out.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="0"
    android:toYDelta="100%p"
    android:duration="300"/>

res/anim/push_up_in.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="100%p"
    android:toYDelta="0"
    android:duration="300"/>

res/anim/push_up_out.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="0"
    android:toYDelta="-100%p"
    android:duration="300"/>

src/sak/samples/MyActivityBase.java

全ての Activity の親となる抽象クラスです。overridePendingTransition はこの中で使用しています。画面遷移では GestureDetector を使用していますが、それもこのクラスの中で定義しています。という訳でこのアプリの重要な部分はこのクラスにほぼ全て集約されています。その他の子クラスでは画面表示と最小限の固有設定をオーバライドすれば良いように設計されています。

abstract public class MyActivityBase extends Activity {

    private static final int THRESHOLD_DISTANCE = 120;
    private static final int THRESHOLD_OPPOSITION_AXIS = 250;
    private static final int THRESHOLD_VELOCITY = 200;
   
    private GestureDetector mGestureDetector;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mGestureDetector = new GestureDetector(new MyGestureListener());
    }
   
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mGestureDetector.onTouchEvent(event))
            return true;
        else
            return false;
    }
   
    /*
     * true なら上下方向、false なら左右方向の画面遷移をする。
     */

    boolean slideUpdown = false;
   
    private class MyGestureListener extends SimpleOnGestureListener {
        @Override
        public boolean onFling(
                MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
           
            float dX = e2.getX() - e1.getX();
            float dY = e2.getY() - e1.getY();
           
            float velocity = Math.abs(slideUpdown ? velocityY : velocityX);
            float diff = slideUpdown ? dY : dX;
            float opposition_axis = Math.abs(slideUpdown ? dX : dY);
           
            if (opposition_axis > THRESHOLD_OPPOSITION_AXIS)
                return false;
           
            if (-diff > THRESHOLD_DISTANCE && velocity > THRESHOLD_VELOCITY)
                next();
            else if (diff > THRESHOLD_DISTANCE && velocity > THRESHOLD_VELOCITY)
                back();
               
            return false;
        }
    }
   
    abstract protected void next();
   
    protected void back() {
        finish();
    }
   
    protected void showNext(Intent intent, int flags) {
        flags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        flags |= Intent.FLAG_ACTIVITY_CLEAR_TOP;
        intent.setFlags(flags);
        startActivity(intent);
        if (slideUpdown)
            overridePendingTransition(R.anim.push_up_in, R.anim.push_up_out);
        else
            overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
    }
   
    protected void showPrev(Intent intent, int flags) {
        finish();
    }
   
    @Override
    public void finish() {
        super.finish();
        if (slideUpdown)
            overridePendingTransition(R.anim.push_down_in, R.anim.push_down_out);
        else
            overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out);
    }
}

src/sak/samples/ActivityTransitionEffectDemo.java

public class ActivityTransitionEffectDemo extends MyActivityBase {
   
    private static final String TEXT = "0";
    private static final int TEXT_SIZE = 64;
    private static final int TEXT_COLOR = Color.argb(0xff, 0xff, 0xff, 0xff);   // 白
    private static final int BACK_COLOR = Color.argb(0xff, 0x88, 0x88, 0x88);   // 灰

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView tv = new TextView(this);
        tv.setLayoutParams(new LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        tv.setGravity(Gravity.CENTER);
        tv.setText(TEXT);
        tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, TEXT_SIZE);
        tv.setTextColor(TEXT_COLOR);
        tv.setBackgroundColor(BACK_COLOR);
        setContentView(tv);
    }
   
    @Override
    protected void next() {
        Intent intent = new Intent(this, Activity1.class);
        super.showNext(intent, 0);
    }

    @Override
    protected void back() {
        Toast.makeText(this, "最初のページです。", Toast.LENGTH_SHORT).show();
    }
}

src/sak/samples/Activity1.java

public class Activity1 extends MyActivityBase {

    private static final String TEXT = "1";
    private static final int TEXT_SIZE = 64;
    private static final int TEXT_COLOR = Color.argb(0xff, 0xff, 0xff, 0xff);   // 白
    private static final int BACK_COLOR = Color.argb(0xff, 0xff, 0x00, 0x00);   // 赤
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        TextView tv = new TextView(this);
        tv.setLayoutParams(new LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        tv.setGravity(Gravity.CENTER);
        tv.setText(TEXT);
        tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, TEXT_SIZE);
        tv.setTextColor(TEXT_COLOR);
        tv.setBackgroundColor(BACK_COLOR);
        setContentView(tv);
    }

    @Override
    protected void next() {
        Intent intent = new Intent(this, Activity2.class);
        super.showNext(intent, 0);
    }
}

src/sak/samples/Activity2.java

public class Activity2 extends MyActivityBase {

    private static final String TEXT = "2";
    private static final int TEXT_SIZE = 64;
    private static final int TEXT_COLOR = Color.argb(0xff, 0xff, 0xff, 0xff);   // 白
    private static final int BACK_COLOR = Color.argb(0xff, 0x00, 0xff, 0x00);   // 緑
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        TextView tv = new TextView(this);
        tv.setLayoutParams(new LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        tv.setGravity(Gravity.CENTER);
        tv.setText(TEXT);
        tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, TEXT_SIZE);
        tv.setTextColor(TEXT_COLOR);
        tv.setBackgroundColor(BACK_COLOR);
        setContentView(tv);
    }
   
    @Override
    protected void next() {
        Intent intent = new Intent(this, Activity3.class);
        super.showNext(intent, 0);
    }
}

src/sak/samples/Activity3.java

public class Activity3 extends MyActivityBase {

    private static final String TEXT = "3";
    private static final int TEXT_SIZE = 64;
    private static final int TEXT_COLOR = Color.argb(0xff, 0xff, 0xff, 0xff);   // 白
    private static final int BACK_COLOR = Color.argb(0xff, 0x00, 0x00, 0xff);   // 青
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        TextView tv = new TextView(this);
        tv.setLayoutParams(new LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        tv.setGravity(Gravity.CENTER);
        tv.setText(TEXT);
        tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, TEXT_SIZE);
        tv.setTextColor(TEXT_COLOR);
        tv.setBackgroundColor(BACK_COLOR);
        setContentView(tv);
    }
   
    @Override
    protected void next() {
        Toast.makeText(this, "最後のページです。", Toast.LENGTH_SHORT).show();
    }
}


Posted by sak+

Comments are closed.

preload preload preload