12

私のアダプタで問題が発生しています。私は、次のようにグリッドに表示画像の選択を持っている:私はアイテムの単一画面分を持っており、彼らはすべての罰金を表示するときこれがうまく機能RecyclerView - 最初のレイアウトパスをスキップするオフスクリーンアイテム

enter image description here

。下にスクロールする項目がさらにある場合に問題が発生します。私は、さらに項目が空白で表示され、下にスクロールするとき最初に、GridLayoutコンテナがあると、画像を表示するためのコードが実行されますが、ここで示したように、彼らが画面に表示されません。

The problem

私はスクロールするとバックアップ、そして再び下方向にスクロールし、画像が本来あるべき場所を正確に表示されます。

enter image description here

私はレイアウトを更新したり、何かが変更されたレンダラを伝える必要がありますように思えるが、私がしようと、何も思いません何をするにも。私はrequestLayoutinvalidateを呼び出そうとしましたが、問題を解決していないようです。私はGlobalOnLayoutListenerも登録しましたが、これ以上はうまくいきませんでした。ここで

は、関連するコードです:

これは私のonBindViewHolder方法

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(); 
       } 
    }); 
} 

これは私が画像をレイアウトするために使用する方法であるからです。基本的には、不規則なグリッド内に画像を配置するので、長い画像や大きい画像がある場合、その画像は空き領域に応じて完全な行または完全な列を占めようとします。私はのparam幅と高さを設定した理由は、そうピカソが.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); 
     } 
    } 
} 

なぜこれが最初に表示項目のための第1のレンダリングパスでないうちスキップするように見えるのでしょうか?

EDIT:リファクタリングを少しして、新しいものを削除/作成するのではなく、イメージビューを再利用して、それらのアイテムに追加されたビューがonLayoutChangeコールバックを取得しないことを知りました。他のすべてのアイテムはonLayoutChangeコールバックを取得し、前と同じように、最初にコールを取得しないアイテムは、スクロールしてスクロールした後に取得します。参照:

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); 
       } 
      }); 

編集:ここでは11月15日

がviewholderレイアウトのXMLあなたが指定するgetItemId(int position)をオーバーライドする必要があることを行う場合は、setHasStableIds(true)を持っているかどうかを

<?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

誰かがこの質問のより良いタイトルを考えることができるなら、それを自由に編集してください –

+0

'onBindViewHolder'が呼び出されるたびに、' GridView'からすべてのイメージが置き換えられますか?どうして? – rubenlop

+0

1つのアイテムのレイアウトには1〜4の画像がありますので、アイテムがリサイクルされたときにオーバーハングが発生します。私はImageViewsのリストを保持して、リサイクルされたときに見えなくなるように設定することができたと思うが、スクロールのパフォーマンスはまあまあだったので、レンダリングの問題よりもそれほど気にならなかった。 –

答えて

-1

チェックです各ビューのID。それをしないと、次のonBindViewholders()コールはトリガーされず、ビューは更新されません。

+0

'setStableIds()'がtrueに設定されていません。 'onBindViewHolder'メソッドは正しく質問されているように呼び出されますが、イメージビューはonLayout呼び出しを取得しません。ビューホルダーのその他の情報は正しいです。 –

0

あなたはtrおそらくあなたはRecyclerViewクラスの使用を検討すべきでしょう。この方法で、LayoutManagerを利用して写真をより簡単にレイアウトすることができます。これは、レイアウトが標準のグリッド(幅と高さが一定である)ではないため、より良いものになります。カスタムLayoutManagerの興味深い例は、hereです。

+0

これはRecyclerViewを使用しています。それぞれのViewHoldersにはGridLayoutがあります。 –

+0

RecyclerViewの中のGridLayoutは少し残忍なようです。カスタムレイアウトマネージャを使用してRecyclerViewを使用する場合、サイズが異なる複数の要素を1行にまとめることができます。私の場合は、テスト目的のために、GridViewを取り除き、単純なものに置き換えたり、複雑なレイアウトを使わずにGridViewのみを使用したりすることで、作業を簡単にすることから始めます。もう一つの選択肢はピカソをグライドに置き換えることです(やはり排除の目的のためです)。 –

0

完全なコードがないので、私は推測することができます。最初にリサイクルアダプタをスクロールすると、グリッドがビューを作成して追加する前にビューを作成するように見えます。グリッドビューを作成するために別のアダプタ、つまりグリッドアダプタを使用していればうまくいくはずです。

私はあなたのリサイクラビューでスクロールを検出するためにonScrollListenerを使用しています。次にグリッドごとにグリッドアダプタを使用してより多くのグリッドをロードします。

関連する問題