Если я объявляю фрагмент в XML-макете, как мне передать ему пакет?
У меня есть активность, которую Я заменил фрагментом. Действие приняло намерение, которое имело некоторую дополнительную информацию о том, какие данные должно было отображать действие.
теперь, когда моя активность-это просто обертка вокруг фрагмента, который выполняет ту же работу, как мне получить этот пакет к фрагменту, если я объявлю фрагмент в XML с тегом?
Если бы я использовал FragmentTransaction, чтобы поместить фрагмент в ViewGroup, у меня был бы шанс передать эту информацию вместе в конструкторе фрагментов, но мне интересно о ситуации, когда фрагмент определяется в XML.
5 ответов:
теперь, когда моя активность-это просто обертка вокруг фрагмента, который выполняет ту же работу, как мне получить этот пакет к фрагменту, если я объявлю фрагмент в XML с тегом?
ты не можешь.
тем не менее, вы можете позвонить
findFragmentById()
наFragmentManager
чтобы получить фрагмент после инфляции, затем вызовите некоторый метод на фрагменте, чтобы связать с ним данные. Хотя, видимо, что не может бытьsetArguments()
, ваш фрагмент может организовать удержание сами данные после изменения конфигурации каким-либо другим способом (onSaveInstanceState()
,setRetainInstance(true)
и т. д.).
это не инкапсулированный способ, но я закончил тем, что" вытащил " пакет из родительской активности:
Bundle bundle = getActivity().getIntent().getExtras();
другой вариант-не объявлять фрагмент в XML. Я знаю, что это не совсем то, что вы хотите сделать. Однако вы можете объявить простой макет в своем представлении следующим образом:
<LinearLayout android:id="@+id/fragment_container" android:layout_width="fill_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, однако я перешел к нему, поскольку он дает вам намного больше контроль над фрагментом.
единственное решение, которое я вижу, это не использовать аргументы в качестве канала обмена данными. Вместо этого сделайте свой фрагмент, чтобы получить необходимую информацию из других источников. Перезвоните, чтобы получить соответствующую активность, обратитесь к памяти временного хранения, Одноэлементному объекту и т. д..
еще одно решение, которое может быть полезно, - это использовать фреймворки, которые позволяют несвязанным объектам обмениваться сообщениями через шаблон дизайна посредника, как Отто.
вы не можете передать пакет, но вы можете передать параметры (или, скорее, атрибуты) через 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 (currentScreen == null) { currentScreen = 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
o un nome a tua scelta):<!-- 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() } }
et voilá, ваши атрибуты XML в вашем фрагменте :)
ограничения:
- Android Studio (на данный момент) не автозаполняет такие аргументы в макете XML
- вы не можете пройти
Parcelable
но только то, что можно определить как Атрибутами Андроид