- Фрагменты
- Основные классы
- FragmentManager
- Методы транзакции
- Аргументы фрагмента
- Управление стеком фрагментов
- Интеграция Action Bar/Options Menu
- Связь между фрагментом и активностью
- Cannot convert from android.support.v4.app.Fragment to android.app.Fragment
- Android Studio and android.support.v4.app.Fragment: cannot resolve symbol
- 24 Answers 24
- DID NOT WORK:
- SOLUTION:
Фрагменты
Существует два основных подхода в использовании фрагментов.
Первый способ основан на замещении родительского контейнера. Создаётся стандартная разметка и в том месте, где будут использоваться фрагменты, размещается контейнер, например, FrameLayout. В коде контейнер замещается фрагментом. При использовании подобного сценария в разметке не используется тег fragment, так как его нельзя менять динамически. Также вам придётся обновлять ActionBar, если он зависит от фрагмента. Здесь показан такой пример.
Второй вариант — используются отдельные разметки для телефонов и планшетов, которые можно разместить в разных папках ресурсов. Например, если в планшете используется двухпанельная разметка с двумя фрагментами на одной активности, мы используем эту же активность для телефона, но подключаем другую разметку, которая содержит один фрагмент. Когда нам нужно переключиться на второй фрагмент, то запускаем вторую активность.
Второй подход является наиболее гибким и в целом предпочтительным способом использования фрагментов. Активность проверяет в каком режиме (свои размеры) он запущен и использует разную разметку из ресурсов. Графически это выглядит следующим образом.
Основные классы
Сами фрагменты наследуются от androidx.fragment.app.Fragment. Существует подклассы фрагментов: ListFragment, DialogFragment, PreferenceFragment, WebViewFragment и др. Не исключено, что число классов будет увеличиваться, например, появился ещё один класс MapFragment.
Для взаимодействия между фрагментами используется класс android.app.FragmentManager — специальный менеджер по фрагментам.
Как в любом офисе, спецманагер не делает работу своими руками, а использует помощников. Например, для транзакций (добавление, удаление, замена) используется класс-помощник android.app.FragmentTransaction.
Для сравнения приведу названия классов из библиотеки совместимости:
- android.support.v4.app.FragmentActivity
- android.support.v4.app.Fragment
- android.support.v4.app.FragmentManager
- android.support.v4.app.FragmentTransaction
Как видите, разница в одном классе, который я привёл первым. Он используется вместо стандартного Activity, чтобы система поняла, что придётся работать с фрагментами. На данный момент студия создаёт проект на основе ActionBarActivity, который является подклассом FragmentActivity.
В одном приложении нельзя использовать новые фрагменты и фрагменты из библиотеки совместимости.
В 2018 году Гугл объявила фрагменты из пакета androd.app устаревшими. Заменяйте везде на версию из библиотеки совместимости. В 2020 году уже используют пакет androidx.fragment.app.
В версии Support Library 27.1.0 появились новые методы requireActivity() и requireContext(), которые пригодятся при написании кода, когда требуется наличие активности и нужно избежать ошибки на null.
Общий алгоритм работы с фрагментами будет следующим:
У каждого фрагмента должен быть свой класс. Класс наследуется от класса Fragment или схожих классов, о которых говорилось выше. Это похоже на создание новой активности или нового компонента.
Также, как в активности, вы создаёте различные методы типа onCreate() и т.д. Если фрагмент имеет разметку, то используется метод onCreateView() — считайте его аналогом метода setContentView(), в котором вы подключали разметку активности. При этом метод onCreateView() возвращает объект View, который является корневым элементом разметки фрагмента.
Разметку для фрагмента можно создать программно или декларативно через XML.
Создание разметки для фрагмента ничем не отличается от создания разметки для активности. Вот отрывок кода из метода onCreateView():
Глядя на этот код, вы должные понять, что фрагмент использует разметку из файла res/layout/first_fragment.xml, которая содержит кнопку с идентификатором android:id=»@+id/button_first». Здесь также прослеживается сходство с подключением компонентов в активности. Обратите внимание, что перед методом findViewById() используется view, так как этот метод относится к компоненту, а не к активности, как мы обычно делали в программах, когда просто опускали имя активности. Т.е. в нашем случае мы ищем ссылку на кнопку не среди разметки активности, а внутри разметки самого фрагмента.
Нужно помнить, что в методе inflate() последний параметр должен иметь значение false в большинстве случаев.
FragmentManager
Класс FragmentManager имеет два метода, позволяющих найти фрагмент, который связан с активностью:
findFragmentById(int id) Находит фрагмент по идентификатору findFragmentByTag(String tag) Находит фрагмент по заданному тегу
Методы транзакции
Мы уже использовали некоторые методы класса FragmentTransaction. Познакомимся с ними поближе
add() Добавляет фрагмент к активности remove() Удаляет фрагмент из активности replace() Заменяет один фрагмент на другой hide() Прячет фрагмент (делает невидимым на экране) show() Выводит скрытый фрагмент на экран detach() (API 13) Отсоединяет фрагмент от графического интерфейса, но экземпляр класса сохраняется attach() (API 13) Присоединяет фрагмент, который был отсоединён методом detach()
Методы remove(), replace(), detach(), attach() не применимы к статичным фрагментам.
Перед началом транзакции нужно получить экземпляр FragmentTransaction через метод FragmentManager.beginTransaction(). Далее вызываются различные методы для управления фрагментами.
В конце любой транзакции, которая может состоять из цепочки вышеперечисленных методов, следует вызвать метод commit().
Аргументы фрагмента
Фрагменты должны сохранять свою модульность и не должны общаться друг с другом напрямую. Если один фрагмент хочет докопаться до другого, он должен сообщить об этом своему менеджеру активности, а он уже передаст просьбу другому фрагменту. И наоборот. Это сделано специально для того, чтобы было понятно, что менеджер тут главный и он не зря зарплату получает. Есть три основных способа общения фрагмента с активностью.
- Активность может создать фрагмент и установить аргументы для него
- Активность может вызвать методы экземпляра фрагмента
- Фрагмент может реализовать интерфейс, который будет использован в активности в виде слушателя
Фрагмент должен иметь только один пустой конструктор без аргументов. Но можно создать статический newInstance с аргументами через метод setArguments().
Доступ к аргументам можно получить в методе onCreate() фрагмента:
Динамически загружаем фрагмент в активность.
Если активность должна выполнить какую-то операцию в фрагменте, то самый простой способ — задать нужный метод в фрагменте и вызвать данный метод через экземпляр фрагмента.
Вызываем метод в активности:
Если фрагмент должен сообщить о своих действиях активности, то следует реализовать интерфейс.
Управление стеком фрагментов
Фрагменты, как и активности, могут управляться кнопкой Back. Вы можете добавить несколько фрагментов, а потом через кнопку Back вернуться к первому фрагменту. Если в стеке не останется ни одного фрагмента, то следующее нажатие кнопки закроет активность.
Чтобы добавить транзакцию в стек, вызовите метод FragmentTransaction.addToBackStack(String) перед завершением транзакции (commit). Строковый аргумент — опциональное имя для идентификации стека или null. Класс FragmentManager имеет метод popBackStack(), возвращающий предыдущее состояние стека по этому имени.
Если вы вызовете метод addToBackStack() при удалении или замещении фрагмента, то будут вызваны методы фрагмента onPause(), onStop(), onDestroyView().
Когда пользователь нажимает на кнопку возврата, то вызываются методы фрагмента onCreateView(), onActivityCreated(), onStart() и onResume().
Рассмотрим пример реагирования на кнопку Back в фрагменте без использования стека. Активность имеет метод onBackPressed(), который реагирует на нажатие кнопки. Мы можем в этом методе сослаться на нужный фрагмент и вызвать метод фрагмента.
Теперь в классе фрагмента прописываем метод с нужным кодом.
Более желательным вариантом является использование интерфейсов. В некоторых примерах с фрагментами такой приём используется.
Интеграция Action Bar/Options Menu
Фрагменты могут добавлять свои элементы в панель действий или меню активности. Сначала вы должны вызвать метод Fragment.setHasOptionsMenu() в методе фрагмента onCreate(). Затем нужно задать настройки для методов фрагмента onCreateOptionsMenu() и onOptionsItemSelected(), а также при необходимости для методов onPrepareOptionsMenu(), onOptionsMenuClosed(), onDestroyOptionsMenu(). Работа методов фрагмента ничем не отличается от аналогичных методов для активности.
В активности, которая содержит фрагмент, данные методы автоматически сработают.
Если активность содержит собственные элементы панели действий или меню, то следует позаботиться, чтобы они не мешали вызовам методам фрагментов.
Код для активности:
Код для фрагмента:
Связь между фрагментом и активностью
Экземпляр фрагмента связан с активностью. Активность может вызывать методы фрагмента через ссылку на объект фрагмента. Доступ к фрагменту можно получить через методы findFragmentById() или findFragmentByTag().
Источник
Cannot convert from android.support.v4.app.Fragment to android.app.Fragment
I’m doing my first Android app, and wanted to get straight into the ICS API. I have so far created an app using an ActionBar, with swipeable tabs using Viewpager and Fragments.
I do however experience some errors that I keep returning to.
Depending on how I implement it, it always keep going back to an «Type mismatch» error: «cannot convert from android.support.v4.app.Fragment to android.app.Fragment». I have tried removing all import references to either, and this error appears when I only use android.support.v4.app.Fragment in TabListener, FragmentActivity and my two Fragments.
The error occurs in my TabListener:
By removing «android.app.FragmentTransaction ft», replacing it with just «FragmentTransaction ft», the problem goes awawy. Then new problems arise:
The method onTabReselected(ActionBar.Tab, FragmentTransaction) of type TabListener must override or implement a supertype method TabListener.java
The method onTabSelected(ActionBar.Tab, FragmentTransaction) of type TabListener must override or implement a supertype method TabListener.java
The method onTabUnselected(ActionBar.Tab, FragmentTransaction) of type TabListener must override or implement a supertype method TabListener.java
The type TabListener must implement the inherited abstract method ActionBar.TabListener.onTabReselected(ActionBar.Tab, FragmentTransaction) TabListener.java
The type TabListener must implement the inherited abstract method ActionBar.TabListener.onTabSelected(ActionBar.Tab, FragmentTransaction) TabListener.java
The type TabListener must implement the inherited abstract method ActionBar.TabListener.onTabUnselected(ActionBar.Tab, FragmentTransaction) TabListener.java
Whats going on here?
As you may understand, I’m new to Java and Android development. I feel like I’m pretty close, but I’m not able to solve this problem. I don’t understand why it want to «convert from android.support.v4.app.Fragment to android.app.Fragment when I’m not even importing android.app.Fragment anywhere.
I guess it’s related to using the compatibility package. (Do I have to use this package at all when creating an app for the newest version of the SDK?)
Источник
Android Studio and android.support.v4.app.Fragment: cannot resolve symbol
I am tryng out Android Studio instead of Eclipse. I install it and then start a completely new project and follow the wizard. I add no code of my own.
Then, I right-click to create a new component, a new Fragment:
and choose a new fragment:
and as soon as I do, I see compile errors:
. so I start googling and find out that I need to install and reference support library 4, and that I do. When I check the build.gradle (whatver that is, new to me coming from Eclipse), I see:
but I change that to
because they said so here. After recompiling and all that, the error is still there. I then reference the .jar-file directly, like this:
and again do recompile yada yada, but that doesnt help either.
This behaviour seems very strange to me. What am I missing here? This is the SDK Manager view:
So, what am I missing? Thanks =)
24 Answers 24
DID NOT WORK:
I have already had the following dependency in my build.gradle
I have tried all of the following,
- Invalidate Caches/Restart
- Sync project with gradle files
- Clean project
- Rebuild project
- gradlew clean
But, none of them worked for me.
SOLUTION:
Finally, I solved it by deleting «/.idea/libraries», and then synced with gradle and built again.
The symptom of this problem is usually that the build works fine from the command line (which means your build.gradle file is set up right) but you get syntax highlighting errors in the IDE. Follow This Steps To Solve The Problem: Click on Tools from the toolbar usually at the top part of your IDE, and then navigate to Android then navigate to Sync Project with Gradle Files button. We realize it’s less than ideal that the IDE can’t just take care of itself instead of forcing you to manually sync at the right time; we’re tracking progress on this in https://code.google.com/p/android/issues/detail?id=63151
Try this may will help you.Go to «File» -> «Invalidate Caches. «, and select «Invalidate and Restart» option to fix this.
replace this line of code
and you are done.
I got the same problem since I updated to latest version of Android Studio 0.3.7. So you can try with my stuffs.
Ensure you have updated to latest version Android Support Repository — 3 Android Support Library — 19
As your attachment picture above, you did it already. Then adding the following setting to your build.gradle
One more thing: Please make sure your Android SDK is targeting to right SDK folder
«File» -> «Invalidate Caches. «
I found a shortcut: File — Project Structure — Tab:Dependencies Click on the green + sign, select support-v4 (or any other you need), click OK.
now go to your gradle file and see that is been added
1> File -> invalidate caches 2> Build-> Rebuild
its work for me
I’m using buck and it seems like by removing the /.idea/libraries in your project folder and sync gradle again works for me.
I’m running the most current version of AndroidStudio to date (11/10/2015) — v1.4 (build AI-141.2288178, built on September 28, 2015) and I built my project and everything worked fine. Then after a few hours of my computer being inactive I came back, edited some code that had nothing to do with the support libraries and started seeing :
cannot resolve symbol ‘fragmentactivity’ and I was seeing red highlighted items related to fragmentactivity in the AndroidStudio editor.
The solution was to simply do a
I only mention this so others might see it and know it is happening out there.
Android studio has option to manage dependencies. Follow path.
- Click on File, then select Project Structure
- Choose Modules «app»
- Click «Dependencies» tab
- Click on the + sign, choose Library Dependencies
- Select support-v4 or other libraries as needed and click OK
2021 here — if, like me, you sadly have to just get some new code working with legacy junk that hasn’t been touched in five+ years and still uses the support libs AND can’t be changed before the deadline, you might try taking a look in gradle.properties for:
and commenting them if present. Android Studio 4.1.2 inserts them in new projects by default and they seem to get in the way of using support libs. Not surprising given the names, but the fact that they get auto-added to new projects is a little obnoxious.
For me : Build->Clean Project solved this question
File -> «Invalidate caches/Restart» This worked for me.
Hrrm. I dont know how many times this has happend so far: I test, try, google, test again and mess around for hours, and when I finally give up, I go to my trusted Stackoverflow and write a detailed and clear question.
When I post the question, switch over to the IDE and boom — error gone.
I can’t say why its gone, because I change absolutely nothing in the code except for that I already tried as stated above. But all of a sudden, the compile error is gone!
In the build.gradle, it now says:
which initially did not work, the compile errors did not go away. it took like 30 min before the IDE got it, it seems. hmm.
=== EDIT === When I view the build.gradle again, it has now changed and looks like this:
Im not really sure what the appcompat is right now.
Источник