Intereting Posts
Событие touchhend не работает на Android Просмотр OpenGL внутри макета Android отправит изображение и сохранит URL Как создать диалог, который будет заполнен горизонтальным размером Ошибка: GooglePlayServicesUtil: произошла внутренняя ошибка. Для получения подробной информации см. Журналы. Как это исправить? После ontouch он не может пойти ondrag на Android Конвертировать PNG-изображения в 9 патчей в Android Studio Динамически добавлять необязательные параметры в запросы API Throwing OutOfMemoryError "pthread_create (стек 1040 КБ) не удалось: повторите попытку" при выполнении асинхронных сообщений с использованием Volley Android-приложение против активности Импорт проекта Android в ADT Eclipse из github Загрузить фотографию в Facebook с Android Android SDK в Android Почему элемент «Фрагмент» в макете Android написан с нижним регистром «f»? Расположение координатора с панелью инструментов в фрагментах или действиях Android SeekBar для контроля прогресса MediaPlayer

Лучшая практика для вложенных фрагментов в Android 4.0, 4.1 (<4.2) без использования библиотеки поддержки

Я пишу приложение для 4,0 и 4,1 таблеток, для которых я не хочу использовать библиотеки поддержки (если не нужно), но 4.x api только поэтому.

Поэтому моя целевая платформа очень хорошо определена как:> = 4.0 и <= 4.1

Приложение имеет многоуровневую компоновку (два фрагмента, один маленький слева, один фрагмент контента справа) и панель действий с вкладками.

Аналогично этому:

Введите описание изображения здесь

Щелчок на вкладке на панели действий изменяет «внешний» фрагмент, а внутренний фрагмент – фрагмент с двумя вложенными фрагментами (1. небольшой фрагмент левого списка, фрагмент с широким содержимым).

Теперь я задаюсь вопросом, что лучше всего заменить фрагменты и особенно вложенные фрагменты. ViewPager является частью библиотеки поддержки, для этого класса нет альтернативы 4.x. Похоже, что я «устарел» в своем смысле. – http://developer.android.com/reference/android/support/v4/view/ViewPager.html

Затем я прочитал примечания к выпуску для Android 4.2, касающиеся ChildFragmentManager , что было бы неплохо, но я нацелен на 4.0 и 4.1, поэтому это тоже нельзя использовать.

ChildFragmentManager доступен только в 4.2

  • http://developer.android.com/about/versions/android-4.2.html#NestedFragments
  • http://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager ()

К сожалению, вряд ли есть хорошие примеры, показывающие лучшие практики использования фрагментов без поддержки библиотеки даже в руководствах для разработчиков Android; И особенно ничего относительно вложенных фрагментов.

Поэтому мне интересно: просто ли можно писать 4.1 приложения с вложенными фрагментами без использования библиотеки поддержки и всего, что с ней связано? (Нужно использовать FragmentActivity вместо Fragment и т. Д.?) Или что было бы лучшей практикой?


Проблема, которую я сейчас имею в разработке, заключается именно в этом утверждении:

  • http://developer.android.com/about/versions/android-4.2.html#NestedFragments

Библиотека поддержки Android теперь также поддерживает вложенные фрагменты, поэтому вы можете реализовать вложенные фрагменты на Android 1.6 и выше.

Примечание. Вы не можете раздувать макет во фрагмент, если этот макет включает <fragment> . Вложенные фрагменты поддерживаются только при динамическом добавлении к фрагменту.

Потому что я ставлю определение вложенных фрагментов в XML, что, по-видимому, вызывает ошибку, например:

 Caused by: java.lang.IllegalArgumentException: Binary XML file line #15: Duplicate id 0x7f090009, tag frgCustomerList, or parent id 0x7f090008 with another fragment for de.xyz.is.android.fragment.CustomerListFragment_ 

На данный момент я заключу для себя: даже на 4.1, когда я даже не хочу нацеливаться на платформу 2.x, вложенные фрагменты, как показано на скриншоте, невозможны без поддержки библиотеки.

(Это может быть скорее вики-запись, чем вопрос, но, возможно, кому-то еще это удалось).

Обновить:

Полезный ответ: Фрагмент внутри фрагмента

Solutions Collecting From Web of "Лучшая практика для вложенных фрагментов в Android 4.0, 4.1 (<4.2) без использования библиотеки поддержки"

Ограничения

Таким образом, вложенные фрагменты внутри другого фрагмента невозможно с помощью xml независимо от используемой вами версии FragmentManager .

Поэтому вам нужно добавить фрагменты через код, это может показаться проблемой, но в конечном итоге ваши макеты суперэкраничны.

Итак, вложенность без использования getChildFragmentManger ? Суть в childFragmentManager заключается в том, что он откладывает загрузку до завершения предыдущей транзакции фрагмента. И, конечно же, это было естественно поддержано в 4.2 или в библиотеке поддержки.

Вложение без ChildManager – решение

Решение, конечно! Я занимаюсь этим уже давно (с ViewPager объявления ViewPager ).

Смотри ниже; Это Fragment который откладывает загрузку, поэтому Fragment могут быть загружены внутри него.

Его довольно простой, Handler – действительно действительно удобный класс, эффективно обработчик ждет пространства для выполнения в основном потоке после завершения транзакции текущего фрагмента (поскольку фрагменты мешают пользовательскому интерфейсу, который они запускают в основном потоке).

 // Remember this is an example, you will need to modify to work with your code private final Handler handler = new Handler(); private Runnable runPager; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) return inflater.inflate(R.layout.frag_layout, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); runPager = new Runnable() { @Override public void run() { getFragmentManager().beginTransaction().addFragment(R.id.frag_container, MyFragment.newInstance()).commit(); } }; handler.post(runPager); } /** * @see android.support.v4.app.Fragment#onPause() */ @Override public void onPause() { super.onPause(); handler.removeCallbacks(runPager); } 

Я бы не стал считать это «лучшей практикой», но у меня есть живые приложения, использующие этот хак, и у меня еще есть проблемы с ним.

Я также использую этот метод для встраивания пейджеров просмотров – https://gist.github.com/chrisjenx/3405429

Лучший способ сделать это в pre-API 17 – это не делать этого вообще. Попытка реализовать это поведение вызовет проблемы. Однако это не означает, что это невозможно подделать убедительно, используя текущий API 14. Что я сделал, так это следующее:

1 – посмотреть связь между фрагментами http://developer.android.com/training/basics/fragments/communicating.html

2 – переместите макет xml FrameLayout из существующего фрагмента в макет действия и спрячьте его, указав высоту 0:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent"> <FrameLayout android:id="@+id/content" android:layout_width="300dp" android:layout_height="match_parent" /> <FrameLayout android:id="@+id/lstResults" android:layout_width="300dp" android:layout_height="0dp" android:layout_below="@+id/content" tools:layout="@layout/treeview_list_content"/> <FrameLayout android:id="@+id/anomalies_fragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_toRightOf="@+id/content" /> 

3 – Внедрить интерфейс в родительском фрагменте

  OnListener mCallback; // Container Activity must implement this interface public interface OnListener { public void onDoSomethingToInitChildFrame(/*parameters*/); public void showResults(); public void hideResults(); } @Override public void onAttach(Activity activity) { super.onAttach(activity); // This makes sure that the container activity has implemented // the callback interface. If not, it throws an exception try { mCallback = (OnFilterAppliedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnListener"); } } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mCallback.showResults(); } @Override public void onPause() { super.onPause(); mCallback.hideResults(); } public void onClickButton(View view) { // do click action here mCallback.onDoSomethingToInitChildFrame(/*parameters*/); } 

4 – Внедрить интерфейс в родительской деятельности

Public class YourActivity extends Activity реализует yourParentFragment.OnListener {

 public void onDoSomethingToInitChildFrame(/*parameters*/) { FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment childFragment = getFragmentManager().findFragmentByTag("Results"); if(childFragment == null) { childFragment = new yourChildFragment(/*parameters*/); ft.add(R.id.lstResults, childFragment, "Results"); } else { ft.detach(childFragment); ((yourChildFragment)childFragment).ResetContent(/*parameters*/); ft.attach(childFragment); } ft.commit(); showResultsPane(); } public void showResults() { FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment childFragment = getFragmentManager().findFragmentByTag("Results"); if(childFragment != null) ft.attach(childFragment); ft.commit(); showResultsPane(); } public void showResultsPane() { //resize the elements to show the results pane findViewById(R.id.content).getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; findViewById(R.id.lstResults).getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; } public void hideResults() { //resize the elements to hide the results pane findViewById(R.id.content).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT; findViewById(R.id.lstResults).getLayoutParams().height = 0; FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment childFragment = getFragmentManager().findFragmentByTag("Results"); if(childFragment != null) ft.detach(childFragment); ft.commit(); } 

}

5 – Наслаждайтесь, с помощью этого метода вы получаете те же функции жидкости, что и с функцией getChildFragmentManager () в пред-API-интерфейсе 17. Как вы, возможно, заметили, что дочерний фрагмент больше не является дочерним элементом родительского фрагмента, а теперь дочерним элементом этой деятельности, этого действительно избежать нельзя.

Я должен был решить эту проблему из-за комбинации NavigationDrawer, TabHost и ViewPager, которые имели сложности с использованием библиотеки поддержки из-за TabHost. И тогда мне также пришлось поддерживать min API JellyBean 4.1, поэтому использование вложенных фрагментов с помощью getChildFragmentManager не было вариантом.

Поэтому моя проблема может быть переделана …

  TabHost (для верхнего уровня)
 + ViewPager (только для одного из фрагментов с вкладками верхнего уровня)
 = Необходимость в вложенных фрагментах (которые JellyBean 4.1 не поддерживает) 

Моим решением было создать иллюзию вложенных фрагментов без фактического вложения фрагментов. Я сделал это, используя основной способ использования TabHost AND ViewPager для управления двумя видами Sibling, управление видимостью которых осуществляется путем переключения layout_weight между 0 и 1.

 //Hide the fragment used by TabHost by setting height and weight to 0 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 0); mTabHostedView.setLayoutParams(lp); //Show the fragment used by ViewPager by setting height to 0 but weight to 1 lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 1); mPagedView.setLayoutParams(lp); 

Это фактически позволило моему поддельному «Nested Fragment» работать как независимое представление, если я вручную управлял соответствующими весами макета.

Вот мой activity_main.xml:

 <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.ringofblades.stackoverflow.app.MainActivity"> <TabHost android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@android:id/tabcontent" android:background="@drawable/background_image" android:layout_width="match_parent" android:layout_weight="0.5" android:layout_height="0dp"/> <android.support.v4.view.ViewPager xmlns:tools="http://schemas.android.com/tools" android:id="@+id/pager" android:background="@drawable/background_image" android:layout_width="match_parent" android:layout_weight="0.5" android:layout_height="0dp" tools:context="com.ringofblades.stackoverflow.app.MainActivity"> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.v4.view.ViewPager> <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </TabHost> <fragment android:id="@+id/navigation_drawer" android:layout_width="@dimen/navigation_drawer_width" android:layout_height="match_parent" android:layout_gravity="start" android:name="com.ringofblades.stackoverflow.app.NavigationDrawerFragment" tools:layout="@layout/fragment_navigation_drawer" /> </android.support.v4.widget.DrawerLayout> 

Обратите внимание, что «@ + id / pager» и «@ + id / container» являются братьями и сестрами с «android: layout_weight =« 0.5 »и« android: layout_height = »0dp». Это так, что я вижу его в предварительном просмотре для любого размера экрана. Во всяком случае, их веса будут управляться кодом во время выполнения.

Основываясь на @ Chris.Jenkins, ответьте, это решение, которое хорошо работает для меня, для удаления фрагментов (ов) во время событий жизненного цикла (которые имеют тенденцию бросать IllegalStateExceptions). Это использует комбинацию подхода Handler и проверку Activity.isFinishing () (в противном случае это вызовет ошибку для «Не удается выполнить это действие после onSaveInstanceState).

 import android.app.Activity; import android.os.Handler; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; public abstract class BaseFragment extends Fragment { private final Handler handler = new Handler(); /** * Removes the {@link Fragment} using {@link #getFragmentManager()}, wrapped in a {@link Handler} to * compensate for illegal states. * * @param fragment The {@link Fragment} to schedule for removal. */ protected void removeFragment(@Nullable final Fragment fragment) { if (fragment == null) return; final Activity activity = getActivity(); handler.post(new Runnable() { @Override public void run() { if (activity != null && !activity.isFinishing()) { getFragmentManager().beginTransaction() .remove(fragment) .commitAllowingStateLoss(); } } }); } /** * Removes each {@link Fragment} using {@link #getFragmentManager()}, wrapped in a {@link Handler} to * compensate for illegal states. * * @param fragments The {@link Fragment}s to schedule for removal. */ protected void removeFragments(final Fragment... fragments) { final FragmentManager fragmentManager = getFragmentManager(); final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); for (Fragment fragment : fragments) { if (fragment != null) { fragmentTransaction.remove(fragment); } } final Activity activity = getActivity(); handler.post(new Runnable() { @Override public void run() { if (activity != null && !activity.isFinishing()) { fragmentTransaction.commitAllowingStateLoss(); } } }); } } 

Применение:

 class MyFragment extends Fragment { @Override public void onDestroyView() { removeFragments(mFragment1, mFragment2, mFragment3); super.onDestroyView(); } } 

Хотя у ОП могут быть особые обстоятельства, которые мешают ему использовать Библиотеку поддержки, большинство людей должны ее использовать. Документация для Android рекомендует, и это сделает ваше приложение доступным для самой широкой аудитории.

В моем более полном ответе я привел пример, демонстрирующий использование вложенных фрагментов в библиотеке поддержки.

Введите описание изображения здесь