フラグメントに置き換えたアクティビティがあります。アクティビティは、アクティビティが表示するデータに関する追加情報を持つインテントを取りました。
アクティビティは、同じ動作を行うフラグメントの単なるラッパーになったので、タグを使用してXMLでフラグメントを宣言した場合、そのバンドルをフラグメントに取得するにはどうすればよいですか?
FragmentTransactionを使用してFragmentをViewGroupに入れると、Fragmentコンストラクターでこの情報を渡す機会が得られますが、フラグメントがXMLで定義されている状況については疑問に思っています。
アクティビティは、同じ動作を行うフラグメントの単なるラッパーになったので、タグを使用してXMLでフラグメントを宣言した場合、そのバンドルをフラグメントに取得するにはどうすればよいですか?
できません。
ただし、FragmentManager
でfindFragmentById()
を呼び出してフラグメント後のインフレーションを取得してから、フラグメントでメソッドを呼び出してデータを関連付けることを歓迎します。明らかにsetArguments()
にすることはできませんが、フラグメントは、他の何らかの手段(onSaveInstanceState()
、setRetainInstance(true)
などによって、データ自体を保持して構成の変更を保持することができます。 )。
カプセル化された方法ではありませんが、親アクティビティからバンドルを「プル」することになりました。
Bundle bundle = getActivity().getIntent().getExtras();
別のオプションは、フラグメントをXMLで宣言しないことです。あなたがしたいことではないことを知っています。ただし、次のようにビューで単純なレイアウトを宣言できます。
<LinearLayout
Android:id="@+id/fragment_container"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical" />
そして、Activity
クラスで、プログラムでフラグメントを使用してレイアウトを膨張させます。このように、引数を使用してパラメーターを渡すことができます。
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で宣言するほど簡潔で単純ではありませんが、フラグメントをより多く制御できるため、このアプローチに移行しました。
Bundleを渡すことはできませんが、XMLを介してフラグメントにパラメーター(または属性)を渡すことができます。
プロセスは Viewカスタム属性の定義方法 に似ています。 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()
}
}
etvoilá、フラグメント内のXML属性:)
制限事項:
Parcelable
を渡すことはできませんが、Android Attributes私が見る唯一の解決策は、データ交換チャネルとして引数を使用しないことです。代わりに、フラグメントを作成して、他の場所から必要な情報を取得します。コールバックして適切なアクティビティを取得し、一時ストレージメモリ、シングルトンオブジェクトなどを調べます。
役立つ可能性のある別の解決策は、関連しないオブジェクトが Otto のようにMediatorデザインパターンを介してメッセージを交換できるようにするフレームワークを採用することです。