android fragment - jak zapisać Stany widoków w fragmencie, gdy inny fragment jest popychany na niego
W Androidzie fragment (powiedzmy FragA
) jest dodawany do backstacka, a inny fragment (powiedzmy FragB
) pojawia się na górze. Teraz po uderzeniu z powrotem FragA
wchodzi na szczyt i onCreateView()
jest wywoływany. Teraz miałem FragA
w określonym stanie, zanim FragB
zostałem zepchnięty na wierzch.
Moje pytanie brzmi: Jak mogę przywrócić FragA
do poprzedniego stanu ? Czy istnieje sposób na zapisanie stanu (jak np. w pakiecie), a jeśli tak, to jaką metodę powinienem nadpisać ?
11 answers
W fragment guide Fragmentlisty przykład można znaleźć:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("curChoice", mCurCheckPosition);
}
Które możesz użyć później w ten sposób:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
// Restore last state for checked position.
mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
}
}
Jestem początkujący we fragmentach, ale wydaje się, że rozwiązanie twojego problemu ;) OnActivityCreated jest wywoływany po powrocie fragmentu z tylnego stosu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-07 19:40:59
Fragment onSaveInstanceState(Bundle outState)
nigdy nie zostanie wywołany, dopóki aktywność fragmentu nie wywoła go na sobie i dołączonych fragmentach. Tak więc ta metoda nie zostanie wywołana, dopóki coś (zazwyczaj obrót) wymusi aktywność SaveInstanceState
i przywróci ją później.
Ale jeśli masz tylko jedną aktywność i duży zestaw fragmentów wewnątrz niej (z intensywnym użyciem replace
) i aplikacja działa tylko w jednym działaniu orientacyjnym onSaveInstanceState(Bundle outState)
może nie być wywołana przez długi czas.
The pierwszy:
Użyj argumentów fragmentu do przechowywania ważnych danych:
public class FragmentA extends Fragment {
private static final String PERSISTENT_VARIABLE_BUNDLE_KEY = "persistentVariable";
private EditText persistentVariableEdit;
public FragmentA() {
setArguments(new Bundle());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_a, null);
persistentVariableEdit = (EditText) view.findViewById(R.id.editText);
TextView proofTextView = (TextView) view.findViewById(R.id.textView);
Bundle mySavedInstanceState = getArguments();
String persistentVariable = mySavedInstanceState.getString(PERSISTENT_VARIABLE_BUNDLE_KEY);
proofTextView.setText(persistentVariable);
view.findViewById(R.id.btnPushFragmentB).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getFragmentManager()
.beginTransaction()
.replace(R.id.frameLayout, new FragmentB())
.addToBackStack(null)
.commit();
}
});
return view;
}
@Override
public void onPause() {
super.onPause();
String persistentVariable = persistentVariableEdit.getText().toString();
getArguments().putString(PERSISTENT_VARIABLE_BUNDLE_KEY, persistentVariable);
}
}
Drugi, ale mniej pedantyczny sposób -
przechowuj zmienne w singletonach
Trzeci-nie replace()
fragmenty, ale add()
/show()
/hide()
zamiast nich.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-01 07:51:31
Zauważ, że jeśli pracujesz z fragmentami za pomocą Viewpagera, jest to całkiem proste. Wystarczy wywołać tę metodę: setOffscreenPageLimit()
.
Zgodnie z docs:
Ustawia liczbę stron, które mają być zachowane po obu stronach bieżącej strony w hierarchii widoku w stanie bezczynności. Strony poza tym limitem zostaną odtworzone z adaptera w razie potrzeby.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:24
Po prostu nadmuchaj Widok.
Exemple:
public class AFragment extends Fragment {
private View mRootView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(mRootView==null){
mRootView = inflater.inflate(R.id.fragment_a, container, false);
//......
}
return mRootView;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-11 06:48:38
Pracowałem z problemem bardzo podobnym do tego. Ponieważ wiedziałem, że często będę wracał do poprzedniego fragmentu, sprawdziłem, czy fragment .isAdded()
jest prawdziwy, a jeśli tak, to zamiast robić transaction.replace()
po prostu robię transaction.show()
. Dzięki temu fragment nie jest odtwarzany, jeśli jest już na stosie - nie jest konieczne zapisywanie stanu.
Fragment target = <my fragment>;
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if(target.isAdded()) {
transaction.show(target);
} else {
transaction.addToBackStack(button_id + "stack_item");
transaction.replace(R.id.page_fragment, target);
}
transaction.commit();
Inną rzeczą, o której należy pamiętać, jest to, że chociaż zachowuje to naturalny porządek dla samych fragmentów, nadal możesz potrzebować obsługi sama aktywność jest niszczona i odtwarzana po zmianie orientacji (config). Aby obejść to w AndroidManifest.xml dla Twojego węzła:
android:configChanges="orientation|screenSize"
[[6]}W Androidzie 3.0 i wyższych, screenSize
jest najwyraźniej wymagane.
Powodzenia
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-26 14:29:54
Najlepsze rozwiązanie jakie znalazłem jest poniżej:
OnSavedInstanceState (): zawsze wywoływana wewnątrz fragmentu, gdy aktywność ma się wyłączyć(przenieść aktywność z jednej do drugiej lub zmienić konfigurację). Jeśli więc wywołujemy wiele fragmentów na tej samej aktywności, musimy użyć następującego podejścia:
Użyj ondestroyview () fragmentu i zapisz cały obiekt wewnątrz tej metody. Wtedy Onactivitycreated (): sprawdza czy obiekt jest null czy nie (ponieważ metoda ta wywołuje za każdym razem). Teraz Przywróć stan obiektu tutaj.
Its works always!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-08 11:51:41
Jeśli obsługujesz zmiany konfiguracyjne w aktywności fragmentu określonej w manifeście Androida, tak jak to
<activity
android:name=".courses.posts.EditPostActivity"
android:configChanges="keyboardHidden|orientation"
android:screenOrientation="unspecified" />
Wtedy onSaveInstanceState
fragmentu nie zostanie wywołany, a savedInstanceState
Obiekt zawsze będzie null.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-03 11:03:00
Użyłem podejścia hybrydowego dla fragmentów zawierających widok listy. Wydaje się być wydajny, ponieważ nie zastępuję bieżącego fragmentu, ale raczej dodaję nowy fragment i ukrywam bieżący. Mam następującą metodę w działaniu, która hostuje moje fragmenty:
public void addFragment(Fragment currentFragment, Fragment targetFragment, String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(0,0,0,0);
transaction.hide(currentFragment);
// use a fragment tag, so that later on we can find the currently displayed fragment
transaction.add(R.id.frame_layout, targetFragment, tag)
.addToBackStack(tag)
.commit();
}
Używam tej metody w moim fragmencie (zawierającym widok listy) za każdym razem, gdy element listy jest kliknięty/stuknięty (a więc muszę uruchomić / wyświetlić fragment szczegółów):
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
SearchFragment currentFragment = (SearchFragment) fragmentManager.findFragmentByTag(getFragmentTags()[0]);
DetailsFragment detailsFragment = DetailsFragment.newInstance("some object containing some details");
((MainActivity) getActivity()).addFragment(currentFragment, detailsFragment, "Details");
getFragmentTags()
zwraca tablicę łańcuchów, które Używam jako znaczników dla różnych fragmentów, gdy dodaję nowy fragment (patrz metoda transaction.add
w metodzie addFragment
powyżej).
W fragmencie zawierającym widok listy robię to w jego metodzie onPause ():
@Override
public void onPause() {
// keep the list view's state in memory ("save" it)
// before adding a new fragment or replacing current fragment with a new one
ListView lv = (ListView) getActivity().findViewById(R.id.listView);
mListViewState = lv.onSaveInstanceState();
super.onPause();
}
Następnie w onCreateView fragmentu (właściwie w metodzie, która jest wywoływana w onCreateView), przywracam stan:
// Restore previous state (including selected item index and scroll position)
if(mListViewState != null) {
Log.d(TAG, "Restoring the listview's state.");
lv.onRestoreInstanceState(mListViewState);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-29 20:26:39
Nie sądzę {[0] } jest dobrym rozwiązaniem. to po prostu użyć do aktywności, która została zniszczona.
Od Androida 3.0 Fragmen został menadżerem przez FragmentManager, warunkiem jest: jedna aktywność mapująca fragmenty manny, gdy fragment zostanie dodany (nie zastąpi: zostanie odtworzony) w backstacku, Widok zostanie destored. po powrocie do ostatniego, wyświetli się jak wcześniej.
Więc myślę, że fragment i transakcja są wystarczająco dobre, aby sobie z tym poradzić.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-20 03:43:46
W końcu po wypróbowaniu wielu z tych skomplikowanych rozwiązań, ponieważ musiałem tylko zapisać / przywrócić pojedynczą wartość w moim fragmencie( zawartość EditText), i chociaż nie jest to najbardziej eleganckie rozwiązanie, stworzenie SharedPreference i przechowywanie mojego stanu tam działało dla mnie
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-25 21:16:57
private ViewPager viewPager;
viewPager = (ViewPager) findViewById(R.id.pager);
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-09 13:59:45