简体   繁体   中英

Is there a way to have a floating action button do something dependant on which fragment is currently in nav host?

I'm having some trouble with a single activity project. There is a floating action button in MainActivity that I want to use in several fragments. So if HomeFragment is in the nav_host_fragment, I want the floating action button to do thing1, and if SecondFragment is in nav_host_fragment, I want the floating action button to do thing2.

If you create a new project in android studio and select basic activity you'll get the code I'm working with. There is a MainActivity, two fragments (FirstFragment and SecondFragment) and a Navigation controller. FirstFragment is displayed first, and this is where I want the action button to invoke method doThing1() . If you click on the button in this fragment it takes you to SecondFragment. If you click the floating action button now, I would like the fab to invoke doThing2() How would I go about this?

I've tried

In the fragments


   public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
           super.onViewCreated(view, savedInstanceState);`
   
   view.findViewById(R.id.button_first).setOnClickListener(v -> {
   doThing1();
    });

But this doesn't work because findViewById doesn't find the fab, I guess because it's searching in the fragments own layout and not in the main activity.

The only way I solved this is by getting a reference to MainActivity in the fragment, invoke a public method from MainActivity and set a field (to "first" or something similar) and then in the fab onClick method check what this variable is set to and execute different methods dependant on this variable.

So in onViewCreated :

MainActivity reference = (MainActivity) getActivity();
assert reference != null;
reference.changeFabActionTo("thing2");

And then in the click listener

fab.setOnClickListener(view -> {
                if(whichFragmentClick.equals("thing1")) {
                    // doThing1()}
                if(whichFragmentClick.equals("thing2")) {
                    // doThing2()}
            });

This doesn't seem like the way to go about this however, and I feel like this isn't the proper way. Any ideas?

One of many possible solutions:

Kotlin:

class MainActivity : AppCompatActivity() {
  private lateinit var floatingButton: FloatingActionButton

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(findViewById(R.id.toolbar))

    floatingButton = findViewById(R.id.fab)
    floatingButton.setOnClickListener { _ ->
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment)
        val visibleFragment = navHostFragment?.childFragmentManager?.fragments?.first()

        when (visibleFragment != null) {
          true -> {
            when (visibleFragment::class.java) {
              FirstFragment::class.java -> doStuff1()
              SecondFragment::class.java -> doStuff2()
              else -> doSomethingElse()
            }
          }
          false -> {
            println("<<<DEV>>> visibleFragment is not defined")
          }
        }
      }
  }

  private fun doStuff1() {
    println("<<<DEV>>> Fragment 1 is visible")
  }

  private fun doStuff2() {
    println("<<<DEV>>> Fragment 2 is visible")
  }

  private fun doSomethingElse() {
    println("<<<DEV>>> Fragment is undefined")
  }

  override fun onCreateOptionsMenu(menu: Menu): Boolean {
    // Inflate the menu; this adds items to the action bar if it is present.
    menuInflater.inflate(R.menu.menu_main, menu)
    return true
  }

  override fun onOptionsItemSelected(item: MenuItem): Boolean {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    return when (item.itemId) {
      R.id.action_settings -> true
      else -> super.onOptionsItemSelected(item)
    }
  }
}

Java:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FloatingActionButton fab = findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Fragment navHostFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);

            if (navHostFragment instanceof NavHostFragment) {
                Fragment visibleFragment = navHostFragment.getChildFragmentManager().getFragments().get(0);

                if (visibleFragment instanceof FirstFragment) {
                    doStuff1();
                } else if (visibleFragment instanceof  SecondFragment) {
                    doStuff2();
                } else {
                    doSomethingElse();
                }
            }
        }
    });
}

public static void doStuff1() {
    System.out.println("<<<DEV>> Fragment 1 is visible");
}

public static void doStuff2() {
    System.out.println("<<<DEV>> Fragment 2 is visible");
}

public static void doSomethingElse() {
    System.out.println("<<<DEV>>> Fragment is undefined");
}

@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) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

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

    return super.onOptionsItemSelected(item);
}
}

You can have simple when(switch) and check latest fragment instance type, i

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM