【Android】Fragmentを使ってインディケーターを実装する

Androidアプリでいい感じにインディケーター付けるやつ標準でないかなーと思ったけど
見つけられなかったので、無理やり実装した。
ものすごく拡張性が低くてダサいのでどうにかしたい。。。

ちなみにインディケーターは、`○`（白丸）を`●`（黒丸）にすることで実現することにした。CSSすらも使わないしレイアウトもベタ書きだしひどくアナログだ。

追記：
今もうちょいググってみたら、ラジオボタン使ったりいろいろ工夫されてるソースあった。
あとレイアウトも、ボタン4つになったらとたんにレイアウト崩れるしこれはあかん。
やっつけとはいえ恥ずかしす。

# 方法
* ページングするViewと、インディケーターを表示するViewを重ねる
* Fragment ⇔ レイアウト（1対1）
* ページングするたびにインディケーターを描き替える
    * FragmentActivityでViewPager.SimpleOnPageChangeListenerをオーバーライドしてページングイベントをキャッチ
    * setText("●");

# 構造
* レイアウトxml
    * インディケーターを表示するView（つまりずーっと表示されてる）
        * layout/fragment_activity.xml
    * ページングとして使われるView
        * layout/fragment_activity2.xml
    * ページ（切り替わる用）
        * layout/fragment0.xml
        * layout/fragment1.xml
        * layout/fragment2.xml
* FragmentActivity
* ActivityFragmentPagerAdapter
* Fragment（ページの数だけ）
    * Fragment0
    * Fragment1
    * Fragment2


# 実装
めも。アプリの最初で使いたかったので`OpeningActivity`としてる。

## レイアウトxml
### インディケーターを表示するView

```xml
<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="com.xxxx.xxxx.OpeningActivity">

    <TextView
        android:id="@+id/indicator_0"
        android:text="●"
        android:textColor="@color/white"
        android:textSize="20dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="40dp"
        android:layout_marginRight="10dp"
        android:layout_toLeftOf="@+id/indicator_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/indicator_1"
        android:text="○"
        android:textColor="@color/white"
        android:textSize="20dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="40dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/indicator_2"
        android:text="○"
        android:textColor="@color/white"
        android:textSize="20dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="40dp"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@+id/indicator_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>
```

### ページングとして使われるView
pegerさえあればよい。

```xml
<LinearLayout 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"
    android:orientation="vertical"
    tools:context="com.xxxx.xxxx.OpeningActivity">

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

</LinearLayout>
```

### ページ
これは省略。お好きな様に。

## FragmentActivity

```java
public class OpeningActivity extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_activity);

        // 上にViewを重ねる（一番上のViewに対してPagerがセットされる）
        View view = getLayoutInflater().inflate(R.layout.fragment_activity2, null);
        addContentView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));

        // getSupportFragmentManager は, FragmentActivity で使える
        FragmentManager fragmentManager = getSupportFragmentManager();
        OpeningActivityFragmentPagerAdapter pagerAdapter = new OpeningActivityFragmentPagerAdapter(fragmentManager);
        ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
        viewPager.setAdapter(pagerAdapter);
        // ページリスナーをセット（インディケーター用）
        viewPager.addOnPageChangeListener(new MyOnPageChangeListener());
    }
    private class MyOnPageChangeListener
            extends ViewPager.SimpleOnPageChangeListener {

        @Override
        public void onPageSelected(int position) {
            // ドラッグ終了時（移動先のページ決定時）
            setCarouselNum(position);
        }

        // インディケーター書き換え
        private void setCarouselNum(int currentPosition) {
            TextView indicator_0 = (TextView)findViewById(R.id.indicator_0);
            TextView indicator_1 = (TextView)findViewById(R.id.indicator_1);
            TextView indicator_2 = (TextView)findViewById(R.id.indicator_2);

            // TODO: もっと良い方法ないかな
            switch(currentPosition) {
                case 0:
                    indicator_0.setText("●");
                    indicator_1.setText("○");
                    indicator_2.setText("○");
                    break;
                case 1:
                    indicator_0.setText("○");
                    indicator_1.setText("●");
                    indicator_2.setText("○");
                    break;
                case 2:
                    indicator_0.setText("○");
                    indicator_1.setText("○");
                    indicator_2.setText("●");
                    break;
                default:
                    indicator_0.setText("○");
                    indicator_1.setText("○");
                    indicator_2.setText("●");
                    break;
            }
        }
    }

    // 以下、デフォルトで作られるonCreateOptionsMenuとonOptionsItemSelectedあり
}
```

## ActivityFragmentPagerAdapter

```java
public class OpeningActivityFragmentPagerAdapter extends FragmentPagerAdapter {
    public OpeningActivityFragmentPagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    @Override
    public Fragment getItem(int position) {
        switch(position){
            case 0:
                return new OpeningActivityFragment0();
            case 1:
                return new OpeningActivityFragment1();
            case 2:
                return new OpeningActivityFragment2();
            default:
                return new OpeningActivityFragment2();
        }
    }

    @Override
    public int getCount() {
        return 3;
    }
}

```

## Fragment
Fragment0だけ。1, 2は0の部分を置き換えるだけ。

```java
public class OpeningActivityFragment0 extends Fragment {
    public OpeningActivityFragment0() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
//         Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment0, container, false);
        return view;
    }
}
```


# 参考
* http://rakuishi.com/archives/6645/
* http://qiita.com/murapon/items/89fb4b8bd462c606d66f
* http://qiita.com/mackiso/items/1dacec44d9096bc6d900
* http://outcesticide.hatenablog.com/entry/ViewPager_SimpleOnPageChangeListener