Вкладка «Панель действий Android» со списком прокрутки сделала дублированный вид после изменения ориентации

У меня очень простой код, где я использую панель действий с фрагментами вкладок. Он работает отлично после нагрузки, но после изменения ориентации он сходит с ума. Старый фрагмент также виден (почему?).

Извините за венгерские тексты на изображении, но я надеюсь, что это не имеет значения. После изменения ориентации

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

Основная деятельность:

public class Main extends Activity { private static ActionBar actionBar; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setup action bar for tabs actionBar = getActionBar(); actionBar.removeAllTabs(); if (actionBar.getTabCount() == 0) { actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); Tab tab = actionBar.newTab().setText(R.string.starter).setTabListener(new TabListener<Starter>(this, "starter", Starter.class)); actionBar.addTab(tab); tab = actionBar.newTab().setText(R.string.newword).setTabListener(new TabListener<NewWord>(this, "newwod", NewWord.class)); actionBar.addTab(tab); tab = actionBar.newTab().setText(R.string.feedback).setTabListener(new TabListener<Feedback>(this, "feedback", Feedback.class)); actionBar.addTab(tab); } if (savedInstanceState != null) { actionBar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0)); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("tab", getActionBar().getSelectedNavigationIndex()); } } 

TabListener (аналогично примеру Google):

 public class TabListener<T extends Fragment> implements android.app.ActionBar.TabListener { private Fragment mFragment; private final Activity mActivity; private final String mTag; private final Class<T> mClass; /** * Constructor used each time a new tab is created. * * @param activity * The host Activity, used to instantiate the fragment * @param tag * The identifier tag for the fragment * @param clz * The fragment's Class, used to instantiate the fragment */ public TabListener(Activity activity, String tag, Class<T> clz) { mActivity = activity; mTag = tag; mClass = clz; } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { // User selected the already selected tab. Usually do nothing. } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { // Check if the fragment is already initialized if (mFragment == null) { // If not, instantiate and add it to the activity mFragment = Fragment.instantiate(mActivity, mClass.getName()); ft.add(android.R.id.content, mFragment, mTag); } else { // If it exists, simply attach it in order to show it ft.attach(mFragment); } } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { if (mFragment != null) { // Detach the fragment, because another one is being attached ft.detach(mFragment); } } } 

Фрагмент:

 public class Starter extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { setRetainInstance(false); return inflater.inflate(R.layout.newword, container, false); } } 

И макет XML:

 <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp" > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/newword" android:textAppearance="?android:attr/textAppearanceMedium" /> <EditText android:id="@+id/newwordtext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/wordhint" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/description" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <EditText android:id="@+id/descriptionwordtext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/descriptionhint" android:inputType="textMultiLine" android:minLines="4" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/origin" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <EditText android:id="@+id/origintext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/originhint" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/source" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <EditText android:id="@+id/sourcetext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/sourcehint" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/name" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <EditText android:id="@+id/nametext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="textPersonName" /> <Button android:id="@+id/sendbutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:text="@string/send" /> </LinearLayout> </ScrollView> Отправить <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp" > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/newword" android:textAppearance="?android:attr/textAppearanceMedium" /> <EditText android:id="@+id/newwordtext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/wordhint" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/description" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <EditText android:id="@+id/descriptionwordtext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/descriptionhint" android:inputType="textMultiLine" android:minLines="4" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/origin" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <EditText android:id="@+id/origintext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/originhint" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/source" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <EditText android:id="@+id/sourcetext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/sourcehint" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" android:text="@string/name" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <EditText android:id="@+id/nametext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="textPersonName" /> <Button android:id="@+id/sendbutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:text="@string/send" /> </LinearLayout> </ScrollView> 

Заранее спасибо!

Solutions Collecting From Web of "Вкладка «Панель действий Android» со списком прокрутки сделала дублированный вид после изменения ориентации"

Я нашел полезный ответ в другом вопросе .

Мне нужно изменить мой TabListener (я переместил его в свой основной класс активности как внутренний класс):

 private class TabListener<T extends Fragment> implements android.app.ActionBar.TabListener { private Fragment mFragment; private final Activity mActivity; private final String mTag; private final Class<T> mClass; /** * Constructor used each time a new tab is created. * * @param activity * The host Activity, used to instantiate the fragment * @param tag * The identifier tag for the fragment * @param clz * The fragment's Class, used to instantiate the fragment */ public TabListener(final Activity activity, final String tag, final Class<T> clz) { mActivity = activity; mTag = tag; mClass = clz; } @Override public void onTabReselected(final Tab tab, final FragmentTransaction ft) { // User selected the already selected tab. Usually do nothing. } @Override public void onTabSelected(final Tab tab, final FragmentTransaction ft) { mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag); if (mFragment == null) { mFragment = Fragment.instantiate(mActivity, mClass.getName()); ft.add(android.R.id.content, mFragment, mTag); } else { ft.attach(mFragment); } } @Override public void onTabUnselected(final Tab tab, final FragmentTransaction ft) { if (mFragment != null) { ft.detach(mFragment); } } } 

Поэтому, прежде чем добавить фрагмент (снова), я проверяю его существование (и получаю его ссылку), и если он существует, я присоединяю его только.

Попробуйте использовать ft.replace (R.id.content, mFragment) вместо ft.attach (mFragment); В функции onTabSelected

Я нашел очень простое решение, чтобы избежать дублирования фрагментов:

  public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) { Fragment currentFragment = getFragmentManager().findFragmentByTag(CURRENT_FRAGMENT_TAG); if (currentFragment == null || !currentFragment.getClass().equals(mFragment.getClass())) { ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); ft.add(android.R.id.content, mFragment, CURRENT_FRAGMENT_TAG); } } public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) { ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); ft.remove(mFragment); } 

Ключ решения находится в условии:

 currentFragment == null || !currentFragment.getClass().equals(mFragment.getClass()) 

Это условие справедливо ТОЛЬКО, если классы фрагментов различны. Если у вас есть разные экземпляры одного и того же класса, вы должны добавить дополнительный атрибут в свои фрагменты, чтобы распознать его функцию (или ассоциацию с и сделать условие! CurrentFragment.getClass (). Equals (mFragment.getClass ()) true : Например, вы можете использовать функцию тега FragmentTransaction.

Пока, Алекс.

 public void onTabSelected(Tab tab, FragmentTransaction ft) { // Check if the fragment is already initialized if (mFragment == null) { if(ft.findFragmentById(android.R.id.content) == null){ // If not, instantiate and add it to the activity mFragment = Fragment.instantiate(mActivity, mClass.getName()); ft.add(android.R.id.content, mFragment, mTag); } } else { // If it exists, simply attach it in order to show it ft.attach(mFragment); } } 

Что-то в этом роде, потому что ваша проблема заключается в том, что вы добавляете тот же фрагмент дважды, нам просто нужно найти, где …

Я решил это, просто просмотрев фрагмент в конструкторе list listener.

 public class TabListener<T extends Fragment> implements ActionBar.TabListener { private Fragment fragment; private final SherlockFragmentActivity activity; private final String tag; private final Class<T> clazz; public TabListener(SherlockFragmentActivity activity, String tag, Class<T> clazz) { this.activity = activity; this.tag = tag; this.clazz = clazz; FragmentManager manager = ((SherlockFragmentActivity) activity).getSupportFragmentManager(); fragment = manager.findFragmentByTag(tag); } ... }