Введение
У меня есть действие с книгой, которая содержит список массивов типа «страница», и для обработки всех страниц я решил использовать FragmentStatePagerAdapter, в котором один из моих фрагментов содержит одну страницу.
Я создал интерфейс для связи между каждым фрагментом пейджера и родительской активностью. Метод, который мне нужен в этом интерфейсе, предназначен для обновления страницы, показанной во фрагменте, поэтому я реализовал отцовскую активность, интерфейс для получения данных из фрагмента и сохранения их на странице для сохранения в массиве.
У каждого фрагмента есть EditText, в котором пользователь может писать, и я установил addTextChangedListener, чтобы ловить момент, когда пользователь перестает писать. Когда пользователь перестает писать в EditText, в onTextChanged() я вызываю функцию, реализованную в отце активности.
Это мой код активности
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();
}
}
Это код фрагмента
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;
}
}
}
Это код 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;
}
}
Из-за длины кода я удалил некоторые части, такие как onClickListener, onPageSelectionListener и другие типы страниц, которые я создаю прямо сейчас.
Проблема
Эта логика, кажется, работает правильно, но каждый раз, когда я изменяю содержимое EditText во фрагменте, закрывающий фрагмент слева также обновляется, и я не знаю, почему.
Как вы можете видеть на изображении, если я напишу что-то в EditText2, то же самое содержимое появится в EditText1, и это не имеет смысла.
Еще проблема, когда добавляю новую страницу в книгу, страница создается корректно, но с содержимым предыдущей страницы и в этом нет смысла. (опять таки!)
Мои попытки
1) Я пытался поймать onFocusChange вместо использования addTextChangedListener, но ничего не изменилось.
2) Я попытался реализовать другую логику, используя onChangePageListener()
, но в этом случае я теряю mBookViewPager.getCurrentItem()
, поэтому обновление идет неправильно.
3) Я пробовал все эти сообщения: one, два, три и четыре.
Как я могу исправить это странное поведение? Возможно ли, что проблема в том, как я ссылаюсь на страницы в ArrayList книги?
Спасибо