7

Wprowadzeniedane EditText zapisać/Aktualizacja fragment jest w FragmentStatePagerAdapter

Mam aktywności z książką, która zawiera ArrayList typu „strona”, a do obsługi wszystkich stron postanowiłem użyć FragmentStatePagerAdapter w których jeden mojego fragmentu zawiera jedną stronę.

Stworzyłem interfejs do komunikacji między każdym fragmentem w pagera i działaniem ojca. Metoda, której potrzebuję w tym interfejsie, służy do aktualizacji strony wyświetlanej w fragmencie, dlatego wprowadziłem implementację do działania ojca, interfejs do odbierania danych z fragmentu i zapisywania ich na stronie, aby zapisać ją na liście.

Każdy fragment ma EditText, w którym użytkownik może pisać i ustawiam addTextChangedListener, aby wychwycić moment, w którym użytkownik przestaje pisać. Gdy użytkownik przestaje pisać w EditText, w onTextChanged(), wywołuję funkcję zaimplementowaną w ojcu aktywności.

To jest mój kod aktywność

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(); 

    } 
} 

Jest to fragment kodu

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; 
     } 
    } 

} 

Jest to kod 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; 
    } 
} 

Ze względu na długość kodu usunąłem kilka części jak onClickListener, onPageSelectionListener i inne typy stron, które tworzę poprawnie teraz.

Problem

Ta logika wydaje się działać poprawnie, ale za każdym razem, zmodyfikować treść w EditText we fragmencie, bliski fragment po lewej stronie jest również aktualizowana i nie wiem czemu.

enter image description here
Jak widać na obrazku, jeśli napiszę coś w EditText2, ta sama zawartość pojawi się w EditText1 i to nie ma sensu.

Innym problemem jest dodanie nowej strony do książki, strona jest tworzona poprawnie, ale z zawartością poprzedniej strony i to nie ma sensu. (Znowu!)

Moje próby

1) Próbowałem złapać onFocusChange zamiast używania addTextChangedListener, ale nic się nie zmieniło.

2) Próbowałem zaimplementować inną logikę za pomocą onChangePageListener(), ale w tym przypadku tracę mBookViewPager.getCurrentItem(), więc aktualizacja się nie udała.

3) Próbowałem to wszystkie posty: one, two, three i four.

Jak mogę poprawić to dziwne zachowanie? Czy to możliwe, że problem leży w sposobie odwoływania się do stron w ArrayList książki?

Dzięki

+0

można podać link do swojego kodu. Trudno replikować za pomocą kodu dostarczonego przez ciebie –

Odpowiedz

0

Niektóre z możliwych błędów znalazłem w swojej wdrożeniowymi jesteśmy.

  1. zarządzać bieżącą stronę posetion wdrożyć

    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) {} 
         }); 
    
  2. viewpager automatycznie załadować ciągu poprzedniego i następnego widoku do privent to ustawić pagera OffscreenPageLimit wywołując Mathod

    mViewPager.setOffscreenPageLimit(); 
    
  3. zawsze upewnić się, że jeśli używasz instrukcji if w adapterze, powinieneś umieścić jej część liczącą zawsze vi instrukcja else nawet dla dowolnej wartości domyślnej.

    if (page instanceof BookPageText) { 
        BookPageText bookPageText = (BookPageText) page; 
        pageContent.putParcelable("page", bookPageText); 
    } 
    
+0

Wprowadziłem zmiany, które zaproponowałeś, ale nic się nie zmieniło ... Czy to możliwe, że problem dotyczy obiektu modelu? Myślałem o tym, ponieważ dla uratowania mojej książki stworzyłem klasę, która implementuje "Serializable", a wewnątrz klasy mam odniesienie do innej klasy, która implementuje "Serializable" i "Parcelable". Za każdym razem, gdy pobieram i zapisuję książkę, znajduje się ona w pliku/z pliku. – michoprogrammer

+0

tak, może tak być, możesz przekazywać dane przez EventBus zamiast Serializable lub Parcable. jeśli chcesz przechowywać te dane, użyj Gson, aby przekonwertować model na ciąg i zapisać ten ciąg do preferencji, możesz pobrać ten ciąg i przekonwertować go do obiektu modelu za pomocą Gson. – RBK

+0

Zacząłem wczoraj w nowym oddziale konwersję do wersji json i mam nadzieję, że to byłby właściwy wybór. Nie wiem, gdzie mogę korzystać z EventBus lub dlaczego używam EventBus zamiast zwykłego pakietu. – michoprogrammer