简体   繁体   English

有没有办法让浮动操作按钮根据导航主机中当前的片段来执行某些操作?

[英]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. MainActivity 中有一个浮动操作按钮,我想在几个片段中使用它。 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.因此,如果 HomeFragment 在 nav_host_fragment 中,我希望浮动操作按钮执行 thing1,如果 SecondFragment 在 nav_host_fragment 中,我希望浮动操作按钮执行 thing2。

If you create a new project in android studio and select basic activity you'll get the code I'm working with.如果您在 android 工作室和 select 基本活动中创建一个新项目,您将获得我正在使用的代码。 There is a MainActivity, two fragments (FirstFragment and SecondFragment) and a Navigation controller.有一个 MainActivity,两个片段(FirstFragment 和 SecondFragment)和一个 Navigation controller。 FirstFragment is displayed first, and this is where I want the action button to invoke method doThing1() .首先显示 FirstFragment,这是我希望操作按钮调用方法doThing1()的地方。 If you click on the button in this fragment it takes you to SecondFragment.如果您单击此片段中的按钮,它会将您带到 SecondFragment。 If you click the floating action button now, I would like the fab to invoke doThing2() How would I go about this?如果您现在单击浮动操作按钮,我希望晶圆厂调用doThing2()我将如何 go?

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.但这不起作用,因为findViewById没有找到工厂,我猜是因为它在片段自己的布局中搜索,而不是在主要活动中搜索。

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.我解决这个问题的唯一方法是在片段中获取对 MainActivity 的引用,从 MainActivity 调用一个公共方法并设置一个字段(设置为“first”或类似的东西),然后在 fab onClick 方法中检查这个变量设置为并根据此变量执行不同的方法。

So in onViewCreated :所以在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.然而,这似乎不是 go 的方法,我觉得这不是正确的方法。 Any ideas?有任何想法吗?

One of many possible solutions:许多可能的解决方案之一:

Kotlin: 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: 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您可以使用简单的 when(switch) 并检查最新的片段实例类型,我

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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