📱

Androidで個人的によく使うlayout系設定チートシート

2020/09/22に公開1

はじめに

この記事はもともとQiitaに投稿していた記事をZennに移植したものです。内容は同じです。
個人的によく使うレイアウト系のチートシート。
よく忘れて毎回調べるのでメモ。
逐次更新

ボタンを横に等間隔で配置する

        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Btn1"/>
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Btn2"/>
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Btn3"/>
        </LinearLayout>

実装のポイント

  • 各ボタンにlayout_width="match_parent",layout_weight="1"を設定

EditTextを横幅いっぱいで右端にTextViewを配置

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="きんがく"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:text=""/>
    </LinearLayout>

実装のポイント

  • EditTextにlayout_weight="1",layout_width="wrap_content"を設定
  • TextViewにgravity="right",layout_width="wrap_content"を設定
     <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:hint="きんがく"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/textView3"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

実装ポイント

  • EditTextにEditTextの右をTextViewの左にの制約をつける
    • app:layout_constraintEnd_toStartOf="@+id/textView3"
  • EditTextのwidthにMatch Constraintsの制約をつける
    • android:layout_width="0dp"

EditTextの入力を右寄せに

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="right"
            android:hint="きんがく"
            android:text="123,456,789"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:text=""/>
    </LinearLayout>

実装のポイント

  • EditTextにgravity="right"を設定
  • Hintも右寄せになるので注意

Viewに対してRippleエフェクト

以前、「AndroidのRecycleViewでrippleエフェクトが出ない時にチェックしたほうがいいこと」で書いた内容

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:focusable="true"
             android:clickable="true"
             android:layout_height="wrap_content"
             android:foreground="?android:attr/selectableItemBackground">
    <LinearLayout android:orientation="vertical"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content">
    <!-- 中身 -->
    </LinearLayout>
</FrameLayout>

実装のポイント

  • 一番外のLayoutをFrameLayoutにする(これ以外のLayoutはNG)
  • FrameLayoutにandroid:focusable="true",android:clickable="true", android:foreground="?android:attr/selectableItemBackground"を設定する
  • 角丸ボタンを作ってそれにエフェクトをつけたい場合は「角丸ボタンにRipple Effectをつける」を参考

ScrollViewのBottomにFooterを固定する

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:padding="@dimen/common_padding"
              android:orientation="vertical">
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <!-- 中身 -->

        </LinearLayout>
    </ScrollView>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="bottom"
        android:orientation="horizontal">

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/cancel"/>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/ok"/>
    </LinearLayout>
</LinearLayout>

実装のポイント

  • ScrollViewにlayout_weight="1"を設定
  • Footer用のLayoutにgravity="bottom",layout_height="wrap_content"を設定

ボタンの共通デザインを定義する

    <style name="ImportantButtonStyle" parent="Theme.AppCompat">
        <item name="colorButtonNormal">@color/importantButtonNormal</item>
        <item name="colorControlHighlight">@color/importantButtonHighLight</item>
        <item name="android:textColor">@color/importantButtonTextColor</item>
    </style>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ImportantButtonStyle"
            android:text="決定"/>

実装のポイント

  • style.xmlにスタイルを定義
  • 呼び出したいボタンのthemeで定義したスタイルを呼び出す

ActionBarのハンバーガーアイコン、戻る矢印、メニューのテキスト、タイトルテキストの色を変える

StackOverFlowから転記(アイコンの色)
StackOverFlowから転記(Menuのテキスト)

<style name="ToolbarStyle" parent="@style/ThemeOverlay.AppCompat.ActionBar">
  <!-- Customize color of navigation drawer icon and back arrow --> 
  <item name="colorControlNormal">@color/actionbarItemColor</item>
  <!-- Customize color of menu item text-->
  <item name="actionMenuTextColor">@color/actionbarItemColor</item>

</style>
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:titleTextColor="@color/actionbarItemColor"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:theme="@style/ToolbarStyle" >
</android.support.v7.widget.Toolbar>

実装のポイント

  • styles.xmlでcolorControlNormalの要素を変更→アイコン系の色変更
  • styles.xmlでactionMenuTextColorの要素を変更→メニューのテキストの色変更
  • Toolbarの要素にapp:titleTextColorの要素を変更→タイトルのテキストの色変更
  • app:theme="@style/ToolbarStyle"を追加し、styleを反映
  • titleTextColorもstyles.xmlで指定できるが、APILv23以上を要求してくる

Tabレイアウトを作る

これはKotlin用のCleanArchitectureのテンプレート作ったよ!で書いた、CleanArchitecture前提

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

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

        <android.support.design.widget.TabItem
            android:id="@+id/details_tab_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="tab2"/>
        <android.support.design.widget.TabItem
            android:id="@+id/details_tab_3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="tab3"/>
    </android.support.design.widget.TabLayout>
    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</LinearLayout>

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        var fragment1 = activity.supportFragmentManager.findFragmentById(R.id.details_tab_1) as Fragment1?
        var fragment2 = activity.supportFragmentManager.findFragmentById(R.id.details_tab_2) as Fragment2?
        var fragment3 = activity.supportFragmentManager.findFragmentById(R.id.details_tab_3) as Fragment3?
        
        if (fragment1 == null) {
            fragment1 = Fragment1.newInstance()
            activity.supportFragmentManager.beginTransaction().add(R.id.details_tab_1, fragment1).commit()
        }
        if (fragment2 == null) {
            fragment2 = Fragment2.newInstance()
            activity.supportFragmentManager.beginTransaction().add(R.id.details_tab_2, fragment2).commit()
        }
        if (fragment3 == null) {
            fragment3 = Fragment3.newInstance()
            activity.supportFragmentManager.beginTransaction().add(R.id.details_tab_3, fragment3).commit()
        }

        (activity.application as MyApplication).rootComponent
                .newFragment1Component(Fragment1Module(fragment1 as Fragment1Contract.View)).inject(fragment1)
        (activity.application as MyApplication).rootComponent
                .newFragment2Component(Fragment2Module(fragment2 as Fragment2Contract.View)).inject(fragment2)
        (activity.application as MyApplication).rootComponent
                .newFragment3Component(Fragment3Module(fragment3 as Fragment3Contract.View)).inject(fragment3)

        val adapter = SectionsPagerAdapter(activity.supportFragmentManager,fragment1,fragment2,fragment3)
        view_pager.adapter = adapter
        view_pager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabs))
        view_pager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener(){
            override fun onPageSelected(position: Int) {
                super.onPageSelected(position)

                when(position) {
                    TAB_1 -> fragment1.load()
                    TAB_2 -> fragment2.load()
                    TAB_3 -> fragment3.load()
                }
            }
        })
        tabs.addOnTabSelectedListener(TabLayout.ViewPagerOnTabSelectedListener(view_pager))

    }

    inner class SectionsPagerAdapter(fm: FragmentManager,
                                     private val fragment1: Fragment1,
                                     private val fragment2: Fragment2,
                                     private val ragment3: Fragment3)
        : FragmentPagerAdapter(fm) {

        override fun getItem(position: Int): Fragment {
            return when(position) {
                TAB_1 -> fragment1
                TAB_2 -> fragment2
                TAB_3 -> fragment3
                else -> fragment1
            }
        }

        override fun getCount(): Int {
            return 3
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        presenter.dispose()
    }

    companion object {
        fun newInstance(): DetailsFragment {
            val args = Bundle()
            val fragment = DetailsFragment()
            fragment.arguments = args
            return fragment
        }

        const val TAB_1 = 0
        const val TAB_2 = 1
        const val TAB_3 = 2
    }

実装のポイント

  • CleanArchitectureTemplateではActivityのonCreateで行なっていたinject処理を、onCreatedViewで行う
  • Tab管理にはFragmentPagerAdapterを利用する
  • view_pager.adapter = adapterでAdapterとViewPagerを紐づける
  • view_pager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabs))でViewPagerが動いたらTabも動くようにしてる
  • view_pager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener(){でページが切り替わったら各Tab内のFragment側でロード処理を行う。(画面が表示された時の処理)
  • tabs.addOnTabSelectedListener(TabLayout.ViewPagerOnTabSelectedListener(view_pager))でTabをタップしたらViewPager側も動くようにしている
  • Activityでも同様の実装が出来る。その場合、onCreatedViewの実装はonCreate内で行う

Headerがスクロールすると消えるやつ

CoordinatorLayoutでヘッダー隠す時の知見を得た話」これの話の要点まとめ

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <!-- AppbarLayout内にHeaderパーツを入れる -->
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">
            
            <android.support.v7.widget.Toolbar
                ...
                app:layout_scrollFlags="scroll|enterAlways"/>  
            <!-- 最初にscrollFlagsが設定されていないパーツが見つかった時点でスクロールが止まるようになる -->
        </android.support.design.widget.AppBarLayout>
         <!-- AppBarLayoutの下にスクロールさせたいパーツを配置する -->
         <!-- 指定できるパーツはNestedScrollViewかRecyclerViewのみ -->
         <!-- app:layout_behavior="@string/appbar_scrolling_view_behavior"この指定をすることで、リストの開始地点がAppBarLayoutの下になる。-->
         <!--  指定しないと画面トップからになる -->
         <android.support.v4.widget.NestedScrollView
            android:id="@+id/pager"
            android:layout_below="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <!-- 中身 -->

        </android.support.v4.widget.NestedScrollView>

    </android.support.design.widget.CoordinatorLayout>

</LinearLayout>

実装のポイント

  • 構造は以下のとおり
 --- CoordinatorLayout
                + AppBarLayout
                |         + Headerでスクロールさせたいパーツ
                |         + Headerでスクロールさせたくないパーツ
                |
                + NestedScrollView or RecyclerView
                       + コンテンツの中身   
  • Headerのパーツは必ずスクロールさせたいパーツスクロールさせたくないパーツの順に並べる
  • スクロールさせたいHeaderパーツにはapp:layout_scrollFlags="scroll"の指定を行うこと
  • スクロールコンテンツはNestedScrollViewRecyclerViewのみ使える
  • スクロールコンテンツにapp:layout_behavior="@string/appbar_scrolling_view_behavior"の設定を行うと、Headerパーツの下からスクロールコンテンツが配置される。指定しないと画面トップからスクロールコンテンツが配置される(Headerの裏にスクロールコンテンツが隠れる感じ)
  • AppBarLayout配下のパーツにはAppThemeが自動で適応される。もしカスタマイズしたい場合はthemeの指定をする必要がある

Drawerメニューを追加する

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                        xmlns:app="http://schemas.android.com/apk/res-auto"
                                        android:id="@+id/menu_drawer_layout"
                                        android:fitsSystemWindows="true"
                                        android:layout_width="match_parent"
                                        android:layout_height="match_parent">
    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/menu_toolbar"
                app:title="?attr/toolbar_title"
                android:theme="@style/ToolbarStyle"
                app:titleTextColor="@color/actionbarItemColor"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary" />

        </android.support.design.widget.AppBarLayout>

        <FrameLayout
            android:paddingTop="?attr/actionBarSize"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/base_fragment"/>

    </android.support.design.widget.CoordinatorLayout>
    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:itemBackground="@drawable/navigation_drawer_item_bg_color"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/main_drawer" />
</android.support.v4.widget.DrawerLayout>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:id="@+id/main_menu_group"
           android:checkableBehavior="single">
        <item android:id="@+id/nav_home"
              android:icon="@drawable/icon_home"
              android:title="@string/nav_home"/>
    </group>
    <group android:id="@+id/main_menu_link_group"
           android:checkableBehavior="none">
        <item android:id="@+id/nav_link"
              android:icon="@drawable/icon_link"
              android:title="@string/nav_link"/>
    </group>
</menu>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.base_menu_activity)

        setSupportActionBar(menu_toolbar)
        val toggle = object : ActionBarDrawerToggle(
                this, menu_drawer_layout, menu_toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
            override fun onDrawerOpened(drawerView: View) {
                super.onDrawerOpened(drawerView)
                //Drawerが開いた時の処理
            }
        }

        menu_drawer_layout.addDrawerListener(toggle)
        toggle.syncState()
        nav_view.setNavigationItemSelectedListener { item ->
            val id = item.itemId
            launch(id)
            menu_drawer_layout.closeDrawer(GravityCompat.START)
            true
        }
        nav_view.menu.findItem(getCurrentNaviId()).isChecked = true
    }

    private fun launch(id: Int) {
        //idに応じて画面遷移など
    }
    override fun onBackPressed() {
        if (menu_drawer_layout.isDrawerOpen(GravityCompat.START)) {
            menu_drawer_layout.closeDrawer(GravityCompat.START)
        } else {
            super.onBackPressed()
        }
    }

実装ポイント

  • Layout.xmlでは一番外側の要素をDrawerLayoutにする
  • DrawerのデザインにはNavigationViewを使う
  • Drawerのメニュー指定はxml側にてapp:menu="@menu/main_drawer"で指定
  • Drawerのヘッダー指定はxml側にてapp:headerLayout="@layout/nav_header"で指定

画面切り替わり時にクロスフェード

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:interpolator="@android:anim/accelerate_interpolator"
       android:fromAlpha="0.0" android:toAlpha="1.0"
       android:duration="300" />
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:interpolator="@android:anim/accelerate_interpolator"
       android:fromAlpha="1.0" android:toAlpha="0.0"
       android:fillAfter="true"
       android:duration="300" />
fun someMethod() {
    someButton.onClickListener({ 
        SomeSubActivity.launch()
        overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
    })
}

実装ポイント

  • intentStart処理の後にoverridePendingTransitionでフェードをかける

layoutのexpand/collapseアニメーション&アイコンくるり

RecycleViewで開閉(Expand/Collapse)のアニメーションを実装する」を参照

HeaderのタイトルをStyle.xmlで変える

共通のbase_activity.xmlを各Activityは使用する前提。
Header部分は「Headerがスクロールすると消えるやつ」の応用。Activity側でイベントを紐づけられるようにするため。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              xmlns:app="http://schemas.android.com/apk/res-auto">
    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                                     android:id="@+id/main_content"
                                                     android:layout_width="match_parent"
                                                     android:layout_height="match_parent">
        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                app:title="?attr/toolbar_title"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                />

        </android.support.design.widget.AppBarLayout>
        <FrameLayout
            android:id="@+id/base_fragment"
            android:paddingTop="?attr/actionBarSize"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </android.support.design.widget.CoordinatorLayout>


</LinearLayout>
<resources>
    <attr name="toolbar_title" format="reference" />

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="toolbar_title">@string/app_name</item>
    </style>

    <style name="CoordinatorLayoutHeader" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="HomeActivity" parent="AppTheme">
        <item name="toolbar_title">@string/home_title</item>
    </style>
</resources>
        <activity
            android:name=".home.HomeActivity"
            android:launchMode="singleTask"
            android:theme="@style/HomeActivity" />

実装のポイント

  • base_activity.xmlのToolbarのapp:titleに対して?attr/toolbar_titleを設定する
  • style.xmlに<attr name="toolbar_title" format="reference" />を設定する
  • style.xmlにて、<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">を定義。ここではAppThemeをNoActionBarで上書きしたいために設定している。要素内でのcolorの定義やtoolbar_titleの定義は任意でOK。
  • CoordinatorLayoutHeaderの設定は任意。設定することで、スクロールすると消える部分の設定を行える。今回はHeader部分のみなので特に影響はない。
  • style.xmlにて、AppThemeを継承したstyleを定義する。(例の場合はHomeActivity)。その要素として<item name="toolbar_title">@string/home_title</item>を指定する
  • AndroidManifest.xmlにて、該当のActivityの属性としてandroid:theme="@style/HomeActivity"を指定する

検索ボタンをActionBarに追加する

<?xml version="1.0" encoding="utf-8"?>
<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/search_menu_item"
          android:title="@string/search"
          android:icon="@android:drawable/ic_menu_search"
          app:showAsAction="always"
          android:orderInCategory="100"
          app:actionViewClass="android.widget.SearchView"
          />
</menu>
class SearchableActivity: AppCompatActivity(), SearchView.OnQueryTextListener {

    protected lateinit var searchView:SearchView

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.search_menu, menu)
        searchView = menu?.findItem(R.id.search_menu_item)?.actionView as SearchView
        searchView.setOnQueryTextListener(this)
        searchView.isSubmitButtonEnabled = false

        return super.onCreateOptionsMenu(menu)
    }

    override fun onQueryTextSubmit(query: String?): Boolean {
        //送信ボタン的なやつ押したら検索
        return false
    }

    override fun onQueryTextChange(newText: String?): Boolean {
        //インクリメンタル検索
        return false
    }
}

実装ポイント

  • 検索のメニューを用意して、OptionsMenuでそいつを追加。

RecycleViewの実装

単純なリスト形式
Adapter生成にはUseful-template-forKotlinを利用(露骨な宣伝)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/some_list"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:listitem="@layout/adapter_some"
        tools:context=".some.SomeListFragment"
        app:layoutManager="LinearLayoutManager"/>
</LinearLayout>

fun loaded(data:List<SomeData>) {
        if (some_list != null && some_list.adapter == null) {
            some_list.adapter = SomeAdapter(data)
        } else {
            (some_list.adapter as SomeAdapter).data = data
            some_list.adapter.notifyDataSetChanged()
        }
}

実装ポイント

  • listのnullチェックは念のため。実装の仕方によっては不要かもしれない

ActionBarにアイコン表示

class SomeActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.base_activity)
        supportActionBar!!.setIcon(R.drawable.ic_launcher_small)
        supportActionBar!!.setDisplayShowHomeEnabled(true)
    }
}
    <style name="SomeActivityTheme" parent="Theme.AppCompat.Light">
    </style>

実装ポイント

  • アイコンセットsupportActionBar!!.setIcon(R.drawable.ic_launcher_small)
  • アイコン表示の設定supportActionBar!!.setDisplayShowHomeEnabled(true)
  • デフォルトのActionBarを使うため、ActivityのテーマのparentにNoActionBar設定しない

Discussion