我有一个被片段替换的活动。该活动采用了一个意图,该意图具有有关该活动应该显示哪些数据的一些额外信息。
现在,我的Activity只是一个Fragment的包装器,它可以完成相同的工作,如果我使用标记在XML中声明该片段,如何将其捆绑到Fragment上呢?
如果我要使用FragmentTransaction将Fragment放入ViewGroup中,我将有机会在Fragment构造函数中传递此信息,但是我想知道片段是在XML中定义的情况。
Answers:
现在,我的Activity只是一个Fragment的包装器,它可以完成相同的工作,如果我使用标记在XML中声明该片段,如何将其捆绑到Fragment上呢?
你不能
不过,欢迎您拨打findFragmentById()
您FragmentManager
检索片段后的通货膨胀,然后调用该片段的一些方法来与之相关联的数据。虽然显然是不能setArguments()
,您的片段可以安排守住数据本身过去通过一些其他方式的构造变化(onSaveInstanceState()
,setRetainInstance(true)
,等)。
setContentView()
才能使Fragments膨胀。但setContentView()
也将它们附加到Activity上,这使得调用它为时已晚setArguments()
。
setArguments()
通话时间。
您不能传递捆绑包(除非您以编程方式而不是通过XML来对片段进行膨胀),但是可以通过XML将参数(或属性)传递给片段。
该过程类似于您定义“视图”自定义属性的方式。除了AndroidStudio(当前)之外,该过程无法帮助您。
假设这是使用参数的片段(我将使用kotlin,但它也完全适用于Java):
class MyFragment: Fragment() {
// your fragment parameter, a string
private var screenName: String? = null
override fun onAttach(context: Context?) {
super.onAttach(context)
if (screenName == null) {
screenName = arguments?.getString("screen_name")
}
}
}
而您想做这样的事情:
<fragment
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/myFragment"
android:name="com.example.MyFragment"
app:screen_name="@string/screen_a"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
注意 app:screen_name="@string/screen_a"
要使其工作,只需将其添加到值文件中(fragment_attrs.xml
或选择所需的任何名称):
<!-- define your attribute name and type -->
<attr name="screen_name" format="string|reference"/>
<!-- define a bunch of constants you wanna use -->
<string name="screen_a" translatable="false">ScreenA</string>
<string name="screen_b" translatable="false">ScreeenB</string>
<!-- now define which arguments your fragment is gonna have (can be more then one) -->
<!-- the convention is "FragmentClassName_MembersInjector" -->
<declare-styleable name="MyFragment_MembersInjector">
<attr name="screen_name"/>
</declare-styleable>
差不多完成了,您只需要在片段中读取它,因此添加方法:
override fun onInflate(context: Context?, attrs: AttributeSet?, savedInstanceState: Bundle?) {
super.onInflate(context, attrs, savedInstanceState)
if (context != null && attrs != null && screenName == null) {
val ta = context.obtainStyledAttributes(attrs, R.styleable.MyFragment_MembersInjector)
if (ta.hasValue(R.styleable.MyFragment_MembersInjector_screen_name)) {
screenName = ta.getString(R.styleable.MyFragment_MembersInjector_screen_name)
}
ta.recycle()
}
}
等,片段中的XML属性:)
局限性:
Parcelable
,只能传递可以定义为Android属性的内容另一个选择是不在XML中声明该片段。我知道这不是您想要做的。但是,您可以在视图中声明一个简单的布局,如下所示:
<LinearLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
然后,在您的Activity
课堂上,以编程方式用片段填充布局。这样,您可以使用args传递参数。
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyFragment fragment = MyFragment.newInstance();
Bundle args = new Bundle();
args.putInt(Global.INTENT_INT_ROLE, 1);
fragment.setArguments(args);
fragmentTransaction.add(R.id.fragment_container, fragment, "MyActivity");
fragmentTransaction.commit();
这种方法不像在xml中声明那样干净简洁,但是我已经转向它,因为它为您提供了对片段的更多控制。
我知道答案为时已晚,但我认为有人需要它:)
只是在活动中覆盖 onAttachFragment()
@Override
public void onAttachFragment(Fragment fragment)
{
super.onAttachFragment(fragment);
if (fragment.getId() == R.id.frgBlank)
{
Bundle b = new Bundle();
b.putString("msg", "Message");
fragment.setArguments(b);
}
}
并在片段onCreateView方法中
Bundle b = getArguments();
if (b != null)
{
Toast.makeText(getBaseContext(), b.getString("msg"), Toast.LENGTH_SHORT).show();
}