Если я объявляю фрагмент в XML-макете, как мне передать ему пакет?


У меня есть активность, которую Я заменил фрагментом. Действие приняло намерение, которое имело некоторую дополнительную информацию о том, какие данные должно было отображать действие.

теперь, когда моя активность-это просто обертка вокруг фрагмента, который выполняет ту же работу, как мне получить этот пакет к фрагменту, если я объявлю фрагмент в XML с тегом?

Если бы я использовал FragmentTransaction, чтобы поместить фрагмент в ViewGroup, у меня был бы шанс передать эту информацию вместе в конструкторе фрагментов, но мне интересно о ситуации, когда фрагмент определяется в XML.

5 52

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 но только то, что можно определить как Атрибутами Андроид