0
0

More than 1 year has passed since last update.

ActionBarでSearchViewを使うと意図せず他のアクションボタンが消えちゃう問題の解決策

Posted at

AndroidでActionBarSearchViewのようなアクションビュークラスを使用してる時に発生するバグもどきに対する備忘録です。

問題の詳細

以下のコードでSearchViewが開かれた(expand)状態でオーバーフローメニューをタップしたりDialogFragmentを開いたりすると表示されていたアクションボタンがオーバーフローメニューに移り、更にその状態でSearchViewを閉じると表示されていたSearchViewを含めた全てのアクションボタンが消える。

動画

再現動画

menu_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/search_bar"
        android:icon="@drawable/ic_search"
        android:title="search"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        app:iconTint="?attr/colorOnPrimarySurface"
        app:showAsAction="ifRoom|collapseActionView" />
    <item
        android:id="@+id/button1"
        android:icon="@drawable/ic_button1"
        android:title="button1"
        app:iconTint="?attr/colorOnPrimarySurface"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/button2"
        android:icon="@drawable/ic_button2"
        android:title="button2"
        app:iconTint="?attr/colorOnPrimarySurface"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/settings"
        android:title="settings"
        app:showAsAction="never" />
</menu>
MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.button1, R.id.button2, R.id.settings -> true
            else -> super.onOptionsItemSelected(item)
        }
    }
}

問題の原因

SearchViewを開いている時にonPrepareOptionsMenuが行われると
SearchViewが邪魔でアクションボタンが表示できない→仕方がないのでアクションボタンをオーバーフローメニューに入れる→SearchViewが閉じられる→オーバーフローメニューに入れられたやつがどっかいく (何故?) 」という流れになるっぽい。

解決策

素直に「menu_main.xml」のifRoomを全てalwaysまたはneverにすれば解決する。

menu_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/search_bar"
        android:icon="@drawable/ic_search"
        android:title="search"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        app:iconTint="?attr/colorOnPrimarySurface"
-       app:showAsAction="ifRoom|collapseActionView"
+       app:showAsAction="always|collapseActionView" />
    <item
        android:id="@+id/button1"
        android:icon="@drawable/ic_button1"
        android:title="button1"
        app:iconTint="?attr/colorOnPrimarySurface"
-       app:showAsAction="ifRoom"
+       app:showAsAction="always" />
    <item
        android:id="@+id/button2"
        android:icon="@drawable/ic_button2"
        android:title="button2"
        app:iconTint="?attr/colorOnPrimarySurface"
-       app:showAsAction="ifRoom"
+       app:showAsAction="never" />
    <item
        android:id="@+id/settings"
        android:title="settings"
        app:showAsAction="never" />
</menu>

ただし、どうしてもifRoomを変えたくないという場合はonPrepareOptionsMenuをオーバーライドしてSearchViewを無理やり閉ざしてやればいい。

MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

+   override fun onPrepareOptionsMenu(menu: Menu): Boolean {
+       menu.findItem(R.id.search_bar).collapseActionView()
+       return true
+   }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.button1, R.id.button2, R.id.settings -> true
            else -> super.onOptionsItemSelected(item)
        }
    }
}
0
0
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
0
0