12

Tôi gặp sự cố với một trong các bộ điều hợp của mình. Tôi có một lựa chọn các hình ảnh mà tôi hiển thị trong một mạng lưới như sau:RecyclerView - các mục bên ngoài màn hình bỏ qua bố trí đầu tiên vượt qua

enter image description here

này hoạt động tốt khi tôi có một giá trị màn hình duy nhất của các mặt hàng và tất cả họ đều hiển thị tốt. Sự cố xuất hiện khi có nhiều mục để cuộn xuống. Ban đầu khi tôi di chuyển xuống thấp hơn nữa các mục xuất hiện trống, GridLayout container đang có và mã để hiển thị những hình ảnh được chạy, nhưng họ không xuất hiện trên màn hình như ở đây:

The problem

Nếu tôi di chuyển trở lên, sau đó di chuyển xuống một lần nữa, những hình ảnh xuất hiện chính xác nơi họ sẽ:

enter image description here

Nó có vẻ như tôi cần phải làm mới bố trí hoặc cho các renderer rằng một cái gì đó đã thay đổi, nhưng không có gì tôi cố gắng dường như để làm bất cứ điều gì. Tôi đã thử gọi requestLayoutinvalidate nhưng dường như không giải quyết được vấn đề. Tôi cũng đã đăng ký GlobalOnLayoutListener, nhưng điều đó không có giá nào tốt hơn.

Đây là mã có liên quan:

Đây là từ phương pháp onBindViewHolder tôi

final GridLayout grid = ((KKAlbumViewHolder) holder).mGridLayout; 
grid.removeAllViews(); 
int width = grid.getWidth(); 
if(width > 0) { 
    albumHolder.setPreviewImages(posts); 
}else { 
    albumHolder.itemView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
       @Override 
       public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
        albumHolder.itemView.removeOnLayoutChangeListener(this); 
        albumHolder.setPreviewImages(posts); 
        albumHolder.mGridLayout.invalidate(); 
       } 
    }); 
} 

Đây là phương pháp tôi sử dụng để bố trí các hình ảnh. Về cơ bản nó đưa hình ảnh ra trong một lưới bất thường, vì vậy nếu có một hình ảnh dài hoặc cao, hình ảnh đó sẽ cố gắng chiếm một hàng đầy đủ hoặc một cột đầy đủ tùy thuộc vào không gian là miễn phí. Lý do tôi thiết lập chiều rộng và chiều cao param như vậy picasso không phàn nàn về phương pháp .fit():

public void setPreviewImages(ArrayList<KKPost> posts) { 
     Picasso picasso = Picasso.with(itemView.getContext()); 

     int space = 0; 
     int tl = 1 << 0; 
     int tr = 1 << 1; 
     int bl = 1 << 2; 
     int br = 1 << 3; 
     int lCol = tl | bl; 
     int rCol = tr | br; 
     int tRow = tl | tr; 
     int bRow = bl | br; 
     int full = lCol | rCol; 
     boolean hasLongImage = false; 
     for(KKPost post : posts) { 
      if(space == full){ 
       break; 
      } 

      int margin = 2; 

      ImageView view = new ImageView(itemView.getContext()); 
      GridLayout.LayoutParams param = new GridLayout.LayoutParams(); 
      view.setBackgroundColor(Color.LTGRAY); 
      if(posts.size() < 4){ 
       param.columnSpec = GridLayout.spec(0, 2); 
       param.rowSpec = GridLayout.spec(0, 2); 
       param.width = mGridLayout.getWidth(); 
       param.height = mGridLayout.getHeight(); 
       mGridLayout.addView(view, param); 
       picasso.load(post.url).fit().centerCrop().into(view); 
       break; 
      } 

      if (post.aspectRatio >= 1.2 && !hasLongImage) { 
       //landscape 
       if((space & tRow) == 0){ 
        param.rowSpec = GridLayout.spec(0, 1); 
        param.columnSpec = GridLayout.spec(0, 2); 
        param.height = mGridLayout.getHeight()/2; 
        param.width = mGridLayout.getWidth(); 
        param.bottomMargin = margin; 
        space |= tRow; 
        mGridLayout.addView(view, param); 
        picasso.load(post.url).fit().centerCrop().into(view); 
        hasLongImage = true; 
        continue; 
       } 
       if((space & bRow) == 0){ 
        param.rowSpec = GridLayout.spec(1, 1); 
        param.columnSpec = GridLayout.spec(0, 2); 
        param.height = mGridLayout.getHeight()/2; 
        param.width = mGridLayout.getWidth(); 
        param.topMargin = margin; 
        space |= bRow; 
        mGridLayout.addView(view, param); 
        picasso.load(post.url).fit().centerCrop().into(view); 
        hasLongImage = true; 
        continue; 
       } 
      } else if (post.aspectRatio <= 0.8 && post.aspectRatio > 0 && !hasLongImage) { 
       //portrait 
       if((space & lCol) == 0){ 
        param.columnSpec = GridLayout.spec(0, 1); 
        param.rowSpec = GridLayout.spec(0, 2); 
        param.height = mGridLayout.getHeight(); 
        param.width = mGridLayout.getWidth()/2; 
        param.rightMargin = margin; 
        space |= lCol; 
        mGridLayout.addView(view, param); 
        picasso.load(post.url).fit().centerCrop().into(view); 
        hasLongImage = true; 
        continue; 
       } 
       if((space & rCol) == 0){ 
        param.columnSpec = GridLayout.spec(1, 1); 
        param.rowSpec = GridLayout.spec(0, 2); 
        param.height = mGridLayout.getHeight(); 
        param.width = mGridLayout.getWidth()/2; 
        param.leftMargin = margin; 
        space |= rCol; 
        mGridLayout.addView(view, param); 
        picasso.load(post.url).fit().centerCrop().into(view); 
        hasLongImage = true; 
        continue; 
       } 
      } 
      //square or no space or unknown 
      if((space & tl) == 0){ 
       param.columnSpec = GridLayout.spec(0,1); 
       param.rowSpec = GridLayout.spec(0,1); 
       space |= tl; 
       param.bottomMargin = margin; 
       param.rightMargin = margin; 
      }else 
      if((space & tr) == 0) { 
       param.columnSpec = GridLayout.spec(1,1); 
       param.rowSpec = GridLayout.spec(0,1); 
       space |= tr; 
       param.bottomMargin = margin; 
       param.leftMargin = margin; 
      }else 
      if((space & bl) == 0){ 
       param.columnSpec = GridLayout.spec(0,1); 
       param.rowSpec = GridLayout.spec(1,1); 
       space |= bl; 
       param.rightMargin = margin; 
       param.topMargin = margin; 
      }else 
      if((space & br) == 0){ 
       param.columnSpec = GridLayout.spec(1,1); 
       param.rowSpec = GridLayout.spec(1,1); 
       space |= br; 
       param.leftMargin = margin; 
       param.topMargin = margin; 
      } 
      param.height = mGridLayout.getHeight()/2; 
      param.width = mGridLayout.getWidth()/2; 
      mGridLayout.addView(view, param); 
      picasso.load(post.url).fit().centerCrop().into(view); 
     } 
    } 
} 

Tại sao dường như này để bỏ ra trên đèo vẽ đầu tiên cho các mục không rõ ràng ban đầu?

EDIT: Tôi đã làm imageviews một chút refactoring vì vậy tôi có thể tái sử dụng thay vì loại bỏ/tạo mới và đã phát hiện ra rằng những quan điểm được bổ sung đối với những mặt hàng không nhận được một cuộc gọi lại onLayoutChange. Tất cả các mục khác nhận được cuộc gọi lại onLayoutChange và như trước đây, các mục không nhận được cuộc gọi ban đầu, nhận được nó sau khi tôi cuộn lên và cuộn xuống một lần nữa. Xem:

view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
       @Override 
       public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
        view.removeOnLayoutChangeListener(this); 
        picasso.load(post.url).into(view); 
       } 
      }); 

Edit: Tháng Mười Một 15

Đây là xml cho bố trí viewholder

<?xml version="1.0" encoding="utf-8"?> 
<android.support.v7.widget.CardView 
    android:id="@+id/album_card_view" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center" 
    card_view:cardCornerRadius="@dimen/feed_card_corner_radius" 
    card_view:cardElevation="@dimen/cardview_default_elevation" 
    card_view:cardMaxElevation="@dimen/cardview_default_elevation" 
    card_view:cardUseCompatPadding="true" 
    xmlns:autofit="http://schemas.android.com/apk/res-auto" 
    xmlns:app="http://schemas.android.com/apk/res-auto"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical"> 

     <android.support.percent.PercentRelativeLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:id="@+id/percent_layout"> 

      <GridLayout 
       android:background="@color/white" 
       android:id="@+id/preview_grid_layout" 
       android:columnCount="2" 
       android:rowCount="2" 
       android:alignmentMode="alignBounds" 
       android:layout_height="0dp" 
       android:layout_width="0dp" 
       app:layout_widthPercent="100%" 
       app:layout_aspectRatio="100%"> 

      </GridLayout> 

     </android.support.percent.PercentRelativeLayout> 

     <LinearLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:padding="@dimen/card_padding_4dp" 
      android:orientation="vertical"> 

      <TextView 
       android:id="@+id/album_title" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       tools:text="Family Photos"/> 

     </LinearLayout> 

    </LinearLayout> 

</android.support.v7.widget.CardView> 
+0

Nếu bất cứ ai có thể nghĩ ra một tiêu đề tốt hơn cho câu hỏi này, hãy chỉnh sửa nó –

+0

Mỗi lần 'onBindViewHolder' được gọi là bạn đang thay thế tất cả hình ảnh từ' GridView'? Tại sao? – rubenlop

+0

Cũng có thể có bất cứ nơi nào từ 1-4 hình ảnh trong bố trí cho bất kỳ mục duy nhất, vì vậy khi các mặt hàng đã tái chế nó sẽ dẫn đến một số nhô ra. Tôi đoán tôi có thể giữ một danh sách các ImageViews và sau đó chỉ cần thiết lập chúng để tầm nhìn biến mất khi chúng được tái chế, nhưng hiệu suất của cuộn là đủ phong nha, vì vậy tôi ít phiền toái hơn vấn đề hiển thị –

Trả lời

-1

Kiểm tra xem bạn có setHasStableIds(true), nếu bạn làm điều đó, bạn phải ghi đè getItemId(int position) để xác định id cho mỗi lượt xem.Nếu bạn không làm điều đó, các cuộc gọi onBindViewholders() tiếp theo sẽ không được kích hoạt và chế độ xem của bạn sẽ không được cập nhật

+0

'setStableIds()' không được đặt thành true. Phương thức 'onBindViewHolder' được gọi chính xác như nó nói trong câu hỏi của tôi, nhưng các khung nhìn hình ảnh không nhận được các cuộc gọi onLayout. Thông tin khác trên trình xem là chính xác. –

0

Khi bạn là tr ying để tạo một danh sách có lẽ bạn nên cân nhắc sử dụng lớp RecyclerView. Bằng cách này, bạn sẽ có thể sử dụng LayoutManager để bố trí ảnh của bạn dễ dàng hơn. Điều này có thể tốt hơn vì bố cục của bạn không phải là lưới tiêu chuẩn (có chiều rộng và chiều cao cột cố định). Một ví dụ thú vị để xem xét cho một LayoutManager tùy chỉnh có thể được tìm thấy here.

+0

Điều này đang sử dụng RecyclerView. Mỗi ViewHolders có một GridLayout bên trong nó –

+0

GridLayout bên trong RecyclerView có vẻ hơi giống như một overkill. Bạn có thể có nhiều phần tử có kích thước khác nhau trong một dòng khi sử dụng RecyclerView với trình quản lý bố cục tùy chỉnh. Nếu tôi là bạn, tôi sẽ bắt đầu bằng cách cố gắng làm mọi việc đơn giản hơn (hoặc loại bỏ GridView và thay thế nó bằng một cái gì đó đơn giản hơn hoặc chỉ sử dụng GridView mà không có bố trí phức tạp xung quanh nó). Một lựa chọn khác là thay thế Picasso bằng Glide (một lần nữa cho mục đích loại bỏ). –

0

Vì mã hoàn chỉnh không có ở đó nên tôi có thể đoán. Có vẻ như khi bạn cuộn bộ điều hợp recycler lần đầu tiên tạo ra các khung nhìn trước khi lưới có cơ hội tạo và thêm các khung nhìn. Tôi đoán nếu bạn sử dụng một bộ điều hợp khác, ví dụ: bộ điều hợp lưới để điền vào chế độ xem lưới của bạn, nó sẽ hoạt động tốt.

Tôi đang nhảy bạn đang sử dụng onScrollListener cho chế độ xem tái chế của bạn để phát hiện cuộn và sau đó tải thêm lưới mà lần lượt tải nhiều mục lưới hơn thông qua bộ điều hợp lưới cho mỗi và mọi lưới.

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