【Android】レイアウトを折りたためるViewを作った - ExpandableLayout

# 概要
最近Viewのクラス作って遊んでます。

一つ前くらいのGooglePlayのアプリ説明文で使われていた、
折りたたみ式のレイアウトがどんな感じで実装できそうか興味があったので、試しに作ってみた。

![demo](http://i.imgur.com/nY4tA5t.gif)

# 紹介
ExpandableLayout

レイアウト内の要素を折りたたむことができるView

- Github
 - https://github.com/chuross/ExpandableLayout
- YouTube
 - https://www.youtube.com/watch?v=e7WaAzMRvzA
 
# 特徴
- 折りたたんだ時のExpandableLayoutの高さを指定できる
- ExpandableLayoutが内包しているViewのIDを指定すると、IDで指定したViewまでを折りたたむ事ができる
- 折りたたんだ時の高さの余白を指定できる
- 折りたたみアニメーションの時間を指定できる
- 折りたたみ時 / 開いた時のコールバックを指定できる
- 折りたたみ時 / 開いた時のアニメーションを指定できる

# 使い方
## Gradleの依存関係にExpandableLayoutを追加

```groovy
repositories {
    maven {
        url 'http://chuross.github.com/maven-repository/'
    }
}

dependencies {
    compile 'com.github.chuross:expandablelayout:1.0.3'
}
```

GithubPageの個人maven-repositoryに上げてあるので、repositoriesへの追加も忘れずに

## XMLのレイアウトに記述する

```xml
<dev.chuross.library.ExpandableLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <!-- ExpandableLayoutの中に自由なViewを入れる -->
</dev.chuross.library.ExpandableLayout>
```

基本これだけで利用できちゃいます

## ExpandableLayoutに属性を追加する
|名前|型|説明|補足|
|:---|:---|:---|:---|
|exl_collapse_height|dimention|折りたたみ時のExpandableLayoutの高さを指定する|exl_collapse_target_idとの併用はできない|
|exl_collapse_target_id|reference|折りたたみ時のExpandableLayoutの高さを計算するためのViewIDを指定する|指定するとIDで指定したViewまでを自動計算して折りたたむ|
|exl_collapse_padding|dimention|折りたたみ時のExpandableLayoutの高さに余白を加える||
|exl_duration|integer|折りたたみ時 / 開いた時のアニメーションの時間を指定する||
|exl_expanded|boolean|View生成時に開いた状態にする||

## 折りたたみを操作する

```java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ExpandableLayout expandableLayout = (ExpandableLayout)findViewById(R.id.layout_expandable);

    expandableLayout.expand();// 開く
    expandableLayout.collapse();// 折りたたむ

    expandableLayout.expand(false);// アニメーション無しで開く
    expandableLayout.collapse(false);// アニメーション無しで折りたたむ
}
```

# 補足
## exl_collapse_heightとexl_collapse_target_idの違い
### exl_collapse_height
- 折りたたんだ時のExpandableLayoutの高さを固定したい場合に使う
- どのくらいの高さで折りたたむか決まっているのであればの属性を指定すると良い

### exl_collapse_target_id
- ExpandableLayoutが内包するViewの位置で、折りたたんだ時のExpandableLayoutの高さを調整したい場合に使う
- TextViewの`layout_height=WRAP_CONTENT`の場合のように、可変する要素を対象として折りたたみ時の高さを調整したい時に使うと良い

## exl_collapse_paddingの使いどころ
- 主にexl_collapse_target_idを使うような場面で使用される
- 折りたたみ時のExpandableLayoutの高さをViewIDで指定しつつ、そのViewの一部を見せた状態で折りたたませたい時に使うと良い

## exl_collapse_target_idの例

こんな感じに指定すると、@+id/twoのViewの先頭までが折りたたまれる

```xml
<dev.chuross.library.ExpandableLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:exl_collapse_target_id="@+id/two">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <View
            android:id="@+id/one"
            android:layout_width="match_parent"
            android:layout_height="120dp" />
        <View
            android:id="@+id/two"
            android:layout_width="match_parent"
            android:layout_height="200dp" />                
    </LinearLayout>
</dev.chuross.library.ExpandableLayout>
```

## exl_collapse_target_idの例(exl_collapse_paddingと組み合わせた例)

こんな感じに書くと@+id/twoのViewが半分見える状態で折りたたまれるようになる
(@+id/twoのViewの先頭から100dp加えた位置までを折りたたむように計算するため)

```xml
<dev.chuross.library.ExpandableLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:exl_collapse_target_id="@+id/two"
    app:exl_collapse_padding="100dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <View
            android:id="@+id/one"
            android:layout_width="match_parent"
            android:layout_height="120dp" />
        <View
            android:id="@+id/two"
            android:layout_width="match_parent"
            android:layout_height="200dp" />                
    </LinearLayout>
</dev.chuross.library.ExpandableLayout>
```

## 折りたたみ時のアニメーションを変更する
![demo2](http://i.imgur.com/2npiSMK.gif)


内部的にはアニメーション動作にScrollerを使用しているので、[Interpolator]
(http://developer.android.com/reference/android/view/animation/Interpolator.html)を変更する事で動作を変更することができる

```java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ExpandableLayout expandableLayout = (ExpandableLayout)findViewById(R.id.layout_expandable);
    expandableLayout.setInterpolator(new BounceInterpolator());
}
```

カスタマイズも可能だが、標準で用意されているものはこちらで確認すると良さそう

- https://dl.dropboxusercontent.com/u/6685256/AndroidInterpolation/index.html

# ライセンス
Apache License 2.0