1

BottomSheetBehavior가있는 LinearLayout 안에 두 개의 RecyclerView가 있습니다. 첫 번째 RecyclerView 안의 항목 (격자가있는)을 클릭하면 RecyclerView가 Gone으로 설정되고 두 번째 RecyclerView (목록 있음)가 표시됩니다. 두 번째 Recycler가 표시되면 BottomSheet를 위아래로 밀어 넣을 수 없습니다. 대신 목록이 펼쳐진 상태에서도 스크롤됩니다. First Recycler가 작동되면 모든 것이 정상입니다. BottomSheet를 위아래로 슬라이드 할 수있는 방법이 있습니까?두 개의 RecyclerView가있는 BottomSheetBehavior

<LinearLayout 
     android:id="@+id/sliding_layout_container" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:focusable="true" 
     android:focusableInTouchMode="true" 
     android:orientation="vertical" 
     app:behavior_hideable="false" 
     app:behavior_peekHeight="400dp" 
     app:layout_behavior="@string/bottomSheetBehavior"> 

     <android.support.v7.widget.RecyclerView 
      android:id="@+id/grid" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:layout_marginEnd="@dimen/activity_horizontal_margin" 
      android:layout_marginStart="@dimen/activity_horizontal_margin" 
      android:background="@color/white" 
      android:clickable="true" 
      android:scrollbars="none" /> 

     <android.support.v7.widget.RecyclerView 
      android:id="@+id/list" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:layout_marginEnd="@dimen/activity_horizontal_margin" 
      android:layout_marginStart="@dimen/activity_horizontal_margin" 
      android:background="@color/white" 
      android:clickable="true" 
      android:scrollbars="none" /> 
</LinearLayout> 

GridAdapter :

@Override 
    public void onBindViewHolder(ViewHolder holder, int position) { 

    String categorieName = mCategories.get(position); 
    final CategoryFilterEvent event = new CategoryFilterEvent(categorieName); 
    holder.grid_item_label.setText(categorieName); 

    holder.itemView.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      EventBus.getDefault().post(event); 
     } 
    }); 
} 

MainActivity :

@Override 
public void onCreate(Bundle savedInstanceState) { 

    linearLayoutManager = new LinearLayoutManager(this); 
    listAdapter = new ListAdapter(this, mList); 
    recyList.setAdapter(listAdapter); 
    recyList.setLayoutManager(linearLayoutManager); 

    gridLayoutManager = new GridLayoutManager(this, 3); 
    gridAdapter = new GridAdapter(this, new ArrayList<String>()); 
    recyGrid.setAdapter(gridAdapter); 
    recyGrid.setLayoutManager(gridLayoutManager); 
} 

public void onEventMainThread(CategoryFilterEvent event) { 
    recyGrid.setVisibilty(GONE); 
    recyList.setVisiblity(VISIBLE); 
} 
+0

손가락으로 슬라이드하면 하단 시트가 위아래로 이동한다는 문제가 있다고 생각하지만 리사이틀보기가 하단 시트 안쪽으로 들어가면 손가락으로 문질러 대는 동작이 리사이클 뷰에서 사용됩니다. 나는 당신이 밑바닥 시트의 내부에 리시버 뷰를 넣는 것이 문제라고 생각한다. –

+0

하지만 첫 번째 RecyclerView에서는 완벽하게 작동합니다. – elpatricko

+0

일부 코드를 공유 –

답변

4

이 레이아웃은 상자 밖으로 "작동하지 않습니다 이유는 내부에 두 개의 스크롤 뷰를 지원하지 않습니다 BottomSheetBehavior의 구현은, 그건 ". 그러나 해커가 있지만이 문제에 대한 간단한 해결 방법이 있습니다. 먼저 클래스의 코드를 새로운 CustomBottomSheetBehavior 클래스에 복사하여 맞춤 BottomSheetBehavior를 만들어야합니다. 수정 "onLayoutChild"방법을

if (mNestedScrollingChildRef == null) { 
    mNestedScrollingChildRef = new WeakReference<>(findScrollingChild(child)); 
} 

와 라인

mNestedScrollingChildRef = new WeakReference<>(findScrollingChild(child)); 

을 대체하여보다 mNestedScrollingChildRef이 BottomSheetBehavior 클래스의 패키지 수준의 액세스 권한을 가지고, 그래서 우리는 그것을 확장 할 수있는 방법이 없습니다.

보다가, 다음과 같은 방법을 추가

public void setNestedScrollingChildRef(View v) { 
    this.mNestedScrollingChildRef = new WeakReference<View>(v); 
} 

을 그리고 당신의 활동 클래스 :

RecyclerView recyGrid = (RecyclerView)findViewById(R.id.grid); 
RecyclerView recyList = (RecyclerView)findViewById(R.id.list); 
layout = (LinearLayout)findViewById(R.id.sliding_layout_container); 

recyGrid.addOnItemTouchListener(onItemTouchListener); 
recyList.addOnItemTouchListener(onItemTouchListener); 

onItemTouchListener 코드 :

모든 터치 이벤트를 잡는 우리가 여기서 할
RecyclerView.OnItemTouchListener onItemTouchListener = new RecyclerView.OnItemTouchListener() { 
    @Override 
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 
     setScrollable(layout, rv); 
     return false; 
    } 

    @Override 
    public void onTouchEvent(RecyclerView rv, MotionEvent e) { 

    } 

    @Override 
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { 

    } 
}; 

private void setScrollable(View bottomSheet, RecyclerView recyclerView){ 
    ViewGroup.LayoutParams params = bottomSheet.getLayoutParams(); 
    if (params instanceof CoordinatorLayout.LayoutParams) { 
     CoordinatorLayout.LayoutParams coordinatorLayoutParams = (CoordinatorLayout.LayoutParams) params; 
     CoordinatorLayout.Behavior behavior = coordinatorLayoutParams.getBehavior(); 
     if (behavior != null && behavior instanceof CustomBottomSheetBehavior) 
      ((CustomBottomSheetBehavior)behavior).setNestedScrollingChildRef(recyclerView); 
    } 
} 

, recyclerView에 와서 mNestedScrollingChildRef로 CustomBottomSheetBehavior에 추가합니다. cl 엉덩이, 그래서 모든 스크롤 이벤트가 올바른 방법으로 처리 할 수 ​​있습니다. BottomSheetDialogFragment이 방법을 사용 2018년 2월 27일 의

업데이트는 더 복사 붙여 넣기를 포함한다. AppCompatDialog를 확장하고 BottomSheetDialog 클래스의 모든 코드를 복사하는 CustomBottomSheetDialog를 만들어야합니다. 클래스 변수 mBehavior를 위에서 설명한 CustomBottomSheetBehavior로 변경합니다.

그런 다음,이 새로운 동작을 설정하려면 "wrapInBottomSheet"방법을 수정

ViewGroup.LayoutParams bottomSheetParams = bottomSheet.getLayoutParams(); 
    if (bottomSheetParams instanceof CoordinatorLayout.LayoutParams) { 
     mBehavior = new CustomBottomSheetBehavior<>(); 
     mBehavior.setBottomSheetCallback(mBottomSheetCallback); 
     mBehavior.setHideable(mCancelable); 
     mBehavior.setPeekHeight(*some value here*); 
     ((CoordinatorLayout.LayoutParams) bottomSheetParams).setBehavior(mBehavior); 
    } 

그리고 당신의 조각 클래스 오버라이드 "이 onCreateDialog"방법

이 CustomBottomSheetDialog을 사용 :

@NonNull 
    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
    CustomBottomSheetDialog dialog = new CustomBottomSheetDialog (getActivity(), R.style.YourDialogTheme); 
    dialog.setContentView(R.layout.bottom_sheet_page_fragment); 

    RecyclerView recyGrid = (RecyclerView)dialog.findViewById(R.id.grid); 
    RecyclerView recyList = (RecyclerView)dialog.findViewById(R.id.list); 
    layout = (LinearLayout)dialog.findViewById(R.id.sliding_layout_container); 

    recyGrid.addOnItemTouchListener(onItemTouchListener); 
    recyList.addOnItemTouchListener(onItemTouchListener); 
    return dialog; 
    } 

의 나머지를 코드는 동일하게 유지됩니다.

+0

어떻게 이것을 BottomSheetDialogFragment에 사용합니까? –

+0

@RasoulMiri이 답변을 BottomSheetDialogFragment와 함께 사용하는 방법을 설명하기 위해 편집했습니다. – anro

관련 문제