Android Checkable Menu Item

后端 未结 9 1796
悲哀的现实
悲哀的现实 2020-12-01 00:59

I have the following menu layout in my Android app:




        
相关标签:
9条回答
  • 2020-12-01 01:40

    I've found that the best solution was to just use the onOptionsItemSelected() method as of my current API (27-28).

    @Override
       public boolean onOptionsItemSelected(MenuItem item) 
       {    
    
    //Copy from here...
           int itemId = item.getItemId();
    
           if(item.isChecked())                          
           { 
               if(R.id.edit_tile_checkbox == itemId)     //Individual checkbox logic
               {   /*TODO unchecked Action*/} 
               item.setChecked(false);                   //Toggles checkbox state.
           }
           else
           {
                if(R.id.edit_tile_checkbox == itemId)    //Individual checkbox logic
                {/*TODO checked Action*/}
                item.setChecked(true);                   //Toggles checkbox state.
           }
    //...To here in to your onOptionsItemSelected() method, then make sure your variables are all sweet.
    
           return super.onOptionsItemSelected(item);
       }
    

    I spent way to long on here for this answer. and for whatever reason, the answers above didn't help (I'm a returning newbie I probably mucked something up I'm sure). There could be a better way of doing this so helpful criticism is welcomed.

    0 讨论(0)
  • 2020-12-01 01:41

    You can create a checkable menu item by setting the actionViewClass to a checkable widget like 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>
    

    And you can can even style it to be a checkable star if you set actionLayout to a layout with a styled 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>
    

    To set the value

    menuItem.setChecked(true/false);
    

    To get the value

    menuItem.isChecked()
    

    Cast MenuItem to CheckBox

    CheckBox checkBox= (CheckBox) menuItem.getActionView();
    
    0 讨论(0)
  • 2020-12-01 01:46

    I have two items in the menu and set to checkable in menu.xml file like below

        <item
            android:id="@+id/A"
            android:title="A"
            app:showAsAction="never"
            android:checkable="true"/>
        <item
            android:id="@+id/B"
            android:title="B"
            app:showAsAction="never"
            android:checkable="true"/> 
    

    and logic for the menu checkboxes is below.

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    
        switch (item.getItemId()) {
            case R.id.A:
               //logic goes here
    
    
                if(item.isChecked())
                {
                 //logic is it is checked
                 item.setChecked(false);
                }
                else
                {
                   //logic is it is not checked
                    item.setChecked(true);
                }
                return true;
            case R.id.B:
             //logic for second checkbox goes here
    
    
                if(item.isChecked())
                {
                 //logic is it is checked
                    item.setChecked(false);
                }
                else
                {
                 //logic is it is not checked
                    item.setChecked(true);
                }
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    
    0 讨论(0)
  • 2020-12-01 01:52

    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);
    }
    
    0 讨论(0)
  • 2020-12-01 01:58

    Layout looks right. But you must check and uncheck menu item in code.

    From the documentation:

    When a checkable item is selected, the system calls your respective item-selected callback method (such as onOptionsItemSelected()). It is here that you must set the state of the checkbox, because a checkbox or radio button does not change its state automatically. You can query the current state of the item (as it was before the user selected it) with isChecked() and then set the checked state with setChecked().

    0 讨论(0)
  • 2020-12-01 01:58

    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" />
    
    0 讨论(0)
提交回复
热议问题