2016-09-05 22 views
8

Zaimplementowałem BottomSheet przy użyciu podejścia DialogFragment. Mam TabLayout i ViewPager w BottomSheet. Model ViewPager zawiera 2 strony, z których każda nadpisuje numer RecyclerView. Pierwsza (karta Kawowa) RecyclerView przewija się dobrze. Problemem, który mam teraz, jest to, że dla drugiej (zakładka Mleko) zwój nie działa. Każdy pomysł, jak mogę to naprawić? Dzięki!Przewiń nie działa dla wielu widoków z odzysku w BottomSheet

można przetestować z projektem demonstracyjnym stworzyłem tutaj: https://github.com/choongyouqi/bottomsheet `

enter image description here

+0

Im nie zagrać jej pompowania poprawnie. Czy masz ustawione na pionowe? – MNM

+0

Sprawdź moją odpowiedź poniżej nie ma żadnej dodatkowej biblioteki używanej, nie ma błędów, jak podano w innych odpowiedziach, po prostu sprawdź mój kod 'Static Fragment' i zastosuj to do twojego. –

+0

Możliwy duplikat [Android ViewPager z RecyclerView działa nieprawidłowo w BottomSheet] (http://stackoverflow.com/questions/37715822/android-viewpager-with-recyclerview-works-incorrectly-inside-bottomsheet) – Vitaly

Odpowiedz

6

Jak wspomniałem przez R. Zagórskiego, opisałem przyczynę tego przewijanego zachowania here, tj. BottomSheetBehavior obsługuje tylko jedno przewijane dziecko. Jednak ta odpowiedź nie koncentrowała się na oknach dialogowych dolnego arkusza.

Dlatego - podobnie jak R. Zagórski - rozszerzyłem swój własny library, który pokonuje to ograniczenie. Począwszy od 0.0.3 jest obsługa okien dialogowych na dole arkusza! Można znaleźć bibliotekę i przykład aplikację tutaj: https://github.com/laenger/ViewPagerBottomSheet

do wykorzystania w projekcie, wystarczy dodać repo maven url do build.gradle:

repositories { 
    maven { url "https://raw.github.com/laenger/maven-releases/master/releases" } 
} 

Dodaj bibliotekę z zależnościami:

dependencies { 
    compile "biz.laenger.android:vpbs:0.0.3" 
} 

Użyj ViewPagerBottomSheetDialogFragment jako super klasy dla fragmentów okna dialogowego. Potem setup dowolny ViewPager wewnątrz zawartości widoku:

public class DialogFragment extends ViewPagerBottomSheetDialogFragment { 
    @Override 
    public void setupDialog(Dialog dialog, int style) { 
     super.setupDialog(dialog, style); 
     final View contentView = View.inflate(getContext(), R.layout.dialog_bottom_sheet, null); 

     final ViewPager viewPager = (ViewPager) contentView.findViewById(R.id.viewpager); 
     // ... 
     BottomSheetUtils.setupViewPager(viewPager); 

     dialog.setContentView(contentView); 
    } 
} 

sample implementation

3

Gdy próbuje szukać problemu na StackOverflow znalazłem this thread. Przedstawia błąd (przynajmniej tak na niego patrzę), że BottomSheetBehaviour działa tylko dla pierwszego przewijanego dziecka, które znajduje. Proponuje również użycie różnych proponowanych i opublikowanych here.

Jednak twoja sprawa jest trochę inna. BottomSheetDialogFragment jest używany. I w tym przypadku dostarczone rozwiązanie nie działa. Jednak udało mi się przełamać ten problem. Opublikowano repository, gdzie Twój projekt został zmodyfikowany, aby działał. Korzysta z ViewPagerBottomSheetBehavior z biblioteki wspomnianej wcześniej.

Zasadniczo, wprowadzono następujące zmiany:

  1. StatisticFragment rozciąga ViewPagerBottomSheetDialogFragment i nie BottomSheetDialogFragment
  2. Funkcja onCreateDialog w StatisticsFragment ulega zmianie:

    @NonNull 
    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
        ViewPagerBottomSheetDialog dialog = (ViewPagerBottomSheetDialog) super.onCreateDialog(savedInstanceState); 
        View rootView = View.inflate(getContext(), R.layout.sheet_main, null); 
        viewPager = (ViewPager) rootView.findViewById(R.id.viewpager); 
        tabLayout = (TabLayout) rootView.findViewById(R.id.tabs); 
        dialog.setContentView(rootView); 
        mBehavior = ViewPagerBottomSheetBehavior.from((View) rootView.getParent()); 
        mBehavior.setPeekHeight(400); 
        if (viewPager != null && tabLayout != null) { 
         initViewPager(); 
        } 
        return dialog; 
    } 
    
  3. Poniższa funkcja jest wywoływana na the ViewPager:

    BottomSheetUtils.setupViewPager(viewPager); 
    

I to wszystko. Projekt działa.

Poniższy odbywa się za kulisami:

BottomSheetDialogFragment ma tylko jedną metodę:

@Override 
public Dialog onCreateDialog(Bundle savedInstanceState) { 
    return new BottomSheetDialog(getContext(), getTheme()); 
} 

Nie jest zwracana BottomSheetDialog. Jednak jego zachowanie zdefiniowane statycznie to BottomSheetBehavior. Trzeba było przesłonić ViewPagerBottomSheetDialogFragment, aby zwrócić ViewPagerBottomSheetDialog, gdzie jest CoordinatorLayout.Behavior ustawiona na ViewPagerBottomSheetBehavior. Również niestandardowy BottomSheet był potrzebny do nadpisania, aby przyzwyczaić się do ViewPagerBottomSheetBehavior.

+0

to nie działa dla mnie: (Mogę tylko przewijać elementy pierwszego elementu strony widoku. Jest to ten sam problem z tą biblioteką zbyt –

0

nie trzeba rozciąga StatisticFragment jak ViewPagerBottomSheetDialogFragment lub nie ma potrzeby korzystania z dowolnej biblioteki na to.

to ty kod mam tylko kilka zmian w swojej Static Fragment związanych View Pager.

Oto Statistic Fragment, w którym dokonano zmian.

Nie ma żadnych błędów, jak stwierdzono we wszystkich powyższych Odpowiedzi.

Należy zamienić ten kod na stary Static fragment tylko na inne zmiany, które dadzą pożądane dane wyjściowe.

Wprowadziłem tylko zmiany z Twoim View Pager i sprawiłem, że działał tak, jak chcesz. używana metoda OnPageChangeListener po prostu uzyskaj ten widok.

Statystyki Fragment.java

public class StatisticFragment extends BottomSheetDialogFragment { 

     private BottomSheetBehavior mBehavior; 
     private TabLayout tabLayout; 
     private ViewPager viewPager; 

     @NonNull 
     @Override 
     public Dialog onCreateDialog(Bundle savedInstanceState) { 
      BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState); 
      View rootView = View.inflate(getContext(), R.layout.sheet_main, null); 

      viewPager = (ViewPager) rootView.findViewById(R.id.viewpager); 
      tabLayout = (TabLayout) rootView.findViewById(R.id.tabs); 
      if (viewPager != null && tabLayout != null) { 
       initViewPager(); 
      } 

      final ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() { 

       @Override 
       public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 

       } 

       @Override 
       public void onPageSelected(int arg0) { 
        // TODO Auto-generated method stub 
        View view = viewPager.findViewWithTag(arg0); 
        if (view == null) { 
         return; 
        } 
        CustomPagerAdapter adapter = new CustomPagerAdapter(getContext()); 
        viewPager.setAdapter(adapter); 
        viewPager.setOffscreenPageLimit(10); 
        tabLayout.setupWithViewPager(viewPager); 
       } 

       @Override 
       public void onPageScrollStateChanged(int state) { 

       } 
      }; 

      viewPager.addOnPageChangeListener(pageChangeListener); 
      viewPager.post(new Runnable() { 
       @Override 
       public void run() { 
        pageChangeListener.onPageSelected(viewPager.getCurrentItem()); 
       } 
      }); 


      dialog.setContentView(rootView); 
      mBehavior = BottomSheetBehavior.from((View) rootView.getParent()); 
      return dialog; 


     } 

     private void initViewPager() { 
      CustomPagerAdapter adapter = new CustomPagerAdapter(getContext()); 
      viewPager.setAdapter(adapter); 
      viewPager.setOffscreenPageLimit(10); 
      tabLayout.setupWithViewPager(viewPager); 

     } 

     @Override 
     public void onStart() { 
      super.onStart(); 
      //mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); 
      //mBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); 
     } 

     public class ServiceVideHolder extends RecyclerView.ViewHolder { 
      protected ViewGroup mItemView; 
      protected TextView mNameView; 
      protected TextView mCodeView; 

      public ServiceVideHolder(View v) { 
       super(v); 
       //rootView = v; 
       mItemView = (ViewGroup) v.findViewById(R.id.item); 
       mNameView = (TextView) v.findViewById(R.id.main_text); 
       mCodeView = (TextView) v.findViewById(R.id.sub_text); 
      } 
     } 

     public class ItemViewHolder extends RecyclerView.ViewHolder { 
      protected TextView mMainText; 
      protected TextView mSubText; 

      public ItemViewHolder(View v) { 
       super(v); 
       mMainText = (TextView) v.findViewById(R.id.main_text); 
       mSubText = (TextView) v.findViewById(R.id.sub_text); 
      } 
     } 

     public class ItemAdapter extends RecyclerView.Adapter<ItemViewHolder> { 
      private List<Item> items; 

      public ItemAdapter(List<Item> items) { 
       this.items = items; 
      } 

      @Override 
      public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { 
       View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false); 
       return new ItemViewHolder(view); 
      } 

      @Override 
      public void onBindViewHolder(final ItemViewHolder viewHolder, final int position) { 
       final Item item = items.get(position); 
       viewHolder.mMainText.setText(item.name); 
       viewHolder.mSubText.setText(item.value); 
       viewHolder.mMainText.setTextColor(ResourcesCompat.getColor(getResources(), position % 2 == 0 ? R.color.md_red_500 : R.color.md_blue_500, null)); 
      } 

      @Override 
      public int getItemCount() { 
       return items.size(); 
      } 
     } 

     class ViewPagerAdapter extends FragmentPagerAdapter { 
      private final List<Fragment> mFragmentList = new ArrayList<>(); 
      private final List<String> mFragmentTitleList = new ArrayList<>(); 

      public ViewPagerAdapter(FragmentManager manager) { 
       super(manager); 
      } 

      @Override 
      public Fragment getItem(int position) { 
       return mFragmentList.get(position); 
      } 

      @Override 
      public int getCount() { 
       return mFragmentList.size(); 
      } 

      public void addFrag(Fragment fragment, String title) { 
       mFragmentList.add(fragment); 
       mFragmentTitleList.add(title); 
      } 

      @Override 
      public CharSequence getPageTitle(int position) { 
       return mFragmentTitleList.get(position); 
      } 
     } 

     public class CustomPagerAdapter extends PagerAdapter { 

      private Context mContext; 

      public CustomPagerAdapter(Context context) { 
       mContext = context; 
      } 

      @Override 
      public Object instantiateItem(ViewGroup collection, int position) { 
       //CustomPagerEnum customPagerEnum = CustomPagerEnum.values()[position]; 
       LayoutInflater inflater = LayoutInflater.from(mContext); 
       ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.adapter, collection, false); 
       rootView.setTag(position); 


       Toast.makeText(mContext, "Inside Instanciate Item", Toast.LENGTH_SHORT).show(); 

       //View rootView = View.inflate(getContext(), R.layout.adapter, null); 
       final RecyclerView mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view); 
       ArrayList<Item> items = new ArrayList<>(); 

       if (position == 0) { 
        items.add(new Item("Coffee 1", "1")); 
        items.add(new Item("Coffee 2", "2")); 
        items.add(new Item("Coffee 3", "3")); 
        items.add(new Item("Coffee 4", "4")); 
        items.add(new Item("Coffee 5", "5")); 
        items.add(new Item("Coffee 6", "6")); 
        items.add(new Item("Coffee 7", "7")); 
        items.add(new Item("Coffee 8", "8")); 
        items.add(new Item("Coffee 9", "9")); 
        items.add(new Item("Coffee 10", "10")); 
       } else { 
        items.add(new Item("Milk 1", "1")); 
        items.add(new Item("Milk 2", "2")); 
        items.add(new Item("Milk 3", "3")); 
        items.add(new Item("Milk 4", "4")); 
        items.add(new Item("Milk 5", "5")); 
        items.add(new Item("Milk 6", "6")); 
        items.add(new Item("Milk 7", "7")); 
        items.add(new Item("Milk 8", "8")); 
        items.add(new Item("Milk 9", "9")); 
        items.add(new Item("Milk 10", "10")); 
       } 

       final ItemAdapter mAdapter = new ItemAdapter(items); 

       mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); 
       mRecyclerView.setNestedScrollingEnabled(false); 
       mRecyclerView.setAdapter(mAdapter); 
       Paint paint = new Paint(); 
       paint.setStrokeWidth(1); 
       paint.setColor(ResourcesCompat.getColor(getResources(), R.color.md_grey_500, null)); 
       paint.setAntiAlias(true); 
       paint.setPathEffect(new DashPathEffect(new float[]{25.0f, 25.0f}, 0)); 
       mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).showLastDivider().paint(paint).build()); //.marginResId(R.dimen.leftmargin, R.dimen.rightmargin) 

       collection.addView(rootView); 


       return rootView; 
      } 

      @Override 
      public void destroyItem(ViewGroup collection, int position, Object view) { 
       collection.removeView((View) view); 
      } 

      @Override 
      public int getCount() { 
       return 2; 
      } 

      @Override 
      public boolean isViewFromObject(View view, Object object) { 
       return view == object; 
      } 

      @Override 
      public CharSequence getPageTitle(int position) { 
       //CustomPagerEnum customPagerEnum = CustomPagerEnum.values()[position]; 
       return position == 0 ? "Coffee" : "Milk"; 
      } 

     } 
    } 

to zrobić.

enter image description here

+1

straci stan przewijania z poprzedniej strony, ponieważ właśnie odtwarzasz adapter i ponowne powiązanie z tablayout za każdym razem, gdy użytkownik przesunie palcem w lewo/prawo nie tylko jest brudny i drogi, ale powoduje migotanie podczas przesyłania strony.) Właściwie szukam rozwiązania, które przeniesie zdarzenie/obliczenia 'fling' do aktywnej strony widoku. –

0

można użyć 2 RecyclerView w CoordinatorLayout.

<android.support.design.widget.CoordinatorLayout 
     android:id="@+id/mainBottomSheet" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:background="@color/white"> 

     <android.support.v7.widget.RecyclerView 
        android:id="@+id/recyclerViewRight" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" /> 

     <android.support.v7.widget.RecyclerView 
        android:id="@+id/recyclerViewLeft" 
        android:layout_width="200dp" 
        android:layout_height="match_parent" /> 

</android.support.design.widget.CoordinatorLayout> 

sprawdzić ten post link