2016-11-13 38 views
6

BottomSheet içinde ListView ve ListView ekranı doldurmak ve daha da fazla kaydırmak için yeterli öğeye sahip bir sorun yaşadım.BottomSheet'de Liste Görünümü

Aşağı kaydırdığımda, her şey işe yarayacak gibi görünüyor, ancak geri kaydırma yapmaya çalıştığımda, BottomSheet kendisini kaydırıyordu ve yalnızca ListView'u kaydırmak yerine görünümü kapatıyordu.

Bir süre sonra bir çözüm bulabildim ve burada herhangi bir yerde bulamadığım için burada yayınlayacağımı düşündüm.

cevap

13

çözüm böyle ListView uzatmaktır:

düzeninizin dosyasında bottom_sheet_view.xml yılında Sonra
public class BottomSheetListView extends ListView { 
    public BottomSheetListView (Context context, AttributeSet p_attrs) { 
     super (context, p_attrs); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     return true; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     if (canScrollVertically(this)) { 
      getParent().requestDisallowInterceptTouchEvent(true); 
     } 
     return super.onTouchEvent(ev); 
    } 

    public boolean canScrollVertically (AbsListView view) { 
     boolean canScroll = false; 

     if (view !=null && view.getChildCount()> 0) { 
      boolean isOnTop = view.getFirstVisiblePosition() != 0 || view.getChildAt(0).getTop() != 0; 
      boolean isAllItemsVisible = isOnTop && view.getLastVisiblePosition() == view.getChildCount(); 

      if (isOnTop || isAllItemsVisible) { 
       canScroll = true; 
      } 
     } 

     return canScroll; 
    } 
} 

: nihayet Sonra

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <com.mypackage.name.BottomSheetListView 
     android:id="@+id/listViewBtmSheet" 
     android:divider="@color/colorPrimary" 
     android:dividerHeight="1dp" 
     android:layout_weight="1" 
     android:layout_width="match_parent" 
     android:layout_height="0dp" /> 

</LinearLayout> 

, senin Activity/Fragment:

BottomSheetDialog dialog = new BottomSheetDialog(context); 
dialog.setContentView(R.layout.bottom_sheet_view); 

BottomSheetListView listView = (BottomSheetListView) dialog.findViewById(R.id.listViewBtmSheet); 
// apply some adapter - add some data to listview 

dialog.show(); 

Bu birsağlayacaktır, ListView kaydırma ile tamamen çalışıyor. Eğer ListView genişletmek istemiyorsanız

+0

hey dostum, güzel çözüm, ancak liste öğeleri tıklanabilir değil, bunun için herhangi bir hack değil? – sUndeep

+0

@sUndeep öğeleri benim için tıklanabilir. Liste öğesi düzeninde "ImageView" veya "Button" var mı? Eğer öyleyse, 'android: descendantFocusability = "blocksDescendants" 'list öğesi düzeninin –

+0

kök elemanına eklemelisiniz, android yazmadan yaptım: descendantFocusability =" blocksDescendants ". Ama biraz daha iyileştirmeye ihtiyacı var. Ben yorum – sUndeep

3
public class BottomSheetListView extends ListView { 

    public BottomSheetListView(Context context, AttributeSet attributeSet) { 
     super(context, attributeSet); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent motionEvent) { 
     View view = (View) getChildAt(getChildCount() - 1); 

     int diffBottom = (view.getBottom() - (getHeight() + getScrollY())); 
     if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 
      if (diffBottom == 0) { 
       return false; 
      } 
     } 

     /*//Need more improvement on this logic. Do not uncomment 
     int diffTop = (view.getTop() - (getHeight() + getScrollY())); 
     if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 
      if (diffTop < 0) { 
       return true; 
      } 
     }*/ 

     return super.onInterceptTouchEvent(motionEvent); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent motionEvent) { 
     if (canScrollVertically(this)) { 
      getParent().requestDisallowInterceptTouchEvent(true); 
     } 
     return super.onTouchEvent(motionEvent); 
    } 

    public boolean canScrollVertically(AbsListView absListView) { 

     boolean canScroll = false; 

     if (absListView != null && absListView.getChildCount() > 0) { 

      boolean isOnTop = absListView.getFirstVisiblePosition() != 0 || absListView.getChildAt(0).getTop() != 0; 
      boolean isAllItemsVisible = isOnTop && getLastVisiblePosition() == absListView.getChildCount(); 

      if (isOnTop || isAllItemsVisible) 
       canScroll = true; 
     } 

     return canScroll; 
    } 
} 
+0

@ th3pat3l koddaki yorumumu kontrol edin. eğer bunu geliştirebilirseniz, o zaman bu harika olur, tamam ben yönetirim. http://stackoverflow.com/questions/32631547/pass-motion-event-to-parent-scrollview-when-listview-at-top-bottom adresinden fikir aldım – sUndeep

2

daha iyi bir yaklaşım vardır: Ben biraz kesmek olduğunu biliyorum

//in onCreate 

_listView.setOnTouchListener(new ListView.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       int action = event.getAction(); 
       switch (action) { 
        case MotionEvent.ACTION_DOWN: 
         // Disallow NestedScrollView to intercept touch events. 
         v.getParent().requestDisallowInterceptTouchEvent(true); 
         break; 

        case MotionEvent.ACTION_UP: 
         // Allow NestedScrollView to intercept touch events. 
         v.getParent().requestDisallowInterceptTouchEvent(false); 
         break; 
       } 

       // Handle ListView touch events. 
       v.onTouchEvent(event); 
       return true; 
      } 
     }); 
0

ama benim için çalıştı ve hatta liste görünümü seçilebilir. Bildiğimiz gibi, alt tabaka değiştiğinde durumunu dinleyicide yakalayabileceğini bildiğimiz için liste görünümü en üstte dokunmuyorsa durumu değiştirmeyin, bundan sonra dokunma olayı liste görünümüne geçecek ve olduğu gibi çalışacaktır.

mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback(){ 
@Override 
public void onStateChanged(View bottomSheet, int newState) { 
     if (newState == BottomSheetBehavior.STATE_DRAGGING && !listIsAtTop()){ 
      mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); 
     } 
} 
@Override 
public void onSlide(View bottomSheet, float slideOffset) {}}); 

public boolean listIsAtTop() { 
    if(tripListView.getChildCount() == 0) return true; 
    return (tripListView.getChildAt(0).getTop() == 0 && tripListView.getFirstVisiblePosition() ==0); 
}