web-dev-qa-db-ja.com

"onBindViewHolder"でrecyclerviewのアイテムの高さを取得する方法

RecyclerViewのアイテムの高さは固定ではありません、iすべてのアイテムに背景画像を設定する必要があるため、recyclerviewのアイテムの高さを取得して画像のサイズを変更しますが、itemView.getHeight()は常にonBindViewHolderで0を返します。

私は多くの質問や記事を検索しようとしましたが、それでも良い解決策を得ることができません。

18
zys

ショート

ビューを手動で測定する

view.measure(
             View.MeasureSpec.makeMeasureSpec(recyclerViewWidth, View.MeasureSpec.EXACTLY),
             View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

view.getMeasuredHeight()で高さを取得します

背景

ビューは、測定後にのみView.getHeight()に有効な値を返します。ビューが画面に表示される直前に、システムによって測定自体が自動的に行われます。

Androidがレイアウトを表示したい場合、ビューツリー内の各ビューに対してview.layout()関数を再帰的に呼び出します。各親は、子が持つ可能性のある制約(幅/高さ)そして、それらにview.measure()を要求します。その結果、ビューは測定値を保存します[〜#〜] based [〜#〜]指定されたメンバーの制約(MeasuredHeight/Width):この時点で、view.getMeasuredHeight()は値を保持しますが、view.getHeight()は引き続き無効です。view.getHeight()は有効な値のみを返します。ビューがUI階層で実際の高さになると。

要約

したがって、ビュー要素の高さを知るには、システムによって測定およびレイアウトされる前に、view.measure()関数を手動で呼び出す必要があります。

Measure関数は、ビューLayoutParams +親制約から派生した2つのパラメーターを予期します。

上記のサンプルコードでは、ビューの幅を強制的に測定しています[〜#〜] exactly [〜#〜]親(RecycleView)の幅で、高さは制限されていません。

32
Eyal Biran

予想される高さで複数のレイアウトファイルを定義し、データセットのいくつかの基準に従ってそれらを拡張することをお勧めします。

ViewHolder onCreateViewHolder (ViewGroup parent, int viewType){
  if(some condition){
    //inflate layout 1
  }else{
    //inflate layout 2
 }

または回答通り ここ :ビューホルダーを初期化しながら測定値を取得できます

itemView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int width = itemView.getMeasuredWidth();
int height = itemView.getMeasuredHeight();
11
Mina Samy

このコードを使用して、リサイクラビューのアイテムの高さを取得します。

view.getViewTreeObserver().addOnGlobalLayoutListener(new 
         ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        //don't forget remove this listener
        view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        //get item height here
        int itemHeight = v.getHeight();
    }
});
1
Tinfu

これはどう:

view.post(() -> {
   int width = view.getMeasuredWidth();
   int height = view.getMeasuredHeight();
}
1
Oleg Shevchenko

MyViewHolder.kt

addOnGlobalLayoutListener()メソッドを使用すると、TextViewが描画される前に高さの値が取得されます。そして、それをメンバー変数に保存します。

キーは、リスナーの実装の内外でUIを変更することです。これにより、レンダリングの問題が発生しません(ビューが再描画される場合)。

つまり、リスナー内でゲッターを使用する必要があります。リスナーの内側と外側のセッター。

companion object {

    var maxHeight: Int = 0

    fun create(mContext: Context): MyViewHolder {
        val view = LayoutInflater.from(mContext).inflate(R.layout.item_answer, null)

        updateLayout(view)

        view.viewTreeObserver.addOnGlobalLayoutListener {

            if (view.myTextView.height > maxHeight)
                maxHeight = view.myTextView.height

            updateLayout(view)

        }

        return MyViewHolder(mContext, view).apply {
            setIsRecyclable(false)
        }
    }

    fun updateLayout(view: View) {
        if (maxHeight != 0 && view.myTextView.height != maxHeight) 
            view.myTextView.height = maxHeight
    }


}

GL

ソース

0
CORONEL Braian