Introduzionedi Save/Aggiornamento Frammento dati EditText in un FragmentStatePagerAdapter
ho un'attività con un libro che contiene un ArrayList di tipo "pagina" e per gestire tutte le pagine che ho deciso di utilizzare un FragmentStatePagerAdapter in cui si del mio frammento contiene una pagina.
Ho creato un'interfaccia per la comunicazione tra ogni frammento nel cercapersone e l'attività padre. Il metodo di cui ho bisogno in questa interfaccia è per l'aggiornamento di una pagina mostrata in un frammento, quindi ho implementato l'attività padre, l'interfaccia per ricevere i dati da un frammento e memorizzarli in una pagina per salvarli nell'array.
Ogni frammento ha un EditText in cui l'utente può scrivere e ho impostato un addTextChangedListener per catturare il momento in cui l'utente si ferma a scrivere. Quando l'utente si ferma a scrivere in EditText, in onTextChanged(), chiamo la funzione implementata nel padre dell'attività.
Questo è il mio codice di attività
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();
}
}
Questo è il frammento di codice
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;
}
}
}
Questo è il codice 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;
}
}
A causa della lunghezza del codice ho rimosso alcune parti come onClickListener, onPageSelectionListener e altri tipi di pagine che sto creando correttamente adesso.
Il problema
Questa logica sembra funzionare correttamente, ma ogni volta che modifico il contenuto di un EditText in un frammento, il frammento vicino alla sinistra viene aggiornato e non so perché.
Come si può vedere nell'immagine, se scrivo qualcosa nel EditText2, lo stesso contenuto apparirà nel EditText1 e questo non ha senso.
Un altro problema è quando aggiungo una nuova pagina nel libro, la pagina è creata correttamente, ma con il contenuto della pagina precedente e questo non ha senso. (Di nuovo!)
I miei tentativi
1) Ho cercato di prendere l'onFocusChange invece di utilizzare l'addTextChangedListener, ma non è cambiato nulla.
2) Ho provato a implementare una logica diversa utilizzando lo onChangePageListener()
, ma in questo caso perdo lo mBookViewPager.getCurrentItem()
in modo che l'aggiornamento non funzioni.
3) Ho provato questo tutti i post: one, two, three e four.
Come posso correggere questo strano comportamento? È possibile che il problema sia nel modo in cui faccio riferimento alle pagine nell'ArrayList del libro?
Grazie
può fornire link al tuo codice. È difficile da replicare con il codice fornito da te –