Guardar / Actualizar los datos de EditText del fragmento en un FragmentStatePagerAdapter
Introducción
Tengo una actividad con un libro que contiene un arraylist de tipo "página" y para manejar todas las páginas que he decidido utilizar un FragmentStatePagerAdapter en el que uno de mi fragmento contiene una página.
- Quitar todos los fragmentos de ViewPager poblados por FragmentStatePagerAdapter
- Ver Pager Crash Null Pointer Excepción debido a navegar de nuevo al fragmento antiguo - Android
- FragmentStatePageAdapter: Múltiples elementos visibles al mismo tiempo - ¿Cómo centrar una página específica?
- Cambio de la imagen de fondo del fragmento actual en viewpager
- Refrescar vista de fragmentos mientras utiliza FragmentStatePagerAdapter
Creé una interfaz para la comunicación entre cada fragmento en el buscapersonas 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 hice implementar a la actividad padre, la interfaz para recibir los datos de un fragmento y almacenarlos en una página para guardar en el arraylist.
Cada fragmento tiene un EditText en el que el usuario puede escribir y establecer un addTextChangedListener para capturar el momento en que el usuario deja de escribir. Cuando el usuario deja de escribir en el EditText, en el onTextChanged (), llamo a la función implementada en el padre de la actividad.
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 del 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 he eliminado algunas partes como el onClickListener, onPageSelectionListener y otros tipos de páginas que estoy creando ahora mismo.
El problema
Esta lógica parece funcionar correctamente, pero cada vez que modifico el contenido de un EditText en un fragmento, el fragmento de cierre a la izquierda también se actualiza y no sé por qué.
Como se puede ver en la imagen, si escribo algo en el EditText2, el mismo contenido aparecerá en el 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é coger el onFocusChange en vez de usar el addTextChangedListener, pero nada cambió.
2) He intentado implementar una lógica diferente usando el onChangePageListener()
, pero en este caso mBookViewPager.getCurrentItem()
el mBookViewPager.getCurrentItem()
para que la actualización salga mal.
3) He intentado esto todo esto puestos: uno , dos , tres y cuatro .
¿Cómo puedo corregir este comportamiento extraño? ¿Es posible que el problema está en la forma en que las páginas de referencia en la ArrayList del libro?
Gracias
- Comunicación entre Fragmentos en ViewPager
- No se puede crear una instancia del tipo PagerAdapter
- ViewPager no se actualiza con FragmentStatePagerAdapter
- Fragmento getView () siempre devuelve null para Fragments creado por un FragmentStatePagerAdapter
- ListFragment no vuelve a mostrar datos al llamar desde FragmentStatePagerAdapter
- FragmentStatePagerAdapter OutOfMemoryError
- FragmentPagerAdapter y FragmentStatePagerAdapter
- Diferencia entre FragmentPagerAdapter y FragmentStatePagerAdapter
Algunos de los posibles errores que encontré en su implementación son.
-
Gestionar la página actual posetion 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 carga automáticamente la vista privious y siguiente a privent que establece pager OffscreenPageLimit llamando a mathod
mViewPager.setOffscreenPageLimit();
-
Siempre asegúrese de que si está utilizando la instrucción
if
en el adaptador, debe poner su contra parte siempre a través de la sentenciaelse
, incluso para cualquier valor por defecto.if (page instanceof BookPageText) { BookPageText bookPageText = (BookPageText) page; pageContent.putParcelable("page", bookPageText); }
- Inicio de sesión de Facebook: finaliza un error de hash de clave no válido, al intentar iniciar sesión de nuevo
- ¿Cómo puedo utilizar ACTION_VOICE_SEARCH_HANDS_FREE en Android 4.1?