LayoutManagerのプロセスをカスタマイズしますか?
3707 ワード
最近、Androidの毎日の知識グループに参加し、技術の漏れを補った.Androidは毎日
ちょうどカスタムLayoutManagerプロセスが見えますか?この問題は,これまでLayoutManagerのカスタム化が様々な効果をもたらすことを知っていたが,コードを引っ張って実践したことがない.この机会を借りて、勉强してみましょう.
参考ドキュメント:LayoutManagerの回転ギャラリーを作成し、カスタムRecyclerViewを参照してください.LayoutManager
最初の参考文書には詳細が明記されているので、私もそれに基づいて自分で一度やっただけで、コードは処理されず、流れだけを書いて、この知識点として記録します.
1.デフォルトのLayoutParamsオブジェクトを複写します.
generateDefaultLayoutParams().新しい継承クラスは書き直さなければなりません
2.複写子Viewの配置.
onLayoutChildren().各サブビューの配置位置を計算する必要があります.はaddView()を介してRecyclerViewにViewを追加します. measureChildWithMargins()は、viewのレイアウトを測定します. layoutDecorated()は、viewを本当に対応する位置に配置します.
3.RecyclerViewの水平または垂直スライドを許可する canscrollVertically()またはcanscrollHorizontally()の2つのデフォルトはfalseであり、スライドは許可されません. scrollVerticallyBy()は、全体スライド時のviewの回収表示を処理します.
4.キャッシュを追加して高速多重化
detachAndScrapAttachedViews()はすべて除去し、再追加(多重化)し、addView、measureChildWithMargins、layoutDecoratedでRecyclerViewに追加します.ここで使用する最も簡単な方法は、実際には、現在表示されている集合を作って、スライドに基づいて1つ追加すると、性能が高くなりますが、本質は同じで、多重化されています.
遭遇した小さなピットは、RecyclerViewが高さのwrap_を設定しているためcontent、子Viewを表示できなくなり、match_に設定parentの可視化.理由:wrap_contentはLayoutManagerでonMeasure()の場合、そのmodeはAT_MOST.AT_MOSTはRecyclerViewにあります.onMeasure()の場合、defalutOnMeasure()を使用します.この関数は、高さの実際に取る最小値を取得し、miniHeight、padingtop padingbuttonを設定していないと、必ず0になります.これがwrap_contentが表示されない理由.
解決方法:LayoutManagerのonMeasureで、そのModeと高さを強制的に修正すればよい.変更内容:
ちょうどカスタムLayoutManagerプロセスが見えますか?この問題は,これまでLayoutManagerのカスタム化が様々な効果をもたらすことを知っていたが,コードを引っ張って実践したことがない.この机会を借りて、勉强してみましょう.
参考ドキュメント:LayoutManagerの回転ギャラリーを作成し、カスタムRecyclerViewを参照してください.LayoutManager
最初の参考文書には詳細が明記されているので、私もそれに基づいて自分で一度やっただけで、コードは処理されず、流れだけを書いて、この知識点として記録します.
1.デフォルトのLayoutParamsオブジェクトを複写します.
generateDefaultLayoutParams().新しい継承クラスは書き直さなければなりません
2.複写子Viewの配置.
onLayoutChildren().各サブビューの配置位置を計算する必要があります.
3.RecyclerViewの水平または垂直スライドを許可する
4.キャッシュを追加して高速多重化
detachAndScrapAttachedViews()はすべて除去し、再追加(多重化)し、addView、measureChildWithMargins、layoutDecoratedでRecyclerViewに追加します.ここで使用する最も簡単な方法は、実際には、現在表示されている集合を作って、スライドに基づいて1つ追加すると、性能が高くなりますが、本質は同じで、多重化されています.
遭遇した小さなピットは、RecyclerViewが高さのwrap_を設定しているためcontent、子Viewを表示できなくなり、match_に設定parentの可視化.理由:wrap_contentはLayoutManagerでonMeasure()の場合、そのmodeはAT_MOST.AT_MOSTはRecyclerViewにあります.onMeasure()の場合、defalutOnMeasure()を使用します.この関数は、高さの実際に取る最小値を取得し、miniHeight、padingtop padingbuttonを設定していないと、必ず0になります.これがwrap_contentが表示されない理由.
void defaultOnMeasure(int widthSpec, int heightSpec) {
// calling LayoutManager here is not pretty but that API is already public and it is better
// than creating another method since this is internal.
final int width = LayoutManager.chooseSize(widthSpec,
getPaddingLeft() + getPaddingRight(),
ViewCompat.getMinimumWidth(this));
final int height = LayoutManager.chooseSize(heightSpec,
getPaddingTop() + getPaddingBottom(),
ViewCompat.getMinimumHeight(this));
setMeasuredDimension(width, height);
}
public static int chooseSize(int spec, int desired, int min) {
final int mode = View.MeasureSpec.getMode(spec);
final int size = View.MeasureSpec.getSize(spec);
switch (mode) {
case View.MeasureSpec.EXACTLY:
return size;
case View.MeasureSpec.AT_MOST:
return Math.min(size, Math.max(desired, min));
case View.MeasureSpec.UNSPECIFIED:
default:
return Math.max(desired, min);
}
}
解決方法:LayoutManagerのonMeasureで、そのModeと高さを強制的に修正すればよい.変更内容:
//LayoutManager.onMeasure()
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
final int heightMode = View.MeasureSpec.getMode(heightSpec);
int height = View.MeasureSpec.getSize(heightSpec);
if (heightMode == View.MeasureSpec.AT_MOST) {
if(totalHeight == 0){
for (int i = 0; i < getItemCount(); i++) {
View viewItem = recycler.getViewForPosition(i);
measureChildWithMargins(viewItem, 0, 0);
int w = getDecoratedMeasuredWidth(viewItem);
int h = getDecoratedMeasuredHeight(viewItem);
totalHeight +=h;
}
}
if(totalHeight< height){
height = totalHeight;
}
height = (height & ~(0x3 << 30)) | (View.MeasureSpec.EXACTLY & (0x3 << 30));
}
super.onMeasure(recycler, state, widthSpec, height);
}