3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

マテリアルデザインな検索バーを作る

Last updated at Posted at 2016-10-01

Google PlayやInboxなどで使われている、Toolbarの上に重なるように表示される検索バーの実装です。

サンプル

シンプルなのアクティビティの場合

|通常|検索バーを開く|
|---+------------|
|basic1.png|basic2.png|

タブを含むアクティビティの場合

|通常|検索バーを開く|
|---+------------|
|tab1.png|tab2.png|

実装方法

MaterialSearchViewライブラリーを利用しました。

usage

上記のgithubのREADMEに書いてある通りですが、もう一度ここで転記しておきます。

gradleファイルに、依存関係を追記する

build.gradle
dependencies {
    compile 'com.miguelcatalan:materialsearchview:1.4.0'
}

MaterialSearchViewをレイアウト内のToolbarと同じ位置に追加する

activity_xxx.xml
<!— Must be last for right layering display —>
<FrameLayout
    android:id="@+id/toolbar_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/theme_primary" />

    <com.miguelcatalan.materialsearchview.MaterialSearchView
        android:id="@+id/search_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</FrameLayout>

メニューファイルにメニューのアイテムを追加する

menu_xxx.xml
<item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_action_action_search"
    android:orderInCategory="100"
    android:title="@string/abc_search_hint"
    app:showAsAction="always" />

onCreateOptionsMenuメソッドに定義を追加する

ActivityXxx.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);

    MenuItem item = menu.findItem(R.id.action_search);
    searchView.setMenuItem(item);

    return true;
}

リスナーを定義する

ActivitXxx.java
searchView = (MaterialSearchView) findViewById(R.id.search_view);
searchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String query) {
        //Do some magic
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        //Do some magic
        return false;
    }
});

searchView.setOnSearchViewListener(new MaterialSearchView.SearchViewListener() {
    @Override
    public void onSearchViewShown() {
        //Do some magic
    }

    @Override
    public void onSearchViewClosed() {
        //Do some magic
    }
});

ライブラリーのドキュメントに書いてなくて、はまったところ

MaterialSearchViewがうまくアクションバーに重なるように表示されるには、

FrameLayout
+-- Toolbar
+-- MaterialSearchView

というように、FrameLayout中にToolbar → MaterialSearchViewという順にViewが定義されないといけない。しかし、最近のAndroidStudioが生成するEmptyActivityとTabActivityはいずれも一筋縄ではいかなかった。

EmptyActivityの場合

AndroidStudioが作成するプロジェクトでは、アクティビティのスタイルのデフォルトが Theme.AppCompat.Light.DarkActionBar になっている。これには、すでにtoolbarが含まれているため、上記の手順のレイアウトを定義している時のtoolbarと被ってしまう。 NoActionBar を使えばいいのだが、その場合Toolbarの色やスタイルを自分で定義しなければならない。もし、デフォルトのスタイルのままでMaterialSearchViewを使いたい場合は、Toolbarが含まれているViewGroupを探し出して、コードでMaterialSearchViewをインスタンス化して追加すると良い。

BasicActivity.java
public class BasicActivity extends AppCompatActivity {
    private MaterialSearchView searchView;

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

        searchView = new MaterialSearchView(this);
        searchView.setLayoutParams(new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, 
            ViewGroup.LayoutParams.WRAP_CONTENT
        ));

        ViewGroup viewGroup = (ViewGroup) findViewById(R.id.activity_main).getParent();
        while (viewGroup != null) {
            if (viewGroup instanceof ActionBarOverlayLayout) {
                viewGroup = (ViewGroup) viewGroup.getParent();
                viewGroup.addView(searchView);
                break;
            }
            viewGroup = (ViewGroup) viewGroup.getParent();
        }
        // 略
    }
    // 略
}

TabActivityの場合

TabActivityの場合は、AndroidStudioのウィザートが NoActionBar を使うようにコードを生成してくれる。ただし、Toolbarと同じ階層にタブ用のビューがあるので、FrameLayoutになっていない。そのため、Toolbarの部分をFrameLayoutでさらに囲み、その中にMaterialSearchViewを入れると良い。

activity_tab.xml
<!-- 略 -->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/appbar_padding_top"
        android:theme="@style/AppTheme.AppBarOverlay">

        <!-- ToolbarをFrameLayoutで囲み、MaterialSearchViewを追加 -->
        <FrameLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/AppTheme.PopupOverlay">

            </android.support.v7.widget.Toolbar>

            <com.miguelcatalan.materialsearchview.MaterialSearchView
                android:id="@+id/search_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </FrameLayout>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </android.support.design.widget.AppBarLayout>
<!-- 略 -->

TODO

  • 検索バーで検索が行われた後の処理は書いていない。
  • タブごとに検索バーの表示を制御する処理は書いていない。
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?