2017-02-22 35 views
6

Tôi đã tạo một RecyclerView bên trong một NavigationView với một mục đầu tiên tùy chỉnh tương đương với ListView's addHeaderView(). Ở phần dưới cùng của bố cục tiêu đề đó, tôi đã đặt EditText để tôi có thể lọc ra danh sách bên dưới.Làm thế nào để buộc RecyclerView cuộn khi không có đủ các mục để lấp đầy chiều cao của sceen

Điều tôi muốn làm là cuộn RecyclerView cho đến khi EditText là mục trên cùng bất cứ khi nào EditText tăng tiêu điểm. Tuy nhiên nếu số mục của tôi đủ nhỏ để nó không thể lấp đầy toàn bộ chiều cao của NavigationView, RecyclerView từ chối di chuyển tất cả các con đường lên và do đó hiển thị thêm một chút tiêu đề khác với EditText. Là một vấn đề được thêm vào, ngay cả khi danh sách đủ lớn, nó vẫn cuộn xuống khi tôi bắt đầu lọc các mục trong danh sách.

Làm thế nào tôi có thể buộc RecyclerView vẫn cuộn hết cỡ ngay cả khi tôi không có đủ mục để lấp đầy chiều cao của phần xem để phần còn lại của tiêu đề không nhìn trộm?

Dưới đây là một hình dung về những gì tôi đang cố gắng để đạt được:

_______________ 
| HEADER LINE 1 | 
| HEADER LINE 2 | 
| HEADER LINE 3 | 
| ------------- | 
| Search box | 
| ------------- | 
| List item 1 | 
| List item 2 | 
| List item 3 | 
--------------- 

hành vi dự kiến ​​khi tôi tập trung vào hộp tìm kiếm:

_______________ 
| ------------- | 
| Search box | <- becomes the topmost item. I can already achieve this 
| ------------- | with RecyclerView.smoothScrollBy(dx, dy) 
| List item 1 | except when the list is small enough (see below) 
| List item 2 | 
| List item 3 | 
| List item 4 | 
|    | <- empty space is okay and is desired if dataset 
|    | is small enough 
--------------- 

Điều gì thực sự xảy ra:

_______________ 
| HEADER LINE 2 | <- the header is 'bleeding' on top 
| HEADER LINE 3 | 
| ------------- | 
| Search box | <- search box cannot take the topmost spot 
| ------------- |  as the recycler tries to position itself to fill in 
| List item 1 |  the bottom part with items 
| List item 2 | 
| List item 3 | 
| List item 4 | <- items are pushed down to the bottom to fill 
---------------  in the space 

Đây là đoạn trích xView NavigationView của tôi (chỉ cần thiết lập thông thường của bạn):

<android.support.design.widget.NavigationView 
    android:id="@+id/navigation_view" 
    android:layout_width="wrap_content" 
    android:layout_height="match_parent" 
    android:layout_gravity="start" 
    android:fitsSystemWindows="true"> 
    <android.support.v7.widget.RecyclerView 
     android:id="@+id/drawer_content" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 
</android.support.design.widget.NavigationView> 

ViewHolder với tiêu đề tùy chỉnh ở đây (RecyclerView Adaptor):

@Override 
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    if(viewType == HEADER) { 
     return new HeaderHolder(mHeaderView); 
    } else { 
     View v = LayoutInflater.from(parent.getContext()) 
       .inflate(R.layout.list_item, parent, false); 

     return new ItemViewHolder(v); 
    } 
} 

Tiêu đề ngăn kéo chỉ là một bố cục xml tôi phồng lên trong hoạt động chính (Tôi phân công người nghe và hình ảnh động có) và truyền lại cho tôi Bộ điều hợp RecyclerView thông qua setHeaderView (Xem tiêu đề) Tôi đã thực hiện.

+0

đã thử điều này? Đó là hiệu quả khác nhau cùng một kết quả. https://stackoverflow.com/questions/26568087/parallax-header-effect-with-recyclerview –

+0

Đã thấy điều đó. Tiêu đề của tôi có các điều khiển trong nó (bao gồm cả bố cục có thể mở rộng) do đó hiệu ứng thị sai sẽ làm hỏng nó. Không phải đề cập đến việc sử dụng một thư viện cho nó sẽ là overkill như tôi đã thực hiện một tiêu đề tùy chỉnh trong RecyclerView của tôi thành công. Đó chỉ là vị trí cuộn là vấn đề – dmonloz

+0

Hãy thử thay đổi chiều cao của chế độ xem tái chế thành 'wrap_content'. –

Trả lời

1

Điều bạn cần là chân trang có cùng chiều cao với tiêu đề của bạn.

Có hai kịch bản để xem xét ở đây:

  1. tiêu đề của bạn có một chiều cao cố định
  2. tiêu đề của bạn có một chiều cao năng động

Trong trường hợp đầu tiên, giải pháp là rất đơn giản .Chỉ cần xác định chiều cao của tiêu đề của bạn trong một số giá trị như <dimen name="header_height">300dp</dimen> và sau đó xác định tiêu đề của bạn và chân trang như sau:

<FrameLayout 
    android:layout_height="@dimen/header_height"> 

    <!-- Content goes here --> 

</FrameLayout> 

Trong trường hợp thứ hai, chúng ta sẽ phải làm một vài điều:

  • Lấy chiều cao của tiêu đề bất cứ khi nào nó thay đổi
  • cập nhật chiều cao của chân đến bất kỳ giá trị chiều cao của tiêu đề là

có ar e rất nhiều cách để làm điều này. Một trong những cách mà tôi đã sử dụng trước đây là bạn có thể sử dụng ViewTreeObserver.OnPreDrawListener trên RecyclerView để phát hiện khi tiêu đề có chiều cao (và sau đó nếu nó đã thay đổi) và sau đó vượt qua chiều cao đó cho RecyclerView.Adapter của bạn sẽ sử dụng nó để đặt yêu cầu chiều cao cho footer của bạn khi nó thổi phồng nó, và sau đó bạn chỉ cần gọi notifyItemChanged(int) trên bộ chuyển đổi với chỉ mục chân của bạn để cho nó làm tăng thêm chân trang của bạn. Dưới đây là hầu hết những gì tôi vừa mô tả trong mã:

final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.drawer_content); 
recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 
    @Override 
    public boolean onPreDraw() { 
     if(recyclerView.getChildCount() < 1 || recyclerView.getChildAt(0) == null || recyclerView.getChildAt(0).getHeight() == 0) { 
      return true; 
     } 

     int headerHeight = recyclerView.getChildAt(0).getHeight(); 
     adapter.setFooterHeight(headerHeight); 

     return true; 
    } 
}); 

Và trong bộ chuyển đổi của bạn:

int footerHeight = 0; 

public void setFooterHeight(int footerHeight){ 
    if(this.footerHeight == footerHeight){ 
     return; 
    } 

    this.footerHeight = footerHeight; 
    notifyItemChanged(getItemCount() - 1); 
} 

Và sau đó chỉ là điều khác bạn cần phải làm là thổi phồng chân của bạn như bạn là tiêu đề của bạn đã và đặt chiều cao thành footerHeight.

Hy vọng điều này sẽ hữu ích.

+0

Điều này gần như đã được phát hiện. Tôi có một tiêu đề thay đổi kích thước động. Thiết lập chiều cao footer và sau đó notifyItemChanged messes lên các hình ảnh động của danh sách khi nó thay đổi xuống. Tôi đã thực hiện một số chỉnh sửa. Đã có một cái nhìn trống cho footer mà tôi gọi là spacer. Tôi đặt kích thước thành 'recyclerVIew.getHeight() - (mItemHeight * (getItemCount() - 2))' Vì vậy, nó sẽ luôn lấp đầy màn hình trong trường hợp các mục danh sách không đủ để lấp đầy màn hình (chiều cao tiêu đề không liên quan). Tôi đặt chiều cao miếng đệm mỗi khi danh sách được cập nhật. Cảm ơn bạn đã chỉ cho tôi đúng hướng. :) – dmonloz

Các vấn đề liên quan