Program Tip

Android 체크 가능 메뉴 항목

programtip 2020. 12. 7. 20:33
반응형

Android 체크 가능 메뉴 항목


내 Android 앱에 다음과 같은 메뉴 레이아웃이 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/item1" 
          android:titleCondensed="Options"
          android:title="Highlight Options" 
          android:icon="@android:drawable/ic_menu_preferences" />

   <item android:id="@+id/item2" 
         android:titleCondensed="Persist"
         android:title="Persist" 
         android:icon="@android:drawable/ic_menu_preferences" 
         android:checkable="true" />
</menu>

내 문제는 Android 에뮬레이터에서 내 앱을 실행할 때 두 번째 메뉴 항목이 "선택 가능"한 것처럼 보이지 않는다는 것입니다. 항목에 녹색 체크 표시가 있어야합니다. 체크 가능함을 나타냅니다.

내가 뭘 잘못하고 있니?


레이아웃이 올바르게 보입니다. 단, 코드에서 메뉴 항목을 체크하고 체크 해제해야합니다.

로부터 문서 :

체크 가능한 항목이 선택되면 시스템은 각 항목 선택 콜백 메서드 (예 :)를 호출합니다 onOptionsItemSelected(). 체크 박스 또는 라디오 버튼은 상태를 자동으로 변경하지 않기 때문에 체크 박스의 상태를 설정해야합니다. 를 사용하여 항목의 현재 상태 (사용자가 선택하기 전의 상태)를 쿼리 isChecked()한 다음를 사용하여 선택 상태를 설정할 수 setChecked()있습니다.


다음 과 같이 요소에 items를 래핑합니다 group.

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="all">
        <item android:id="@+id/item1"
              android:titleCondensed="Options"
              android:title="Highlight Options"
              android:icon="@android:drawable/ic_menu_preferences">
        </item>
        <item android:id="@+id/item2"
              android:titleCondensed="Persist"
              android:title="Persist"
              android:icon="@android:drawable/ic_menu_preferences"
              android:checkable="true">
        </item>
    </group>
</menu>

로부터 안드로이드 문서 :

android : checkableBehavior 속성은 다음 중 하나를 허용합니다.

single-그룹에서 하나의 항목 만 확인할 수 있습니다 (라디오 버튼).

all-모든 항목을 확인할 수 있습니다 (확인란).

none-체크 할 수있는 항목이 없습니다.


다음 actionViewClass과 같이 체크 가능한 위젯 으로 설정하여 체크 가능한 메뉴 항목을 만들 수 있습니다.android.widget.CheckBox

res / menu / menu_with_checkable_menu_item.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_favorite"
        android:checkable="true"
        android:title="@string/action_favorite"
        app:actionViewClass="android.widget.CheckBox"
        app:showAsAction="ifRoom|withText" />
</menu>

스타일 actionLayout이 지정된 레이아웃으로 설정하면 체크 가능한 별표로 스타일을 지정할 수도 있습니다.android.widget.CheckBox

res / layout / action_layout_styled_checkbox.xml

<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
    style="?android:attr/starStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

res / menu / menu_with_checkable_star_menu_item.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_favorites"
        android:checkable="true"
        android:title="@string/action_favorites"
        app:actionLayout="@layout/action_layout_styled_checkbox"
        app:showAsAction="ifRoom|withText" />
</menu>

값을 설정하려면

menuItem.setChecked(true/false);

가치를 얻으려면

menuItem.isChecked()

MenuItem을 CheckBox로 캐스팅

CheckBox checkBox= (CheckBox) menuItem.getActionView();

여기에 대한 답변이 길고 복잡해 보이기 때문에 답변합니다. 여기에 정확한 Kotlin 코드가 있습니다.

상단에서 활동을 재정의하고 onMenuItemClick 함수를 재정의합니다. 메뉴를 열려면 버튼 클릭을 처리하는 함수가 있습니다.

확인 된 값을 보유하고 메뉴가 다시 생성 될 때 확인을 설정하는 배열 또는 목록이 있습니다.

참고 :이 코드는 메뉴를 열어 두지 않고 선택된 항목이 선택된 상태로 유지되도록합니다. 나는 스택 오버플로에 대한 많은 해결책이 있음을 지적 했으므로 원하는 것이 있다면 살펴보십시오.

class exampleActivity : AppCompatActivity(), PopupMenu.OnMenuItemClickListener {
   private var checkChecked = arrayListOf(false,false)
   //some code

  fun clickBTN(v: View){
        val popup = PopupMenu(this,v)
        popup.setOnMenuItemClickListener(this)
        popup.inflate(R.menu.yourmenufilename)
        //assuming you have 2 or more menu items
        popup.menu[0].isChecked = checkChecked[0]
        popup.menu[1].isChecked = checkChecked[1]
        popup.show()
  }

  override fun onMenuItemClick(item: MenuItem?): Boolean {
     when(item?.itemID){
        R.id.item0 -> {
                item.isChecked = !item.isChecked
                checkChecked[0] = item.isChecked
                return true
        }
        R.id.item1 -> {
                item.isChecked = !item.isChecked
                checkChecked[1] = item.isChecked
                return true
        }
  }
}

물론 XML에서는 버튼과 메뉴 설정이 있어야합니다. 메뉴 예시는 여기

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/item0"
        android:title="@string/hi"
        android:checkable="true"/>
    <item android:id="@+id/item1"
        android:title="@string/yo"
        android:checkable="true"/>
</menu>

이것은 테마에 따라 다를 수 있지만 내 메뉴에 확인란이 표시되지 않았습니다. 나는 이것을 발견 했다 :

Note: Menu items in the Icon Menu cannot display a checkbox or radio button. If you choose to make items in the Icon Menu checkable, then you must personally indicate the state by swapping the icon and/or text each time the state changes between on and off.


For Adding Menu items Programmatically,

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    menu.add("Item1").setActionView(R.layout.action_layout_checkbox).setCheckable(true);
    return super.onCreateOptionsMenu(menu);
}

res/layout /action_layout_checkbox.xml

<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

READ THIS

As has been said the "manual checking" is only the tip of the iceberg. It flashes the menu away so fast the users don't see anything happen and it is very counter intuitive, frustrating, and effectively utter crap. The REAL TASK (therefore) is allowing the check box event to be digested by the users mind.

Good news: this can be done and it does work and this is how you do it. @TouchBoarder had it best so I will copy his code. then develop it.

the idea is to detect if the checkbox is clicked, then (and only if that one is picked) slightly suppress the menu removal, add a timer for 500ms then close the menu, this give the "tick" animation of the checkbox time to run and creates the right "feel"

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_favorite"
        android:checkable="true"
        android:title="@string/action_favorite"
        app:actionViewClass="android.widget.CheckBox"
        app:showAsAction="ifRoom|withText" />
</menu>

then you make this method as usual, but you make sure you add all this extra bumpf

public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the bottom bar and the top bar (weird)
    BottomAppBar bottomBar = findViewById(R.id.bottom_app_bar_help);
    Menu bottomMenu = bottomBar.getMenu();
    getMenuInflater().inflate(R.menu.bottom_nav_menu, bottomMenu);
    for (int i = 0; i < bottomMenu.size(); i++) {
        bottomMenu.getItem(i).setOnMenuItemClickListener(item -> {
            if (item.getItemId()==R.id.action_favorite){
                item.setChecked(!item.isChecked());
                // Keep the popup menu open
                item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
                item.setActionView(new View(frmMain.this));
                item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
                    @Override
                    public boolean onMenuItemActionExpand(MenuItem item) {
                        final Handler handler = new Handler();
                        handler.postDelayed(() -> bottomMenu.close(), 500);
                        return false;
                    }

                    @Override
                    public boolean onMenuItemActionCollapse(MenuItem item) {
                        final Handler handler = new Handler();
                        handler.postDelayed(() -> bottomMenu.close(), 500);
                        return false;
                    }
                });
                return false;
            }
            else {
                return onOptionsItemSelected(item);
            }
        });
    }
    return true;
}

the other menu events are here

public boolean onOptionsItemSelected(MenuItem item) {
    // Bottom Bar item click
    try {
        switch (item.getItemId()) {
            case R.id.mnuExit:
                MenuClick(ClickType.LOGOUT);
                return true;

            case R.id.mnuList:
                MenuClick(ClickType.LIST);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return super.onOptionsItemSelected(item);
}

참고URL : https://stackoverflow.com/questions/6239163/android-checkable-menu-item

반응형