Moamen Mohamed
Moamen Mohamed

Reputation: 325

Disappearing fab icon on navigation fragment change

I have a bottom navigation view with 3 items which navigate to 3 different fragments (fragments are created only once and their instances are saved in mainactivity's onSavedInstanceState()) and on top of it a floating action button.

We want to change the icon drawable for the fab when each fragment is visited we tried both setImageResource() and .setImageDrawable() on the fab in a switch case when each bottom navigation icon is picked.

/**
 * used to handle switching between fragments when a new navigation item is selected
 */
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    switch (item.getItemId()) {
        case R.id.nav_tasks:
            .........
    loadFragment(tasksFragment);
            mFab.setOnClickListener(mFabClickListenerTasks);
            mFab.setImageDrawable(getResources().getDrawable(R.drawable.ic_add_task));
    //2 tabs in 1 fragment
            if (mTabLayout.getSelectedTabPosition() == 1)
                mFab.hide();
            else mFab.show();
            break;
        case R.id.nav_employees:
            .......
            loadFragment(employeesFragment);
            mFab.setOnClickListener(mFabClickListenerEmployees);
            mFab.setImageDrawable(getResources().getDrawable(R.drawable.ic_add_employee2));
            mFab.show();


            break;
        case R.id.nav_departments:
            .......
            loadFragment(departmentsFragment);
            mFab.setOnClickListener(mFabClickListenerDepartments);
           mFab.setImageDrawable(getResources().getDrawable(R.drawable.ic_add_department));
            mFab.show();


            break;

    }

    item.setChecked(true);

    return true;
}
void loadFragment(Fragment fragment) {
    if (activeFragment == fragment)
        return;

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.hide(activeFragment).show(fragment);
    activeFragment = fragment;
    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

    if (activeFragment instanceof TasksFragment)
        mFab.setImageResource(R.drawable.ic_add_task);
    else if(activeFragment instanceof DepartmentsFragment)
        mFab.setImageResource(R.drawable.ic_add_department);
    else if(activeFragment instanceof EmployeesFragment)
        mFab.setImageResource(R.drawable.ic_add_employee2);

    transaction.commit();
}

The 3 fragments are mainly 3 recycler views, we also hide the fab when recyclerview scrolls.

The fab drawable will be set correctly when traversing the fragments from the bottom navigation , but in any fragment when we scroll it saves this state to return to it afterwards.

This removes the fab drawable when going to another fragment and leaves the fab empty with no icon drawable. How can we solve this ?

Upvotes: 13

Views: 2513

Answers (4)

Alex Styl
Alex Styl

Reputation: 4219

The issue seems to be fixed in Material Components 1.1.0, but it is currently in alpha.

Tried with:

implementation com.google.android.material:material:1.1.0-alpha10

Upvotes: 1

Ziad Halabi
Ziad Halabi

Reputation: 866

I am having the same issue when the activity goes into onPause then onResume I was calling setImageResource on the FloatingActionButton. The FAB icon was disappearing. My solution was to call the following right after setImageResource

mFloatingActionButton.hide();        
mFloatingActionButton.show();

Upvotes: 20

MrStahlfelge
MrStahlfelge

Reputation: 1791

It's a bug in the FloatingActionButton class: When calling show(), imageMatrixScale is set to 0. A call to setImageResource() then just displays blank. It works before calling show().

The bug has been introduced in the design lib 28.0.0, it was working on v27.1.1. Downgrade to 27.1.1

EDIT: Google Issuetracker

Upvotes: 14

Paweł Galiński
Paweł Galiński

Reputation: 91

In my case downgrading design lib wasn't posible for many reasons. MrStahlfelge's answer helped me to find solution:

public class MyNewFab  extends FloatingActionButton {

    private Matrix imageMatrix;

    ...  

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        imageMatrix = getImageMatrix();
    }

    @Override
    public void setImageResource(int resId) {
        super.setImageResource(resId);
        setImageMatrix(imageMatrix);
    }
}

This works for me. Hope it will help the others facing same problem.

Upvotes: 4

Related Questions