Home > OS >  Material Button Toggle Group doesn't switch switch state correctly after check() function
Material Button Toggle Group doesn't switch switch state correctly after check() function

Time:09-29

It seems like after calling check() function on Material Button Toggle Group object, there is one additional and unwanted call to addOnButtonCheckedListener. First one is desired and correct and second one is restoring check status to previous one, so the result is that nothing changes. Can somebody tell me what i did wrong?

XML layout:

<com.google.android.material.button.MaterialButtonToggleGroup
        android:id="@ id/chooseFilter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="10dp"
        app:singleSelection="true"
        app:selectionRequired="true"
        android:visibility="visible"
        android:importantForAutofill="no"
        app:checkedButton="@ id/weeklyButton">

        <Button
            style="?attr/materialButtonOutlinedStyle"
            android:id="@ id/singleButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Single"/>

        <Button
            style="?attr/materialButtonOutlinedStyle"
            android:id="@ id/weeklyButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Weekly"/>

        <Button
            style="?attr/materialButtonOutlinedStyle"
            android:id="@ id/yearlyButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Yearly"/>

    </com.google.android.material.button.MaterialButtonToggleGroup>

Java file OnCreateView:

@Override
    public View onCreateView(
            @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        view = inflater.inflate(R.layout.alarm_weekly_fragment, container, false);
        setUpToolbar(view);

        alarmRecView = view.findViewById(R.id.AlarmRecView);
        alarmadapter = new AlarmRecViewAdapter(requireActivity());
        alarmRecView.setAdapter(alarmadapter);
        alarmRecView.setLayoutManager(new LinearLayoutManager(view.getContext()));

        chooseFilter = view.findViewById(R.id.chooseFilter);

        chooseFilter.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() {
            @Override
            public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) {

                System.out.println("ID: " checkedId " "   isChecked);
                if(isChecked)
                {
                    switch(group.getCheckedButtonId())
                    {
                        case R.id.singleButton:
                            mode = 0;
                            break;

                        case R.id.weeklyButton:
                            mode = 1;
                            break;

                        case R.id.yearlyButton:
                            mode = 2;
                            break;
                    }
                    alarmadapter.setMode(mode);
                }
                System.out.println("Mode: " mode);
            }
        });

        seletionMenu = view.findViewById(R.id.selectionMenu);

        deleteSelectionButton = view.findViewById(R.id.deleteSelectionButton);
        deleteSelectionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            }
        });

        cancelSelectionButton = view.findViewById(R.id.cancelSelectionButton);
        cancelSelectionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                alarmadapter.editMode(false);
            }
        });

        switch(mode)
        {
            case 0:
                System.out.println("Single mode "   mode);
                chooseFilter.check(R.id.singleButton);
                break;

            case 1:
                System.out.println("Weekly mode "   mode);
                chooseFilter.check(R.id.weeklyButton);
                break;

            case 2:
                System.out.println("Yearly mode "   mode);
                chooseFilter.check(R.id.yearlyButton);
                break;

            default:
                break;
        }
        
        return view;
    }

I have variable mode which decides which button should be checked after creating activity. I set this value in other activity. I made some prints and discovered this behavior.

IDS:

singleButton - 2131231140

weeklyButton - 2131231257

yearlyButton - 2131231268

Default checked button is weeklyButton. After setting mode and coming back to this layout, I can see these prints:

2022-09-25 00:48:52.085 27553-27553/pp.project.nixieclock I/System.out: Single mode 0
2022-09-25 00:48:52.087 27553-27553/pp.project.nixieclock I/System.out: ID: 2131231140 true
2022-09-25 00:48:52.087 27553-27553/pp.project.nixieclock I/System.out: Mode: 0
2022-09-25 00:48:52.088 27553-27553/pp.project.nixieclock I/System.out: ID: 2131231257 false
2022-09-25 00:48:52.089 27553-27553/pp.project.nixieclock I/System.out: Mode: 0
2022-09-25 00:48:52.098 27553-27553/pp.project.nixieclock I/System.out: ID: 2131231140 false
2022-09-25 00:48:52.098 27553-27553/pp.project.nixieclock I/System.out: Mode: 0
2022-09-25 00:48:52.098 27553-27553/pp.project.nixieclock I/System.out: ID: 2131231257 true
2022-09-25 00:48:52.098 27553-27553/pp.project.nixieclock I/System.out: Mode: 1

First 5 lines are the ones what I expect and then there is an additional mentioned call restoring button check states to previous ones.

One thing to mention is it only happens when coming back to this layout from another. On first start, default check state is correct.

Android Api 31

material desing: 1.6.1

CodePudding user response:

Okay, it seems like problem is gone. The solution was to move adding listener to onResume() function.

@Override
    public void onResume() {
        super.onResume();
        chooseFilter.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() {
            @Override
            public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) {
                System.out.println("Listener: " this);
                System.out.println("Group: " group);
                System.out.println("ID: " checkedId " "   isChecked);
                if(isChecked)
                {
                    switch(checkedId)
                    {
                        case R.id.singleButton:
                            mode = 0;
                            break;

                        case R.id.weeklyButton:
                            mode = 1;
                            break;

                        case R.id.yearlyButton:
                            mode = 2;
                            break;
                    }
                    alarmadapter.setMode(mode);
                }
                System.out.println("Mode in listener: " mode);
            }
        });

        switch(mode)
        {
            case 0:
                chooseFilter.check(R.id.singleButton);
                break;

            case 1:
                chooseFilter.check(R.id.weeklyButton);
                break;

            case 2:
                chooseFilter.check(R.id.yearlyButton);
                break;

            default:
                break;
        }
    }
  • Related