我有一个活动A,它启动活动B向它传递一些意图数据。活动B托管来自新导航架构组件的导航图。我想将该意图数据作为参数传递给startDestination片段如何做到这一点?
答案 0 :(得分:16)
TLDR:您必须手动夸大图表,将键/值添加到defaultArgs,然后在navController
上设置图表。
第1步
该文档告诉您在<fragment>
布局的Activity
标记中设置图表。类似的东西:
<fragment
android:id="@+id/navFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:graph="@navigation/nav_whatever"
app:defaultNavHost="true"
/>
删除设置graph=
。
第2步
在将显示NavHostFragment
的活动中,像这样夸大图表:
val navHostFragment = navFragment as NavHostFragment
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(R.navigation.nav_whatever)
其中navFragment
是你用XML给你的片段的id,如上所述。
第3步[至关重要!]
创建一个包以保存您要传递给startDestination
片段的参数,并将其添加到图表的默认参数中:
val bundle = Bundle()
// ...add keys and values
graph.addDefaultArguments(bundle)
第4步
在主持人navController
上设置图表:
navHostFragment.navController.graph = graph
答案 1 :(得分:9)
下面是官方文档中的Pass data to the start destination部分:
首先,构造一个包含数据的捆绑包:
val bundle = Bundle().apply {
putString(KEY, "value")
}
接下来,使用以下方法之一将Bundle传递到起始目的地:
如果要以编程方式创建NavHost
NavHostFragment.create(R.navigation.graph, bundle)
否则,您可以通过调用NavController.setGraph()
的以下重载之一来设置起始目标参数:
navHostFragment.navController.setGraph(R.navigation.graph, bundle)
然后,您应该使用Fragment.getArguments()
来检索起始目的地中的数据。
编辑:
您也可以使用FragmentArgs
来代替手动创建捆绑包,这样更加方便和安全:
navHostFragment.navController.setGraph(R.navigation.graph, MyFragmentArgs(arg).toBundle())
然后在该片段中,您可以按以下方式检索args:
private val args: PodFragmentArgs by navArgs()
确保您的片段在navigation.xml文件中具有参数元素:
<fragment
android:id="@+id/myFragment"
android:name="MyFragment"
android:label="fragment_my"
tools:layout="@layout/fragment_my">
<argument
android:name="argName"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
</fragment>
答案 2 :(得分:8)
它已在1.0.0-alpha07
中修复。 See detail.
该解决方案与Elliot Schrock的答案类似,但由官方API包装。
我们必须手动为NavHostFragment
或graph
充气
使用
NavHostFragment.create(R.navigation.graph, args)
或
navController.setGraph(R.navigation.graph, args)
参数是我们要传递到起始目标的数据。
答案 3 :(得分:6)
好的,感谢Google团队的Ian Lake,我找到了解决这个问题的方法。 假设您有一个活动A,它将使用一些意图数据启动活动B,并且您希望在startDestination中获取该数据,如果您使用安全参数,那么您可以在这里使用两个选项
class SomePlugin {
public __construct() {
add_action('wp_head', array(&$this, 'addMetatags'));
}
public function addMetatags() {
echo '<meta property="og:type" content="article" ';
}
}
从Intent中读取args。如果你不使用安全args,你可以从你自己使用的StartFragmentArgs.fromBundle(requireActivity().intent?.extras)
包中提取数据,这将返回你可以使用的Bundle而不是片段requireActivity().intent?.extras
方法。这就是我尝试它,一切正常。
答案 4 :(得分:2)
我认为1.0.0版本再次改变了这一点。 Google在官方文档中很好地隐藏了这些信息。或者至少我很难找到它,但是在迁移到导航组件指南中偶然发现了它。这里提到了如何将参数传递给起始目的地:
简而言之
findNavController(R.id.main_content) .setGraph(R.navigation.product_detail_graph, intent.extras)
val args by navArgs<ProductDetailsArgs>() val productId = args.productId
更新:Google表示确实缺少用于将参数传递给初始导航目标的官方文档。希望它会尽快作为导航组件文档的一部分添加。
答案 5 :(得分:1)
所以最后,我找到了解决此问题的方法。
在撰写此答案时,我正在使用Navigation 2.2.0-alpha01
如果要直接将某些数据作为主机活动的参数传递到起始目标,则需要在主机活动的onCreate()方法中手动设置主机的导航图,如下所示:
让您获得navController:
val navController by lazy { findNavController(R.id.<your_nav_host_id>) }
然后在主持人活动的onCreate()
val bundle = Bundle()
bundle.putString("some_argument", "some_value")
navController.setGraph(R.navigation.<you_nav_graph_xml>, bundle)
或者,如果您想将整个意图额外信息直接传递给startDestination:
navController.setGraph(R.navigation.<you_nav_graph_xml>, intent.extras)
由于intent.extras
仅返回Bundle
使用setGraph()方法设置navGraph时,应避免在以下位置设置app:NavGraph属性 NavHostFragment定义,因为这样做会导致膨胀 并设置两次导航图。
在startDestination片段中读取这些参数时,
如果您使用Safe Args Plugin(强烈建议使用),则在您的片段中:
private val args by navArgs<DummyFragmentArgs>()
Safe Args插件会通过将Args附加到您的片段名称来生成Args类。例如,如果您将片段称为DummyFragment
,那么安全Args会生成一个名为DummyFragmentArgs
其中navArgs<>
是Android KTX中定义的扩展功能
如果您未使用Android KTX,则可以获取args对象,例如:
val args = DummyFragmentArgs.fromBundle(arguments!!)
一旦获取了arguments对象,就可以简单地获取参数:
args.someArgument
请注意我们如何传递"some_argument"
作为参数,并使用安全参数将其读为someArgument
如果您不使用安全Args(虽然没有理由不使用它),则可以这样访问参数:
arguments?.getString("some_argument")
所有这些都记录在此处的“迁移到导航组件”文档中: https://developer.android.com/guide/navigation/navigation-migrate#pass_activity_destination_args_to_a_start_destination_fragment
答案 6 :(得分:0)
因此,对于仍在为此奋斗的人民。我找到了另一种无需使用Safe-Args的方法,也可以使用@Elliot的答案。
因此,可以说您在活动B中从活动A接收了一些参数,并且您的活动B具有片段startDestination,您正在像这样初始化Nav控制器:
navController = Navigation.findNavController(this, R.id.detailFragment);
从Nav Controller中,您可以访问以XML设置的图形,如下所示,您可以在defaultArguments中设置参数:
navController.getGraph().addDefaultArguments(extras);
注意:如果图形xml中已经存在键,这还将更新键的值
现在在您的Fragment中,您必须像这样从NavHostFragment中找到默认参数:
Bundle defaultArguments = NavHostFragment.findNavController(this).getGraph().getDefaultArguments();
,您将在那里找到值。我不知道为什么@Elliot认为这很关键,但是应该这样吗?
更新alpha09: 此版本不再支持addDefault参数,您必须使用NavArgument
答案 7 :(得分:0)
addDefaultArguments在最新版本的库中不再可用。我已经解决了这样的问题:
val navHostFragment = fragment_navigation_onboarding as NavHostFragment
val navController = navHostFragment.navController
val navInflater = navController.navInflater
val graph:NavGraph = navInflater.inflate(R.navigation.navigation_your_xml)
val model = Model()//you might get it from another activity
graph.addArgument("Data", NavArgument.Builder().setDefaultValue(model).build()) // This is where you pass the bundle data from Activity to StartDestination
navHostFragment.navController.graph = graph
答案 8 :(得分:0)
在阅读解决方案后,我做出了适合自己需求的解决方案, 此解决方案假定发送到托管此图的活动的数据
在开始目的地:
@Override
public void onAttach(Context context) {
super.onAttach(context);
// work around get get starting destination with activity bundle
userId = getActivity().getIntent().getIntExtra(KEY_USER_ID, -1);
}