Вопрос по android – Избегайте воссоздания того же представления при переключении вкладок

31

Тока у меня 2Fragments, который переключается черезActionBarвкладка.

    getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    ActionBar.Tab newTab = getSupportActionBar().newTab();
    newTab.setText("history");
    newTab.setTabListener(new TabListenerHistoryFragment>(this, "history",
        HistoryFragment.class));

 @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());
        mFragment.setRetainInstance(true);
        ft.add(android.R.id.content, mFragment, mTag);
    } else {
        // If it exists, simply attach it in order to show it
        ft.attach(mFragment);
    }        
}

Я понимаю, первый раз мойActivity (Это действие содержит 2 фрагмента) запускается,FragmentS & APOS; Методы будут вызываться в следующей последовательности.

onCreate -> onCreateView -> onStart

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

onCreateView -> onStart

Я просто хочу сохранить то же состояние графического интерфейса, когда Tab переключается обратно.

  • I want my chart continue to be zoomed into previous level.
  • I want my chart horizontal scroll stay at previous level.
  • I want my list continue scroll stay at previous level.
  • ...

Я знаю, что я могу сохранить / восстановить простые переменные, используя следующий метод при переключении Tab

Android фрагмент - Как сохранить состояния представлений во фрагменте, когда другой фрагмент помещается поверх него

Но это не то, чего я хочу, так как мое состояние GUI довольно сложно описать в целом ряде примитивных значений.

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

public class HistoryFragment extends Fragment {
    View view = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (this.view != null) {
            return this.view;
        }
        this.view = inflater.inflate(R.layout.history_activity, container, false); 
    }
}

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

Я понимаю, что следующий демонстрационный пример может сохранить состояние фрагмента графического интерфейса пользователя (например, положение вертикальной прокрутки списка) при переключении табуляции. Но я думаю, возможно, это потому, что они используют ListFragment? Поскольку я не нахожу, что они выполняют какую-либо специальную обработку, чтобы сохранить состояние GUI.

  • com.example.android.apis.app.FragmentTabs
  • com.example.android.apis.app.LoaderCursor.CursorLoaderListFragment

May I know, how I can avoid from recreating same view when perform tab switching?

Вы узнали, как это сделать? Emil
Тоже самое. Вы думаете, что это будет просто ... thunderousNinja
Имея ту же проблему. Тем более, что на одной из моих вкладок поля добавляются динамически. Victor Araújo

Ваш Ответ

6   ответов
0

Update

ViewPager вместоActionBarвкладка.

19

наконец, наткнулсяответ @roger который спас мне много волос ....

При использовании ViewPager в других реализациях я мог бы просто вызвать:

mViewPager.setOffscreenPageLimit(//number of pages to cache);

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

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FragmentExample extends Fragment {

    private View rootView;

    public FragmentExample() {
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {

        if (rootView == null) {

            rootView = inflater.inflate(R.layout.fragment_example_layout, container, false);

            // Initialise your layout here

        } else {
            ((ViewGroup) rootView.getParent()).removeView(rootView);
        }

        return rootView;
    }
}

Я искал следующие ключевые фразы, которые я добавляю здесь, в надежде, что я смогу спасти кого-то еще от разочарования, которое я только что испытал!

FragmentTabHost сохранить состояние фрагмента

FragmentTabHost просмотров воссоздан

FragmentTabHost кеш фрагменты

FragmentTabHost onCreateView Фрагмент уничтожен

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededthis
6

onCreateView при переключении вкладок.

Операция onCreate должна добавить все фрагменты и скрыть все, кроме одного для первой вкладки:

ft.add(R.id.fragment_content, secondTabFragment);
ft.hide(secondTabFragment);
ft.add(R.id.fragment_content, firstTabFragment);
ft.show(firstTabFragment);
ft.commit();
currentFragment = firstTabFragment;

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

ft.hide(currentFragment);
ft.show(chosenFragment);
ft.commit();
currentFragment = chosenFragment;

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

<activity android:configChanges="keyboardHidden|orientation" ...
Error: User Rate Limit Exceeded
3

View mMyView = null;     
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state)  {
        , if (state == null) {
             mMyView = new MyView(getActivity());
         } else {
             container.removeView(mMyView);
         }

         return mMyView; 
    }
36

и я попытался следовать предложению в сообщении об ошибке. Я попробовал следующий код, и он работал для меня.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state)  {
     if (mMyView == null) {
         mMyView = new MyView(getActivity());
     } else {
         ((ViewGroup) mMyView.getParent()).removeView(mMyView);
     }

     return mPuzzleView; 
}
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
-1

но то, что я сделал, перед тем как прикрепить или отсоединить фрагмент внутри обратных вызовов ActionBar.TabListener, вызвать

fragmentManager.executePendingTransactions();

это решает проблему для меня

@Override
public void onTabelected(Tab tab, FragmentTransaction ft, FragmentManager fm) {
    fm.executePendingTransactions(); // **execute the pending transactions before adding another fragment.
    if (mFragment == null) {
        mFragment = Fragment.instantiate(mContext, mFragmentName);
        ft.replace(android.R.id.tabcontent, mFragment, mTag);
    } else {
        ft.attach(mFragment);
    }
}

Похожие вопросы