Android: проблема перекрытия фрагментов
я сталкиваюсь с проблемой перекрытия фрагментов при переключении между вкладками и прикреплении фрагментов к представлению вкладки ниже приведен мой код, Пожалуйста, помогите
public class FragmentManage extends Fragment implements ActionBar.TabListener {
private Fragment mFragment;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_manage, container, false);
OnClickListener clickListener = new OnClickListener() {
public void onClick(View v) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
switch(v.getId()) {
case R.id.imageBtnCategory:
if (mFragment == null){
mFragment = new FragmentCategory();
}
ft.replace(android.R.id.content, mFragment);
break;
case R.id.imageBtnManageKey:
if (mFragment == null){
mFragment = new FragmentKeys();
}
ft.replace(android.R.id.content, mFragment);
break;
case R.id.imageBtnChangePswd:
if (mFragment == null){
mFragment = new FragmentChangePwd();
}
ft.replace(android.R.id.content, mFragment);
break;
}
ft.commit();
}
};
ImageButton imageBtnCategory = (ImageButton) v.findViewById(R.id.imageBtnCategory);
ImageButton imageBtnManageKey = (ImageButton) v.findViewById(R.id.imageBtnManageKey);
ImageButton imageBtnChangePswd = (ImageButton) v.findViewById(R.id.imageBtnChangePswd);
imageBtnCategory.setOnClickListener(clickListener);
imageBtnManageKey.setOnClickListener(clickListener);
imageBtnChangePswd.setOnClickListener(clickListener);
return v;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mFragment = new FragmentManage();
ft.add(android.R.id.content, mFragment);
ft.attach(mFragment);
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(mFragment);
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
15 ответов
Я могу очень поздно ответить на этот вопрос.
Примечание:
этот ответ может не быть связан с вышеуказанным вопросом, но надеюсь, что это поможет для некоторых.
Иногда проблема перекрытия фрагментов возникает, когда мы пытаемся использовать другой тип фрагментов (i.e использование фрагментов поддержки в нескольких фрагментах и нормальных фрагментах в другом фрагменте)
недавно я столкнулся с той же проблемой в навигации ящик. По ошибке я использовал "импорт android.поддержка.В4.приложение.Фрагмент; "в одном фрагменте, и используется"импорт android.приложение.Фрагмент; " в нескольких других фрагментах.
надеюсь, это поможет кому-то..
менеджер фрагментов поддерживает стек всех предыдущих фрагментов, которые заменяются иногда фрагменты заднего стека перекрываются с фрагментом, который мы заменили, для меня
fragmentManager.popBackStack();
работает, мы можем сделать это в цикле тоже, чтобы поп все фрагменты в стеке надеюсь, что это поможет, Спасибо. Счастливое Кодирование:)
Ну Настройка цвета фона фрагмента не является решением, потому что фрагмент все еще будет в стеке действий, который может потреблять память.
решение будет удалить все представления из вашего framelayout перед добавлением любого нового фрагмента.
private void changeFragment(Fragment fr){
FrameLayout fl = (FrameLayout) findViewById(R.id.mainframe);
fl.removeAllViews();
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
transaction1.add(R.id.mainframe, fr);
transaction1.commit();
}
вот как я это исправил ..
установка фона удалит эффект перекрытия с экрана, только если макет соответствует заполнению экрана
новые фрагменты, замененные при нажатии кнопки, не заменялись на tab_selected или tab change action
следующий код исправил это для меня
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// This is required since button click replaces fragment whose link is lost hence overlapping isuee was occuring
ft.replace(android.R.id.content, mFragment);
// On Tab Change remove old fragment views
ft.remove(mFragment);
}
еще одна проблема может быть связана с использованием android.R.id.content
как контейнер. Я только что создал FrameLayout
и используйте id оттуда.
Я также столкнулся с проблемой перекрытия фрагментов.Вот как я решил это -
1) Нам нужно добавить первый фрагмент с addToBackStack, чтобы он остался в стеке -
FirstFragment firstFragment = new FirstFragment();
getFragmentManager().beginTransaction().add(R.id.fragment_container, firstFragment).addToBackStack("first frag").commit();
2) при добавлении второго фрагмента замените первый фрагмент, а не добавляя его.Поскольку первый фрагмент уже был добавлен в стек, поэтому он будет присутствовать при нажатии назад из второго фрагмента -
SecondFragment secondFragment= new SecondFragment();
getFragmentManager().beginTransaction().replace(R.id.fragment_container, secondFragment).addToBackStack("second frag").commit();
3) здесь как заднюю прессу можно отрегулировать, ниже код должен присутствовать в Родительском действии -
public void onBackPressed(){
if(getFragmentManager().getBackStackEntryCount() <= 1){
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
private void changeFragment(Fragment fr){
FrameLayout fl = (FrameLayout) findViewById(R.id.mainframe);
fl.removeAllViews();
FragmentTransaction transaction1 =getSupportFragmentManager().beginTransaction();
transaction1.add(R.id.mainframe, fr);
transaction1.commit();}
когда у вас есть фрагмент перекрытия, возможно, ваш фон вашего фрагмента прозрачен, вам нужно поместить android:background="@color/white"' внутри ваших свойств фрагмента
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
и белый вам нужно положить внутри цветов.XML #FFFFFF в папке rest.
Я иногда та же проблема, но моя проблема не связана с разными менеджерами фрагмент (getSupportFragmentManager()
, getFragmentManager()
). Думаю, есть еще одна проблема. В моем случае, когда я открываю навигационный ящик, я всегда удаляю старые фрагменты в каждой опции меню, например:
Fragment calendarFragment = context.getSupportFragmentManager().findFragmentByTag(FragmentTag.CALENDAR.name());
if (calendarFragment != null)
{
context.getSupportFragmentManager().beginTransaction().remove(calendarFragment).commit();
}
невозможно попасть в подменю без навигационного ящика, поэтому фрагменты в основном всегда удаляются. В некоторых случаях после удаления и добавления фрагмента снова внутри действия он внезапно перекрывается с другим (предыдущим) фрагментом?! Но почему менеджер фрагментов внезапно находит предыдущие фрагменты?
Это может означать, что диспетчер фрагментов глючит и не удаляет старые фрагменты, или что что-то другое сломано.
Моя мысль заключается в том, что это как-то вина Android Studio или любого другого инструмента разработки adb, который используется им. Почему я думаю, что это так, потому что Android Studio иногда, похоже, теряет экземпляр запущенного приложения. Вероятно, эта проблема как-то связана с той же проблемой: Android Studio не развертывает изменения в app. Я еще не понял, когда это произойдет. Я знаю, что это не может быть проблемой программирования, потому что она не воспроизводима после перезапуска приложения Android Studio. Я предполагаю, что каким-то образом висят какие-то фоновые процессы, которые вызывают несколько экземпляров действий, фрагментов, менеджеров фрагментов и так далее. Кроме того, это не просто ошибка. Я видел много странных поведение в прошлом, похожее на это. (Например, поведение внезапно исчезло, когда приложение не было запущено IDE).
все это имеет отношение к технике за заменить и addToBackStack методы.
Метод replace фактически сделает две вещи. Скройте существующий фрагмент (скажем, A) и добавьте новый (скажем, B) в контейнер.
Добавление этой транзакции в задний стек будет делать обратное. Удалите B и добавьте A.
Итак, решение вашей проблемы -
1. использовать addToBackStack метод.
2. убедитесь, что обратная замена фрагментов в правильном порядке
Второе предложение действительно важно, потому что довольно часто в какой-то момент текущий фрагмент не удаляется, а добавляется другой, что вызывает одновременное отображение двух фрагментов.
создание белого цвета фона решило это и для меня. Я думаю, это ошибка или и проблема реализации в fragmentment менеджер для Android. Я правильно реализовал свои replace и popBackStack ().
когда у меня была такая проблема, оказалось, что я добавляю один фрагмент с childFragmentManager, а другой с fragmentManager родителя, поэтому проверьте, что вы используете тот же тип менеджера фрагментов.
Я не думаю, что реализация белого фона является безопасным решением, хотя это может быть удобно. В основном проблема возникает из-за того, что диспетчер фрагментов путается о том, какой фрагмент всплывать.
backstack выглядит так и думает ваш на фраг 4 1->2, 2->3, 3->4 но ваш На самом деле на frag 6 по какой-то причине так popbackstack идет
удалить(4) Добавить(3)
чтобы лучше контролировать свои навигация я отслеживаю мои текущие / предыдущие фрагменты и заменяю их следующим образом. Это позволяет моему приложению управлять навигацией по фрагментам.
if ( !(currentFragment instanceof Settings)) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, settings);
fragmentTransaction.addToBackStack(null);
previousFrag = currentFragment;
currentFragment = settings;
fragmentTransaction.commit();
}
во-вторых, я считаю, что fragmentmanager.метод replace () является лучшей альтернативой. Не уверен, что это доступно для OP в то время.
В-третьих, для обработки андроидов родной назад нажмите вы должны иметь возможность прокручивать назад бесконечно. Многие люди рекомендуют не добавлять первый фрагмент в задний стек, не используя это линия.
fragmentTransaction.addToBackStack (null);
однако, если это так, вы должны проверить, если его первый раз приложение загрузилось. Если его нет, и вы исключаете эту строку, то ваше приложение будет иметь эти проблемы при навигации по этому фрагменту. Я предпочитаю оставить его на месте и вместо этого сделать следующее.
не уверен, что это считается хорошим решением, но оно работает очень хорошо.
1-получить подсчет backstack 2 - удалить все существующие Фраги 3 - Следите за вами фрагмент объектов 4-если его последний фрагмент в стеке пользователь хочет выйти, и так как мы добавили основное действие в задний стек, нам нужно удвоить pop
@Override
public void onBackPressed() {
int num = getFragmentManager().getBackStackEntryCount();
fl.removeAllViews();
super.onBackPressed();
if (currentFragment != previousFrag) {
currentFragment = previousFrag;
}else{
currentFragment = null;
}
if (num == 1){
super.onBackPressed();
}
Я нашел простое и чистое решение. Для меня проблема заключалась в выполнении транзакции фрагмента в каждом вызове onCreate() моей деятельности. Теперь я выполняю транзакцию только если savedInstanceState == null
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (savedInstanceState == null) {
// replace fragment
}
}