Goodroid

GoodroidはAndroidアプリ開発のための情報をコラムやブログで紹介するサイトです。


ページめくりを実装する
ここではページめくりを実装する方法を確認していきます。

ページをめくるような横スクロールを実装するためには、「 ViewFlipper 」クラスとスクロールを表現するアニメーションを組み合わせます。

アニメーションといきなり言われてピンとくる人はいないと思います。
/res/anim フォルダをつくって、左から右、右から左の動きを、ページのfromXDelta (どこから) ページのtoXDelta(どこまで) を duration(どのくらい時間をかけて)といった感じに設定するXMLファイルを作成します。

サンプルでは、left_in.xml, left_out.xml, right_in.xml, right_out.xmlを作成しました。



left_in.xmlは左から入ってくるときの、left_out.xmlは左へ出ていくときのアニメーションを設定しています。同様に右バージョンも作成します。※具体的なコードは後述しています。

もうひとつ大事なのがページをめくる行為(以降、フリック)を検知することです。フリックは画面のタッチイベントを取得して「 MotionEvent.ACTION_DOWN 」と「MotionEvent.ACTION_UP」のそれぞれでX軸を取得し、その座標を比較することにより右方向へのフリックか、左方向へのフリックかを判断します。

それにより、「 setInAnimation 」メソッドで表示されるビューに適用されるアニメーションを指定し、「 showNext() 」もしくは「 showPrevious() 」で目的の画面を表示します。

ScrollActivity.java
package goodroid.sample.scroll;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ViewFlipper;

public class ScrollActivity extends Activity implements OnTouchListener {

  ViewFlipper viewflipper;
  float posX;
  Animation left_in;
  Animation right_in;
  Animation left_out;
  Animation right_out;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // ViewFlipperを取得する
        viewflipper = (ViewFlipper)this.findViewById(R.id.viewflipper);

        // リスナーを設定する
        viewflipper.setOnTouchListener(this);

        // アニメーションを設定する
        left_in = AnimationUtils.loadAnimation(this, R.anim.left_in);
        right_in = AnimationUtils.loadAnimation(this, R.anim.right_in);
        left_out = AnimationUtils.loadAnimation(this, R.anim.left_out);
        right_out = AnimationUtils.loadAnimation(this, R.anim.right_out);

    }

    // タッチイベント発生時
    @Override
  public boolean onTouch(View v, MotionEvent event) {

    switch(event.getAction()){

    case MotionEvent.ACTION_DOWN:
  	  // タッチ場所を取得
	  posX = event.getX();
	  break;
	case MotionEvent.ACTION_UP:
	  if(posX > event.getX()){

	    // アニメーションを設定
	    viewflipper.setInAnimation(right_in);
	    viewflipper.setOutAnimation(left_out);

	    // 次ページへ移動
	    viewflipper.showNext();
	  }else if(posX < event.getX()){

	    // アニメーションを設定
	    viewflipper.setInAnimation(left_in);
	    viewflipper.setOutAnimation(right_out);

	    // 前ページへ移動
	    viewflipper.showPrevious();
	  }
	default:
	  break;
      }
	  return true;
    }
}

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ViewFlipper
        android:id="@+id/viewflipper"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#000000"
            >
            <TextView
                android:layout_centerInParent="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="48dip"
                android:text="画面1"/>

        </RelativeLayout>

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#FFFFFF"
            >
            <TextView
                android:layout_centerInParent="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="48dip"
                android:text="画面2"/>

        </RelativeLayout>

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#333333"
            >
            <TextView
                android:layout_centerInParent="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="48dip"
                android:text="画面3"/>

        </RelativeLayout>

    </ViewFlipper>

</LinearLayout>

res/anim/left_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator">
    <translate
        android:fromXDelta="-100%"
        android:toXDelta="0%"
        android:duration="500" />
</set>

res/anim/right_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator">
    <translate
        android:fromXDelta="100%"
        android:toXDelta="0%"
        android:duration="500" />
</set>

res/anim/left_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator">
    <translate
        android:fromXDelta="0%"
        android:toXDelta="-100%"
        android:duration="500" />
</set>

res/anim/right_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator">
    <translate
        android:fromXDelta="0%"
        android:toXDelta="100%"
        android:duration="500" />
</set>


実行結果

11365 views | コメント:5 | 2012-06-25
コメント
Commented by bluetree at 2012-08-04 20:44:54
ページめくりの実装方法を調べていて、ここのサイトが一番ポイントをおさえて説明してあり、わかりやすくて非常に参考になりました。ありがとうございます。
ただ、ソースを動かしてみて、左から右へのフリックで動作が怪しいので原因を調べてて気づいたことがありました。
ScrollActivity.javaの36行目の記述が間違っているようです。
R.anim.left_out でなく R.anim.right_out だと思います。
Commented by KI at 2012-08-15 23:43:03
>>bluetree

管理人のKIです。
ご指摘ありがとうございます!
ScrollActivity.javaの36行目は「R.anim.left_out」 でなく「 R.anim.right_out」でした。みなさんには大変ご迷惑お掛けしましたがソースの修正を行いましたので、今後とも宜しくお願いいたします。
Commented by K at 2012-10-18 14:50:25
細かいですが
res/anim/rigth_in.xml
になってますよ

私もこちらのサンプルを参考にさせていただきました
ありがとうございました
Commented by KI at 2012-10-27 15:39:28
>>Kさん
ご指摘ありがとうございます!
修正いたしました。
今後とも宜しくお願いいたします。
Commented by aaa at 2012-11-11 14:25:49
参考になりました!
コメントの投稿
名前 (必須)

メールアドレス (非公開)

本文(必須)

パスワード (必須)
(半角数字4桁)