燚軒科技 助力中小型企業(yè)
關(guān)注行業(yè)新聞 把握時(shí)代脈搏
安卓app開(kāi)發(fā)中解決recycleview 和 scollview 嵌套 問(wèn)題
有時(shí)候想要recycleview 和 scollview 嵌套 并且全部展開(kāi)recycleview,這樣的app技術(shù)無(wú)疑是很多人頭疼的,那么下面鄭州app開(kāi)發(fā)就來(lái)詳細(xì)的講解一下。
但是會(huì)發(fā)現(xiàn) 簡(jiǎn)單的嵌套后 recycleview不能滑動(dòng) 或者無(wú)法看到展開(kāi)的全部?jī)?nèi)容
下面鄭州app開(kāi)發(fā)小編為大家附上解決問(wèn)題的代碼
經(jīng)過(guò)查閱相關(guān)內(nèi)容發(fā)現(xiàn)在設(shè)置recycleview。setLayoutManager可以解決這個(gè)問(wèn)題
下面是manager的代碼
public class FullyLinearLayoutManager extends LinearLayoutManager {
private static boolean canMakeInsetsDirty = true;
private static Field insetsDirtyField = 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 FullyLinearLayoutManager(Context context) {
super(context);
this.view = null;
}
public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
this.view = null;
}
public FullyLinearLayoutManager(RecyclerView view) {
super(view.getContext());
this.view = view;
this.overScrollMode = ViewCompat.getOverScrollMode(view);
}
public FullyLinearLayoutManager(RecyclerView view, int orientation, boolean reverseLayout) {
super(view.getContext(), orientation, reverseLayout);
this.view = view;
this.overScrollMode = ViewCompat.getOverScrollMode(view);
}
public void setOverScrollMode(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.setOverScrollMode(view, overScrollMode);
}
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 = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(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 case of exact calculations for both dimensions let's use default "onMeasure" implementation
super.onMeasure(recycler, state, widthSpec, heightSpec);
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 because their invalidation happens after "onMeasure" method. As a workaround let's clear the
// recycler now (it should not cause any performance issues while scrolling as "onMeasure" is never
// called whiles scrolling)
recycler.clear();
final int stateItemCount = state.getItemCount();
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 use 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, otherwise we'll get IndexOutOfBoundsException. For such items
// we will use previously calculated dimensions
measureChild(recycler, i, widthSize, unspecified, childDimensions);
} else {
logMeasureWarning(i);
}
}
height += childDimensions[CHILD_HEIGHT];
if (i == 0) {
width = childDimensions[CHILD_WIDTH];
}
if (hasHeightSize && height >= heightSize) {
break;
}
} else {
if (!hasChildSize) {
if (i < stateItemCount) {
// we should not exceed state count, otherwise we'll get IndexOutOfBoundsException. For such items
// we will use previously calculated dimensions
measureChild(recycler, i, unspecified, heightSize, childDimensions);
} else {
logMeasureWarning(i);
}
}
width += childDimensions[CHILD_WIDTH];
if (i == 0) {
height = childDimensions[CHILD_HEIGHT];
}
if (hasWidthSize && width >= widthSize) {
break;
}
}
}
if (exactWidth) {
width = widthSize;
} else {
width += getPaddingLeft() + getPaddingRight();
if (hasWidthSize) {
width = Math.min(width, widthSize);
}
}
if (exactHeight) {
height = heightSize;
} else {
height += getPaddingTop() + getPaddingBottom();
if (hasHeightSize) {
height = Math.min(height, heightSize);
}
}
setMeasuredDimension(width, height);
if (view != null && overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS) {
final boolean fit = (vertical && (!hasHeightSize || height < heightSize))
|| (!vertical && (!hasWidthSize || width < widthSize));
ViewCompat.setOverScrollMode(view, fit ? ViewCompat.OVER_SCROLL_NEVER : ViewCompat.OVER_SCROLL_ALWAYS);
}
}
private void logMeasureWarning(int child) {
}
private void initChildDimensions(int width, int height, boolean vertical) {
if (childDimensions[CHILD_WIDTH] != 0 || childDimensions[CHILD_HEIGHT] != 0) {
// already initialized, skipping
return;
}
if (vertical) {
childDimensions[CHILD_WIDTH] = width;
childDimensions[CHILD_HEIGHT] = childSize;
} else {
childDimensions[CHILD_WIDTH] = childSize;
childDimensions[CHILD_HEIGHT] = height;
}
}
@Override
public void setOrientation(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.setOrientation(orientation);
}
public void clearChildSize() {
hasChildSize = false;
setChildSize(DEFAULT_CHILD_SIZE);
}
public void setChildSize(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 = recycler.getViewForPosition(position);
} catch (IndexOutOfBoundsException e) {
return;
}
final RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) child.getLayoutParams();
final int hPadding = getPaddingLeft() + getPaddingRight();
final int vPadding = getPaddingTop() + getPaddingBottom();
final int hMargin = p.leftMargin + p.rightMargin;
final int vMargin = p.topMargin + p.bottomMargin;
// we must make insets dirty in order calculateItemDecorationsForChild to work
makeInsetsDirty(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());
final int childHeightSpec = getChildMeasureSpec(heightSize, vPadding + vMargin + vDecoration, p.height, canScrollVertically());
child.measure(childWidthSpec, childHeightSpec);
dimensions[CHILD_WIDTH] = getDecoratedMeasuredWidth(child) + p.leftMargin + p.rightMargin;
dimensions[CHILD_HEIGHT] = getDecoratedMeasuredHeight(child) + p.bottomMargin + p.topMargin;
// as view is recycled let's not keep old measured values
makeInsetsDirty(p);
recycler.recycleView(child);
}
private static void makeInsetsDirty(RecyclerView.LayoutParams p) {
if (!canMakeInsetsDirty) {
return;
}
try {
if (insetsDirtyField == null) {
insetsDirtyField = RecyclerView.LayoutParams.class.getDeclaredField("mInsetsDirty");
insetsDirtyField.setAccessible(true);
}
insetsDirtyField.set(p, true);
} catch (NoSuchFieldException e) {
onMakeInsertDirtyFailed();
} catch (IllegalAccessException e) {
onMakeInsertDirtyFailed();
}
}
private static void onMakeInsertDirtyFailed() {
canMakeInsetsDirty = false;
}
}
以上信息由鄭州app開(kāi)發(fā)公司燚軒科技整理發(fā)布。
版權(quán)與免責(zé)聲明
鄭州APP開(kāi)發(fā),鄭州小程序開(kāi)發(fā)燚軒軟件科技有限公司聲明:如發(fā)現(xiàn)內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息發(fā)郵件至854221200@qq.com,我們將及時(shí)溝通處理。本站內(nèi)容源于網(wǎng)絡(luò),涉及內(nèi)容、言論與本站無(wú)關(guān)
案主要是為用戶(hù)提供房源信息及購(gòu)買(mǎi)服務(wù),房地產(chǎn)行業(yè)的開(kāi)發(fā)方案是為了方便用戶(hù)能夠隨時(shí)隨地了解房產(chǎn)...
發(fā)的不斷增多,應(yīng)用市場(chǎng)中的手機(jī)APP讓人們應(yīng)接不暇。因而APP開(kāi)發(fā)市場(chǎng)從2010年以來(lái),一直...
就產(chǎn)生了。那么建材采購(gòu)類(lèi)的APP需要具備哪些功能呢?鄭州APP開(kāi)發(fā)的小編就來(lái)給大家介紹一下。...
企業(yè)活動(dòng)非常受歡迎的一種方式,如果運(yùn)用的好,能夠給企業(yè)的形象加分不少。那么我們?cè)撊绾沃谱鞒鲆?..
且近幾年,網(wǎng)絡(luò)直播平臺(tái)捧紅了一大批網(wǎng)絡(luò)紅人,在這個(gè)“看臉”的時(shí)代,促使越來(lái)越多的人開(kāi)始想變漂...
個(gè)問(wèn)題,應(yīng)該是所有想要投資app開(kāi)發(fā)的投資者都廣泛關(guān)注的一個(gè)問(wèn)題,而且也是詢(xún)問(wèn)app開(kāi)發(fā)公司...
熱點(diǎn)文章More +
- 網(wǎng)頁(yè)時(shí)代已經(jīng)慢慢消逝,APP引領(lǐng)時(shí)代潮流
- 鄭州APP開(kāi)發(fā)除了看價(jià)格還要注意什么?
- 沒(méi)個(gè)百來(lái)萬(wàn)就想自建技術(shù)團(tuán)隊(duì)?親身經(jīng)歷告訴你,一個(gè)APP從無(wú)到有的開(kāi)發(fā)到底要花多少錢(qián)!
- 二維碼支付為何能打敗NFC支付
- 開(kāi)發(fā)手機(jī)APP,這些點(diǎn)很重要!
- 商城類(lèi)app開(kāi)發(fā)需要多少錢(qián)