will come true

[Android/Kotlin] MenuItem 객체의 actionView 속성 접근시 에러 해결 본문

Android

[Android/Kotlin] MenuItem 객체의 actionView 속성 접근시 에러 해결

haehyun 2022. 1. 6. 22:03

에러

메뉴, 메뉴 아이템, 액션뷰에 대한 XML 파일이 작성되어 있는 상태에서 Menu객체에서 특정 id의 MenuItem 객체를 얻고, MenuItem 객체에서 해당 MenuItem에 지정된 ActionView를 얻어내는 과정에서 에러가 발생함.

 

메뉴 XML 파일 (menu_main.xml)

<?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/menu_search"
        android:title="search"
        app:showAsAction="always"
        app:actionViewClass="androidx.appcompat.widget.SearchView" />
</menu>

 

메인 액티비티 파일 (MainActivity.kt)

package com.example.androidlab

import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.widget.SearchView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
   }

    // 업 버튼 클릭 이벤트
    override fun onSupportNavigateUp(): Boolean {
        Log.d("kkang", "onSupportNavigateUp")
        return super.onSupportNavigateUp()
    }

    // 메뉴 구성
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)

        val menuItem = menu.findItem(R.id.menu_search)
        val searchView = menuItem.actionView as SearchView  // 에러 발생 부분

        searchView.setOnQueryTextListener(object: SearchView.OnQueryTextListener{
            // 검색어 변경 이벤트
            override fun onQueryTextChange(newText: String?): Boolean {
                return true
            }

            // 키보드의 검색 버튼을 클릭한 순간의 이벤트
            override fun onQueryTextSubmit(query: String?): Boolean {
                return true
            }
        })

        return super.onCreateOptionsMenu(menu)
    }

    // 메뉴 클릭 이벤트
    override fun onOptionsItemSelected(item: MenuItem): Boolean = when(item.itemId) {
        0 -> {
            Log.d("kkang", "menu1 click")
            true
        }
        1 -> {
            Log.d("kkang", "menu2 click")
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

 

디버깅 돌려본 결과, menu.findItem(R.id.menu_search)에 의해 MenuItem 객체까지는 제대로 얻어지나 해당 MenuItem에 설정된 ActionView를 가져오는 과정에서 에러가 발생함.

menuInflater.inflate(R.menu.menu_main, menu)

        val menuItem = menu.findItem(R.id.menu_search)
        val searchView = menuItem.actionView as SearchView  // 에러 발생 부분

 

해결

해당 코드 한줄에 문제가 있다고 생각해 actionView 속성에 바로 접근하는 방식에서 MenuItemCompat.getActionView(menuItem) 과 같이 지금은 @Deprecated 된 메서드로 접근하는 방식도 사용해봤으나 해결되지 않았다.

val searchView = menuItem.actionView as SearchView
val searchView = MenuItemCompat.getActionView(menuItem) as SearchView

 

한참을 헤매던 중 우연히 코드 상단의 import문을 펼쳐보게 됐고, 패지키가 잘 못 참조되었다는 걸 알게되었다..
메뉴 XML 파일에서 사용한대로 androidx.appcompat.widget 라이브러리의 SearchView 클래스를 import해야하는데, 자동 import기능 때문에 코드 내에서 SearchView 클래스를 사용하자마자 자동으로 android.widget 라이브러리에 속한 동명의 SearchView 클래스가 import 되어버린 것이다.

(X)

import android.widget.SearchView

(O)

import androidx.appcompat.widget.SearchView

 

import문을 아래와 같이 바꾸니 MenuItem에서 ActoinView가 정상적으로 얻어지고, 앱도 제대로 실행되었다.

Comments