読者です 読者をやめる 読者になる 読者になる

うさがにっき

読書感想文とプログラムのこと書いてきます

viewPagerのインディケータの実装

概要

viewPagerの現在のページ位置を表示するインディケータを実装する
RadioGroupを拡張してページ数文だけRadioButtonを配置すればわりと簡単に実装できる

まとめ

レイアウト
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- ページの下に来るようにインディケータを配置 -->
    <com.example.indicator.ViewPagerIndicator
        android:id="@+id/indicator"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/pager"
        android:layout_marginBottom="@dimen/indicator_height" />

</RelativeLayout>
ロジック

activity

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    CustomPagerAdapter adapter = new CustomPagerAdapter(this);

    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(adapter);

    mViewPagerIndicator = (ViewPagerIndicator) findViewById(R.id.indicator);
    mViewPagerIndicator.setCount(adapter.getCount());

    mViewPager
            .setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                @Override
                public void onPageSelected(int position) {
                    super.onPageSelected(position);
                    mViewPagerIndicator.setCurrentPosition(position);
                }
            });
}

viewPager adapter

static class CustomPagerAdapter extends PagerAdapter {

	private static int[] mViewColor = {Color.RED, Color.BLACK, Color.BLUE, Color.GREEN, Color.DKGRAY};

    Context mContext;

    public CustomPagerAdapter(Context context) {
        mContext = context;
    }

    @Override
    public int getCount() {
        return mViewColor.length;
    }

    @Override
    public boolean isViewFromObject(View v, Object o) {
        return ((View) o).equals(v);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
    	TextView tv = new TextView(mContext);
        tv.setText("Postion :" + position);
        tv.setTextColor(Color.WHITE);
        tv.setTextSize(30);
        tv.setBackgroundColor(mViewColor[position]);
        container.addView(tv);
        return tv;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        View v = (View) object;
        container.removeView(v);
    }
}

PagerAdapterを実装するには以下の四つのメソッドを実装する必要がある
getCount()…viewPagerの枚数
instantiateItem()…pageのviewの内容
destroyItem()…instantiateItemで作成したアイテムの廃棄時の挙動
isViewFromObject()…第二引数のoの中身とvが同じか比較する、、、何のためにあるかいまいちわからない、、、

インディケータ

public class ViewPagerIndicator extends RadioGroup {

    public ViewPagerIndicator(Context context) {
        this(context, null);
    }

    public ViewPagerIndicator(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOrientation(LinearLayout.HORIZONTAL);
        setGravity(Gravity.CENTER);
    }

    private int mCount;

    /**
     * ページ数をセットする
     * 
     * @param count
     */
    public void setCount(int count) {
        mCount = count;
        removeAllViews();
        // 指定されたページ数分だけRadioButtonを追加
        for (int i = 0; i < count; i++) {
            // RadioButtonにインディケータの画像をセット
            RadioButton rb = new RadioButton(getContext());
            rb.setFocusable(false);
            rb.setClickable(false);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
                // 4.2以前は背景画像でpaddingを設定していたため、RadioButtonのサイズを画像サイズセットしなければならない
                Drawable d = getResources().getDrawable(R.drawable.indicator);
                rb.setButtonDrawable(d);
                
                LinearLayout.LayoutParams params = generateDefaultLayoutParams();
                params.width = d.getIntrinsicWidth();
                params.height = d.getIntrinsicHeight();
                
                rb.setLayoutParams(params);
            } else {
                rb.setButtonDrawable(R.drawable.indicator);
            }
            addView(rb);
        }
        setCurrentPosition(-1);
    }

    /**
     * 現在の位置をセットする
     * 
     * @param position
     */
    public void setCurrentPosition(int position) {
        if (position >= mCount) {
            position = mCount - 1;
        }
        if (position < 0) {
            position = mCount > 0 ? 0 : -1;
        }

        if (position >= 0 && position < mCount) {
            // 現在の位置のRadioButtonをチェック状態にする
            RadioButton rb = (RadioButton) getChildAt(position);
            rb.setChecked(true);
        }
    }
}

4.2以前と以後で画像に対してpaddingが発生してしまう
以前
f:id:tiro105:20140513152150p:plain
以後
f:id:tiro105:20140513152203p:plain

なので画像サイズをボタンサイズとして設定している

インディケータのリソース

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 選択時 -->
    <item android:drawable="@drawable/indicator_selected" android:state_checked="true"/>

    <!-- 通常時 -->
    <item android:drawable="@drawable/indicator_normal"/>

</selector>