android - viewpager - fragmentpageradapter example
Guardar/Actualizar datos EditText de Fragment en un FragmentStatePagerAdapter (1)
Introducción
Tengo una actividad con un libro que contiene una lista de tipos de "página" y para manejar todas las páginas decidí usar un FragmentStatePagerAdapter en el que uno de mis fragmentos contiene una página.
Creé una interfaz para la comunicación entre cada fragmento en el busca y la actividad del padre. El método que necesito en esta interfaz es para actualizar una página mostrada en un fragmento, así que implementé la actividad padre, la interfaz para recibir los datos de un fragmento y almacenarlos en una página para guardarlos en la lista de arrays.
Cada fragmento tiene un EditText en el que el usuario puede escribir y yo configuro addTextChangedListener para captar el momento en que el usuario deja de escribir. Cuando el usuario se detiene a escribir en EditText, en onTextChanged (), invoco la función implementada en la actividad padre.
Este es mi código de actividad
public class BookEditorActivity implements BookEditorFragment.EditorFrToEditorActInterface {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.book_editor_activity);
Bundle extras = getIntent().getExtras();
b = (Book) extras.get("book");
setBookViewPager(b);
}
private void setBookViewPager(Book b) {
mBookViewPager = (ViewPager) findViewById(R.id.book_editor_pager);
mBookViewPagerAdapter = new BookViewPagerAdapter(getSupportFragmentManager(), b);
mBookViewPager.setAdapter(mBookViewPagerAdapter);
}
@Override
public void saveBookPageTextContent(String textContent) {
int current = mBookViewPager.getCurrentItem();
if (b.getPages().get(current) instanceof BookPageText) {
((BookPageText) b.getPages().get(current)).setContentPageText(textContent);
}
}
@Override
public void newBookPageText() {
int current = mBookViewPager.getCurrentItem();
BookPageText bookPageText = new BookPageText();
bookPageText.setContentPageText("");
b.getPages().add(b.getPages().size() - 1, bookPageText);
setIndicator(current + 1, b.getPages().size());
mBookViewPagerAdapter.notifyDataSetChanged();
}
}
Este es el código de fragmento
public class BookEditorFragment extends Fragment {
private EditorFrToEditorActInterface mCallback;
public interface EditorFrToEditorActInterface {
void newBookPageText();
void saveBookPageTextContent(String s);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle pageContent = getArguments();
if (pageContent != null) {
page = pageContent.getParcelable("page");
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (page instanceof BookPageText) {
BookPageText bookPage = (BookPageText) page;
mView = inflater.inflate(R.layout.book_page_text_fragment, container, false);
contentPage = (EditText) mView.findViewById(R.id.content_text);
String contentPageText = bookPage.getContentPageText();
contentPage.setText(contentPageText.isEmpty() ? "" : Html.fromHtml(contentPageText));
contentPage.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence c, int start, int before, int count) {
mCallback.saveBookPageTextContent(c.toString());
}
public void beforeTextChanged(CharSequence c, int start, int count, int after) {
}
public void afterTextChanged(Editable c) {
}
});
}
return mView;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
mCallback = (EditorFrToEditorActInterface) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement NewPageInterface");
}
}
@Override
public void onDetach() {
mCallback = null;
super.onDetach();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.editor_new_text:
mCallback.newBookPageText();
break;
}
}
}
Este es el código FragmentStatePagerAdapter
public class BookViewPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<Object> bookPages = new ArrayList<>();
private final SparseArray<WeakReference<BookEditorFragment>> instantiatedFragments = new SparseArray<>();
public BookViewPagerAdapter(FragmentManager fm, Book b) {
super(fm);
this.bookPages = b.getPages();
}
@Override
public Fragment getItem(int position) {
Object page = bookPages.get(position);
Bundle pageContent = new Bundle();
if (page instanceof BookPageText) {
BookPageText bookPageText = (BookPageText) page;
pageContent.putParcelable("page", bookPageText);
}
BookEditorFragment fragment = new BookEditorFragment();
fragment.setArguments(pageContent);
return fragment;
}
@Override
public int getCount() {
return bookPages.size();
}
@Override
public Object instantiateItem(final ViewGroup container, final int position) {
final BookEditorFragment fragment = (BookEditorFragment) super.instantiateItem(container, position);
instantiatedFragments.put(position, new WeakReference<>(fragment));
return fragment;
}
@Override
public void destroyItem(final ViewGroup container, final int position, final Object object) {
instantiatedFragments.remove(position);
super.destroyItem(container, position, object);
}
@Nullable
public Fragment getFragment(final int position) {
final WeakReference<BookEditorFragment> wr = instantiatedFragments.get(position);
if (wr != null) {
return wr.get();
} else {
return null;
}
}
@Override
public int getItemPosition(Object object) {
int position = bookPages.indexOf(object);
return position == -1 ? POSITION_NONE : position;
}
}
Debido a la longitud del código, eliminé algunas partes como onClickListener, onPageSelectionListener y otros tipos de páginas que estoy creando en este momento.
El problema
Esta lógica parece funcionar correctamente, pero cada vez que modifico el contenido de un EditText en un fragmento, el fragmento cercano a la izquierda también se actualiza y no sé por qué.
Como puede ver en la imagen, si escribo algo en EditText2, aparecerá el mismo contenido en EditText1 y esto no tiene sentido.
Otro problema es cuando agrego una nueva página en el libro, la página se crea correctamente, pero con el contenido de la página anterior y esto no tiene sentido. (¡de nuevo!)
Mis intentos
1) Intenté capturar el cambio enfoque en lugar de utilizar AddTextChangedListener, pero no cambió nada.
2) Intenté implementar una lógica diferente utilizando onChangePageListener()
, pero en este caso mBookViewPager.getCurrentItem()
por lo que la actualización falla.
3) Probé todas estas publicaciones: una , dos , tres y cuatro .
¿Cómo puedo corregir este extraño comportamiento? ¿Es posible que el problema esté en la forma en que hago referencia a las páginas en el ArrayList del libro?
Gracias
Algunos de los posibles errores que encontré en su implementación son.
para gestionar la implementación de la página actual implementar
mViewPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int p) { current = p; Log.e("Postion", "" + p); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) {} @Override public void onPageScrollStateChanged(int arg0) {} });
viewpager automáticamente carga privious y la siguiente vista para privent establece el buscapersonas OffscreenPageLimit llamando a mathod
mViewPager.setOffscreenPageLimit();
siempre asegúrese de que si está utilizando la instrucción
if
en el adaptador, debe poner su contraparte siempre a través de la instrucciónelse
incluso para cualquier valor predeterminado.if (page instanceof BookPageText) { BookPageText bookPageText = (BookPageText) page; pageContent.putParcelable("page", bookPageText); }