ScrollView嵌套RecyclerView⾼度⾃适应,item显⽰不全问题昨天遇到个超级头疼的问题,弄了⼀整天了 才解决,本来简简单单的 ,可是查了 百度CSDN 什么的之后,好像被误导了,,
最近我们APP 改版,⾸页风格⼤变,布局什么的都得改动,新的功能呢 ,就是⽤到了 RecyclerView ,因为是⾸页 显⽰的数据就⽐较少,固定的五条数据 也就是五个 item,
本⾝⾸页 东西也⽐较多,需要滑动 两个屏幕 才能 看完⾸页, 问题就来了,ScrollView 滑动嘛,,下边的 5条数据就⽤了 RecyclerView ,完了 ,就显⽰四条半 数据,最后⼀个item 死活显⽰不完全,,就查啊 找啊,,有的说是RecyclerView 的 23.1.0 的包的问题,换成23.2.0 就好了,有的说 RecyclerView ⾼度⾃适应 ,有的说 是重写 LinearLayoutManager onMeasure ⽅法,,,拿过来之后 ,问题依旧存在,还是解决不了,
可能⼤家遇到的问题是⼀样的 但是原因可能不⼀样,,反正就是不能盲⽬的去解决,,。
最后 实在 没办法了,,靠⾃⼰吧,,,毕竟 listview GridView 也遇到过类似的情况,,,
说⼀下 我的 解决⽅案吧 ,
⾸先 : RecyclerView ⾼度⾃适应 ,
<android.support.v7.widget.RecyclerView
android:id="@+id/home__recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"shoe
android:scrollbars="none"/>
也有的说 需要嵌套⼀个相对布局 加上个属性 (我也不知道什么意思,反正 我 加不加 都没什么卵⽤,)
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<android.support.v7.widget.RecyclerView
android:id="@+id/home_newMsg_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"/>帕丁森与斯图尔特
</RelativeLayout>
ScrollView 重点是加上这个属性充满view android:fillViewport="true"
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="none">
//你的recyclerview 控件
</ScrollView>
接着 重点来了 为了尽量的避免 再出现什么 问题 ,最好还是⾃定义⼀个LinearLayoutManager
透析英语法代码中 调⽤
MyLinearLayoutManager mLayoutManager = new MyLinearLayoutManager(getActivity());
mRecylerView.tLayoutManager(mLayoutManager);
MyLinearLayoutManager 代码:
public class FullyLinearLayoutManager extends LinearLayoutManager {
private static boolean canMakeIntsDirty = true;
private static Field intsDirtyField = null;
private static final int CHILD_WIDTH = 0;
private static final int CHILD_HEIGHT = 1;
private static final int DEFAULT_CHILD_SIZE = 100;
private final int[] childDimensions = new int[2];
private final RecyclerView view;
private int childSize = DEFAULT_CHILD_SIZE;
private boolean hasChildSize;
private int overScrollMode = ViewCompat.OVER_SCROLL_ALWAYS;
private final Rect tmpRect = new Rect();
public MyLinearLayoutManager (Context context) {
super(context);
this.view = null;
}
public MyLinearLayoutManager (Context context, int orientation, boolean reverLayout) { super(context, orientation, reverLayout);
this.view = null;
}
public MyLinearLayoutManager (RecyclerView view) {
Context());
this.view = view;
this.overScrollMode = OverScrollMode(view);
}
public MyLinearLayoutManager (RecyclerView view, int orientation, boolean reverLayout) { Context(), orientation, reverLayout);
this.view = view;
this.overScrollMode = OverScrollMode(view);
}
public void tOverScrollMode(int overScrollMode) {
if (overScrollMode < ViewCompat.OVER_SCROLL_ALWAYS || overScrollMode > ViewCompat.OVER_SCROLL_NEVER)
throw new IllegalArgumentException("Unknown overscroll mode: " + overScrollMode); if (this.view == null) throw new IllegalStateException("view == null");
this.overScrollMode = overScrollMode;
ViewCompat.tOverScrollMode(view, overScrollMode);
}
public static int makeUnspecifiedSpec() {
public static int makeUnspecifiedSpec() {
return View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
}
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
final int widthMode = Mode(widthSpec);
final int heightMode = Mode(heightSpec);
final int widthSize = Size(widthSpec);
final int heightSize = Size(heightSpec);
final boolean hasWidthSize = widthMode != View.MeasureSpec.UNSPECIFIED;
final boolean hasHeightSize = heightMode != View.MeasureSpec.UNSPECIFIED;
final boolean exactWidth = widthMode == View.MeasureSpec.EXACTLY;
final boolean exactHeight = heightMode == View.MeasureSpec.EXACTLY;
final int unspecified = makeUnspecifiedSpec();
if (exactWidth && exactHeight) {
// in ca of exact calculations for both dimensions let's u default "onMeasure" implementation
return;
}
final boolean vertical = getOrientation() == VERTICAL;
initChildDimensions(widthSize, heightSize, vertical);
int width = 0;
int height = 0;
/
/ it's possible to get scrap views in recycler which are bound to old (invalid) adapter entities. This
// happens becau their invalidation happens after "onMeasure" method. As a workaround let's clear the
// recycler now (it should not cau any performance issues while scrolling as "onMeasure" is never
// called whiles scrolling)
recycler.clear();
final int stateItemCount = ItemCount();
final int adapterItemCount = getItemCount();
// adapter always contains actual data while state might contain old data (f.e. data before the animation is
// done). As we want to measure the view with actual data we must u data from the adapter and not from the
/
/ state
for (int i = 0; i < adapterItemCount; i++) {
if (vertical) {
if (!hasChildSize) {
if (i < stateItemCount) {
// we should not exceed state count, otherwi we'll get IndexOutOfBoundsException. For such items
// we will u previously calculated dimensions
measureChild(recycler, i, widthSize, unspecified, childDimensions);
} el {
logMeasureWarning(i);
}
}
height += childDimensions[CHILD_HEIGHT];
if (i == 0) {
width = childDimensions[CHILD_WIDTH];
}
if (hasHeightSize && height >= heightSize) {
break;
break;
}
} el {
if (!hasChildSize) {
if (i < stateItemCount) {
// we should not exceed state count, otherwi we'll get IndexOutOfBoundsException. For such items
// we will u previously calculated dimensions
measureChild(recycler, i, unspecified, heightSize, childDimensions);
} el {
logMeasureWarning(i);
}
}
width += childDimensions[CHILD_WIDTH];
if (i == 0) {
height = childDimensions[CHILD_HEIGHT];
}
tenureif (hasWidthSize && width >= widthSize) {
break;
}
avatar}
}
if (exactWidth) {
width = widthSize;
} el {
width += getPaddingLeft() + getPaddingRight();
if (hasWidthSize) {
width = Math.min(width, widthSize);
清新的拼音
}
}
if (exactHeight) {
height = heightSize;
} el {
height += getPaddingTop() + getPaddingBottom();
if (hasHeightSize) {
height = Math.min(height, heightSize);
}
}
tMeasuredDimension(width, height);
if (view != null && overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS) { final boolean fit = (vertical && (!hasHeightSize || height < heightSize))
|| (!vertical && (!hasWidthSize || width < widthSize));
ViewCompat.tOverScrollMode(view, fit ? ViewCompat.OVER_SCROLL_NEVER : ViewCompat.OVER_SCROLL_ALWAYS);
}
实习生英文
}
private void logMeasureWarning(int child) {
if (BuildConfig.DEBUG) {
Log.w("LinearLayoutManager", "Can't measure child #" + child + ", previously ud dimensions will be reud." +
"To remove this message either u #tChildSize() method or don't run RecyclerView animations");
}
}
private void initChildDimensions(int width, int height, boolean vertical) {
if (childDimensions[CHILD_WIDTH] != 0 || childDimensions[CHILD_HEIGHT] != 0) {
// already initialized, skipping
return;
}
if (vertical) {
}
if (vertical) {
childDimensions[CHILD_WIDTH] = width;
childDimensions[CHILD_HEIGHT] = childSize;
} el {
childDimensions[CHILD_WIDTH] = childSize;
childDimensions[CHILD_HEIGHT] = height;
}
}
@Override
public void tOrientation(int orientation) {
// might be called before the constructor of this class is called
//noinspection ConstantConditions
if (childDimensions != null) {
if (getOrientation() != orientation) {
childDimensions[CHILD_WIDTH] = 0;
childDimensions[CHILD_HEIGHT] = 0;
}
}
super.tOrientation(orientation);
}
public void clearChildSize() {
hasChildSize = fal;
tChildSize(DEFAULT_CHILD_SIZE);
}
public void tChildSize(int childSize) {
hasChildSize = true;
if (this.childSize != childSize) {
this.childSize = childSize;
requestLayout();
}
}
private void measureChild(RecyclerView.Recycler recycler, int position, int widthSize, int heightSize, int[] dimensions) {
final View child;
try {
child = ViewForPosition(position);
} catch (IndexOutOfBoundsException e) {
if (BuildConfig.DEBUG) {
Log.w("LinearLayoutManager", "LinearLayoutManager doesn't work well with animations. Consider switching them off", e);
}
return;
}pets5考试时间
final RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) LayoutParams();
final int hPadding = getPaddingLeft() + getPaddingRight();
final int vPadding = getPaddingTop() + getPaddingBottom();
beginwithfinal int hMargin = p.leftMargin + p.rightMargin;
周遭final int vMargin = p.topMargin + p.bottomMargin;
// we must make ints dirty in order calculateItemDecorationsForChild to work
makeIntsDirty(p);
// this method should be called before any getXxxDecorationXxx() methods
calculateItemDecorationsForChild(child, tmpRect);
final int hDecoration = getRightDecorationWidth(child) + getLeftDecorationWidth(child);
final int vDecoration = getTopDecorationHeight(child) + getBottomDecorationHeight(child);
final int childWidthSpec = getChildMeasureSpec(widthSize, hPadding + hMargin + hDecoration,
p.width, canScrollHorizontally());