Search code examples
androidandroid-actionbarandroid-toolbarandroid-menu

Switch onCheckedChangedListner not registering clicks inside toolbar menu


I have a switch in my app toolbar to provide an option to the user to change the language.

app toolbar

When I am using the switch, the onCheckedChanged method is not working. Further, it looks to me that onOptionsItemSelected is also not being hit as I don't see any log message on the screen.

Please note that the app is not crashing when I use the switch.

The clicks on options present inside the overflow menu are working properly. I am getting the log in those cases.

Switch aSwitch;
RelativeLayout langSwitch;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

context = this;

// Removed non relevant code here. 
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    Log.d("tag_id",String.valueOf(id));
    langSwitch = findViewById(R.id.app_bar_switch);

    aSwitch = langSwitch.findViewById(R.id.langSwitch);

    aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            if (!b){
                //Language1 code
                Toast.makeText(context,"Language1 Selected",Toast.LENGTH_SHORT).show();
            }else{
                //Language2 code
                Toast.makeText(context,"Language2 Selected",Toast.LENGTH_SHORT).show();
            }
        }
    });

    if (id == R.id.action_settings) {
        return true;
    }

    if (id == R.id.savedPost){
        Intent intent = new Intent(this,SavedPost.class);
        startActivity(intent);
    }


    return super.onOptionsItemSelected(item);
}

Below is my menu_main.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.app_name.android.app_name.MainActivity">
<item
    android:id="@+id/app_bar_switch"
    android:orderInCategory="2"
    android:title=""
    app:actionLayout="@layout/switch_item"
    app:showAsAction="always" />
<item
    android:id="@+id/action_settings"
    android:orderInCategory="100"
    android:title="@string/action_settings"
    app:showAsAction="never" />
<item
    android:id="@+id/savedPost"
    android:checkable="false"
    android:orderInCategory="4"
    android:title="@string/saved_post" />

</menu>

This is my layout file for switch item.

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

<Switch
    android:id="@+id/langSwitch"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:textOff="@string/switch_text_off"
    android:textOn="@string/switch_text_on"
    android:focusable="true"
    android:clickable="true"/>

</RelativeLayout>

Additional information.

If I create another menu item (code below) with showAsAction 'always' and click on this once, now when I use the switch the Toast message comes. I am clueless here as to why is it not happening for the first time. Also, how do I make it work without this menu item.

<item
    android:id="@+id/english"
    android:orderInCategory="3"
    android:title="@string/switch_text_on"
    app:showAsAction="always" />

Solution

  • To inflate an external layout over ActionBar that seems to first creating a view that holds your ChildView for your layout

    like Example

    RelativeLayout item = (RelativeLayout)findViewById(R.id.item);
    View child = getLayoutInflater().inflate(R.layout.child, null);
    item.addView(child);
    

    Try this in your code

    Switch aSwitch;
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    
       getMenuInflater().inflate(R.menu.menu_main, menu);
       View sw = menu.findItem(R.id.app_bar_switch).getActionView();
       aSwitch = (Switch) sw.findViewById(R.id.langSwitch);
    
       aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    
      @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            if (!b){
                //Language1 code
                Toast.makeText(context,"Language1 Selected",Toast.LENGTH_SHORT).show();
            }else{
                //Language2 code
                Toast.makeText(context,"Language2 Selected",Toast.LENGTH_SHORT).show();
            }
        }
    });
    
        return true;
    }