android - studio - Uso de backstack y botón de retroceso en viewpager
on back pressed android fragment (5)
Estoy usando un visor para deslizar entre los fragmentos y me gustaría que el botón Atrás navegue al fragmento visto anteriormente en lugar de finalizar la actividad. Lo siento si esto es un duplicado de esta pregunta, pero no encontré la respuesta muy útil. Obviamente onBackPressed necesita ser anulado, pero no sé cómo obtener y mostrar el fragmento correcto. Supongo que debería usar backstack de fragmentmanager, pero getSupportFragmentManager().getBackStackEntryCount()
siempre devuelve 0. ¿Tengo que agregar fragmentos manualmente a la backstack usando FragmentTransaction.addToBackStack()
? Si es así, ¿dónde debería agregar esto en mi adaptador?
Aquí está el código para mi actividad,
public class PagerActivity extends FragmentActivity {
ArrayList<Sale> sales;
MyAdapter mAdapter;
ViewPager mPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent it = getIntent();
this.sales = (ArrayList<Sale>) it.getExtras().get("sales");
int position = it.getExtras().getInt("position");
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.fragment_pager);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(position);
}
public class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public int getCount() {
return sales.size();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
@Override
public Fragment getItem(int position) {
SalesThumbFragment frag = new SalesThumbFragment();
return frag.newInstance(sales.get(position));
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.sales_controller, menu);
return true;
}
@Override
public void onBackPressed() {
if(getSupportFragmentManager().getBackStackEntryCount() != 0) {
getSupportFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
}
He creado ViewPager personalizado e implementado la funcionalidad de pila en él.
public class CustomViewPager extends ViewPager {
private Stack<Integer> stack = new Stack<>();
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
stack.push(getCurrentItem());
super.setCurrentItem(item, smoothScroll);
}
public int popFromBackStack(boolean smoothScroll) {
if (stack.size()>0) {
super.setCurrentItem(stack.pop(), smoothScroll);
return getCurrentItem();
} else return -1;
}
Si utiliza un campo para realizar un seguimiento del índice de la página anterior utilizando mPager.getCurrentItem()
después de cada vez que el usuario navega a un nuevo fragmento, en el método onBackPressed()
, debe poder llamar a mPager.setCurrentItem(previousPage)
O bien, si el usuario solo puede hacer una página en orden, entonces no necesita un campo en absoluto, y podría simplemente hacer mPager.setCurrentItem(mPager.getCurrentItem()-1)
Tuve un problema similar, así es como lo resolví. Creo que puedes adaptar el código a tu problema si entendí cuál es tu problema. Tenía un ViewPager con 6 fragmentos y quería hacer un seguimiento del historial de la página y poder usar el botón Atrás para navegar hacia atrás en el historial. Creo un objeto java.util.Stack<Integer>
, le agrego números de fragmento (excepto cuando utilizo el botón Atrás, vea abajo), y onBackPressed()
para hacer que onBackPressed()
el último fragmento visto en lugar de usar la pila de respaldo , cuando mi pila de historial no está vacía.
Desea evitar presionar elementos en la pila cuando presiona el botón Atrás, de lo contrario se quedará atrapado entre dos fragmentos si continúa utilizando el botón Atrás, en lugar de salir finalmente.
Mi código:
MyAdapter mAdapter;
ViewPager mPager;
Stack<Integer> pageHistory;
int currentPage;
boolean saveToHistory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.container);
mPager.setAdapter(mAdapter);
mPager.setOffscreenPageLimit(5);
pageHistory = new Stack<Integer>();
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
if(saveToHistory)
pageHistory.push(Integer.valueOf(currentPage));
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
saveToHistory = true;
}
@Override
public void onBackPressed() {
if(pageHistory.empty())
super.onBackPressed();
else {
saveToHistory = false;
mPager.setCurrentItem(pageHistory.pop().intValue());
saveToHistory = true;
}
};
Usa este código en la clase de Actividad de Fragmentos. No te olvides de agregar el retorno verdadero;
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
mViewPager.setCurrentItem(viewPageSelected - 1);
return true;
}
return super.onKeyDown(keyCode, event);
}
En la nueva biblioteca de soporte de diseño, uso esto
Tengo el mismo problema y sigo este paso
En la actividad principal donde hay 3 fragmentos en viewpager, creo pila y datos push y pop.
//private Stack<Integer> stackkk; ==> As i get edit suggestion
private Stack<Integer> stackkk = new Stack<>(); // Edited
private ViewPager mPager;
private int tabPosition = 0;
mTabLayout.setupWithViewPager(mPager);
mPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
tabPosition = tab.getPosition();
mPager.setCurrentItem(tab.getPosition());
if (stackkk.empty())
stackkk.push(0);
if (stackkk.contains(tabPosition)) {
stackkk.remove(stackkk.indexOf(tabPosition));
stackkk.push(tabPosition);
} else {
stackkk.push(tabPosition);
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
tabPositionUnselected = tab.getPosition();
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
y en la actividad onBackPressed in,
@Override
public void onBackPressed() {
if (stackkk.size() > 1) {
stackkk.pop();
mPager.setCurrentItem(stackkk.lastElement());
} else {
}
}