RecyclerView 巢狀遇到的坑
在專案中根據原型圖實現程式碼
思路:最外層是一個ScrollView 然後下面的細節是RecyclerView的二級巢狀
佈局檔案
最外層
<Scrollview android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/rl_title" android:layout_marginBottom="52dp" android:layout_marginTop="5dp" android:scrollbars="none" android:fillViewport="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:text="面料選擇" android:textColor="#000000" android:textSize="12sp" /> <LinearLayout android:id="@+id/ll_mianliao" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:background="@drawable/squre_hui" android:orientation="vertical" android:padding="5dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/iv_mianliao" android:layout_width="150dp" android:layout_height="60dp" /> <LinearLayout android:id="@+id/ll_detail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1" android:gravity="center_vertical" android:orientation="vertical"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="5dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="編號: " android:textSize="10sp" /> <TextView android:id="@+id/tv_identifier" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="10sp" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="5dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="顏色: " android:textSize="10sp" /> <TextView android:id="@+id/tv_color" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="10sp" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="5dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="成分: " android:textSize="10sp" /> <TextView android:id="@+id/tv_component" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="10sp" /> </LinearLayout> </LinearLayout> <TextView android:id="@+id/tv_null" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="10dp" android:text="沒有預設面料,請選擇" android:textSize="12sp" android:visibility="gone" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:padding="10dp" android:src="@drawable/ic_more" /> </LinearLayout> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#ededed" /> <android.support.v7.widget.RecyclerView android:id="@+id/rv_style" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> </LinearLayout> </Scrollview>
大RecyclerView的item佈局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:orientation="vertical"> <TextView android:id="@+id/tv_style_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="5dp" android:textColor="#000000" android:textSize="12sp"/> <android.support.v7.widget.RecyclerView android:id="@+id/rv_style_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="5dp"> </android.support.v7.widget.RecyclerView> </LinearLayout>
小recyclerview item的佈局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:gravity="center" android:orientation="vertical"> <LinearLayout android:id="@+id/ll_bg" android:layout_width="70dp" android:layout_height="70dp" android:padding="2dp" android:descendantFocusability="blocksDescendants" android:orientation="horizontal"> <ImageView android:id="@+id/iv_style" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> <TextView android:id="@+id/tv_name" android:layout_width="70dp" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:paddingBottom="10dp" android:singleLine="true" android:textSize="10sp" /> </LinearLayout>
最初的時候,發現外層RecyclerView顯示不全,後面百度,大家說需要重新計算item的高度,試了好幾種方法,還是不行,後面翻看一篇國外大神的文章發現了不通,結果也算順利解決
下面給出程式碼:MyLinearLayoutManager
public class MyLinearLayoutManager 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 MyLinearLayoutManager(Context context) { super(context); this.view = null; } public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); this.view = null; } public MyLinearLayoutManager(RecyclerView view) { super(view.getContext()); this.view = view; this.overScrollMode = ViewCompat.getOverScrollMode(view); } public MyLinearLayoutManager(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); } } 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); } } 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); } } @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); } 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; } } 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; } }
Activity 中程式碼就跟是常規使用recyclerview的方法
下面貼出第一個adapter中的程式碼 StyleAdapte
這裡在onBindView中繫結資料,並設定第二個recyclerview的adapter
注意f粉色部分 後面出現了小recyclerview也顯示不全 明明設定好了layoutManager還是顯示不全,試了好幾種都不行,後面將其改成紅色部分就好了
原因我還不是太清楚 我想應該是資料來源的地址相同引起的資料錯亂 。
放在外面 即使在下方clear了 但是資料地址還是一樣,所以引起了資料錯亂
放在下面的話,就相當於 每一次繫結資料都是一個 新的資料
public class StyleAdapter extends RecyclerView.Adapter<StyleAdapter.MyViewHolder> { private List<AttributeClass> mAttributeClassDatas;
//List<Attribute> mAttributeDatas = new ArrayList<Attribute>();
private LayoutInflater mInflater; private DetailTaoxiActivity mContext; public StyleAdapter(DetailTaoxiActivity context, List<AttributeClass> datas) { mInflater = LayoutInflater.from(context);mAttributeClassDatas = datas;mContext = context;} @Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { MyViewHolder holder = new MyViewHolder(mInflater.inflate(R.layout.item_style, parent, false)); return holder;} @Overridepublic void onBindViewHolder(MyViewHolder holder, int position) { holder.tv_style_name.setText(mAttributeClassDatas.get(position).name);JSONArray attributeList = mAttributeClassDatas.get(position).attributeList;//mAttributeDatas.clear();
List<Attribute> mAttributeDatas = new ArrayList<Attribute>(); for (int i = 0; i < attributeList.length(); i++) { Attribute attribute = Attribute.createFromJson(attributeList.optJSONObject(i));mAttributeDatas.add(attribute);} if (mAttributeDatas != null && mAttributeDatas.size() > 0) { ImageAdapter imageAdapter = new ImageAdapter(mContext, mAttributeDatas);FullyGridLayoutManager gm = new FullyGridLayoutManager(mContext, 4, FullyGridLayoutManager.VERTICAL, false);holder.rv_style_item.setLayoutManager(gm);holder.rv_style_item.setAdapter(imageAdapter);holder.rv_style_item.setVisibility(View.VISIBLE);} else { holder.rv_style_item.setVisibility(View.GONE);} } @Overridepublic int getItemCount() { return mAttributeClassDatas.size();} class MyViewHolder extends ViewHolder { TextView tv_style_name;RecyclerView rv_style_item; public MyViewHolder(View view) { super(view);tv_style_name = (TextView) view.findViewById(R.id.tv_style_name);rv_style_item = (RecyclerView) view.findViewById(R.id.rv_style_item);} }}
小Adapter也是很簡單的 就跟平常用的recyclerview的adapter一樣
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.MyViewHolder>{ private List<Attribute> mDatas; private LayoutInflater mInflater; private DetailTaoxiActivity mContext; private ImageLoader imageLoader; private int layoutPosition; private List<String> idList=new ArrayList<String>(); public ImageAdapter(DetailTaoxiActivity context, List<Attribute> datas) { mInflater = LayoutInflater.from(context); mDatas = datas; mContext=context; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = mInflater.inflate(R.layout.item_style_item, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(final MyViewHolder holder, final int position) { holder.tv_name.setText(mDatas.get(position).name); imageLoader = new ImageLoader(mContext); imageLoader.DisplayImage(URL_P.ImageBasePath +mDatas.get(position).pic, holder.iv_style); mContext.setBackground(holder.ll_bg,position); holder.ll_bg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) {
/*
實現item的單選
*/
//上一個選中的位置 int selPos=mContext.getmSelectedPos(); String oldId=mDatas.get(selPos).attributeValueId; //獲取當前點選的位置 layoutPosition = holder.getLayoutPosition(); notifyDataSetChanged(); String newId=mDatas.get(layoutPosition).attributeValueId;mContext.updataBackground(oldId,newId); } }); //更改狀態 if(position == layoutPosition){ holder.ll_bg.setBackgroundResource(R.drawable.squre_gray_black); }else{ holder.ll_bg.setBackgroundResource(R.drawable.squre_hui); } } @Override public int getItemCount() {相關推薦
RecyclerView 巢狀遇到的坑
在專案中根據原型圖實現程式碼 思路:最外層是一個ScrollView 然後下面的細節是RecyclerView的二級巢狀 佈局檔案 最外層 <Scrollview android:layout_width="match_parent" android:layo
RecyclerView巢狀RecyclerView item 顯示不全及資料不顯示問題
今天在做專案中的商品屬性選擇彈框,用RecyclerView巢狀RecyclerView來實現,發現子RecyclerView item資料不顯示並且item數不全,如圖: 查了網上的解決方案。改為 父RecyclerView繫結佈局方式: return new AttributesV
recyclerview巢狀GridView去遮蔽後者的點選事件,而是前者響應到事件。
無論是標題中的巢狀方式,還是其它列表控制元件之間的巢狀,都適用。 1、在GirdView的所在佈局的根佈局中設定改屬性: android:descendantFocusability="blacksDescendants" 2、動態設定GirdView的如下屬性: gridvi
分組(recyclerview巢狀)
效果 分包方式 重要程式碼 recyclerview巢狀recyclerview 介面卡(大的介面卡巢狀子介面卡) package com.jia.dividegroups.adapt; import android.content.Context; import android
一層RecyclerView實現list RecyclerView巢狀grid RecyclerView
有需求的可以看看前言準備工作具體實現感謝 前言 還是先上圖看下效果,不符要求或者不感興趣的老哥就可以省個時間去做其他事了。 效果圖: 準備工作 首先我們分析這個圖,我們可以把張圖分為三種類型的item,分別是頭部帶標題的一欄,中間內容,和尾部空白填充。 我
Android 仿京東,淘寶RecyclerView巢狀ViewPager巢狀RecyclerView商品展示
最近看到京東,淘寶都有RecyclerView巢狀ViewPager巢狀RecyclerView商品展示的效果,效果挺好,廢話不多說先看效果圖: GIF.gif 技能點: 1.Android事件分發機制等 需求點: 1.列表巢狀,內層的列表可以左右切換 2.V
使用Recyclerview巢狀實現購物車全選反選
在drawable建立selector改變CheckBox外形 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/
解決垂直RecyclerView巢狀水平RecyclerView橫向滑問題
如下程式碼主要解決兩個問題: 解決ViewPager巢狀垂直RecyclerView巢狀水平RecyclerView橫向滑動到底後不滑動ViewPager 解決思路: 繼承RecyclerView,重寫dispatchTouchEvent,根據ACTION_MOVE的方
帶下拉重新整理的RecyclerView巢狀橫向RecyclerView事件衝突
實際效果圖 採用結構 PtrFrameLayout 巢狀一個帶下拉重新整理的RecyclerViewPtrFrameLayout是一個自定義下拉重新整理佈局 RV內部Item包含一
RecyclerView巢狀viewpage無效
第一篇部落格,說的快點,我有次用RecyclerView巢狀viewPager後ViewPager不顯示,當我把寬和高設定為一個固定值而不是 wrap_content或者match_parent後viewpager可以正常顯示,可以理解為viewpager在使用時需要獲取父
Android RecyclerView巢狀到ScrollView中Item的寬度不能完全填充父佈局的問題
RecyclerView巢狀到ScrollView經常會出現item不能完全填充的問題,給大家個簡單暴力的方案:重新設定佈局引數 class MyViewHolder extends RecyclerView.ViewHolder{ private My
豎直滑動的RecyclerView巢狀豎直滑動的RecyclerView並解決滑動衝突
入職國美三個月了,進入大公司最大的感觸就是人遠比你自己想象的要強大!這一路走來實屬不易,但給我帶來的更多是成長。這裡是人生的起點,也可以說是夢開始的地方,加油吧! 專案中要求兩個紅框區域列表滑動時吸頂,頭像部分超過四行可上下滑動。 問題①兩個區域吸頂實現:這個比較好實
RecyclerView巢狀ViewPager實現淘寶搜狐主頁廣告輪播圖
RecyclerView巢狀ViewPager實現原理: RecyclerView巢狀ViewPager實際上就是RecyclerView複雜佈局的實現,給其中一個item設定為ViewPager來實現廣告輪播圖。既然知道原理 那麼
簡單解決RecyclerView巢狀的RecyclerView條目顯示不全和寬度不能鋪滿
第一個RecyclerView的Adapter @Override public MyHolder onCreateViewHolder(ViewGroup parent, int viewT
RecyclerView巢狀ListView 只顯示一條資料
今天做專案發現 RecyclerView巢狀ListView 只顯示一個item, 咋辦! 此時我們需要把ListView重寫一下onMeasure方法。因為當ListView的Item每次改變時都會呼叫onMeasure. 自定義ListView就可以 了 publ
RecyclerView巢狀RecyclerView
看看本篇文章要實現的是什麼效果: 實現思路: 1.在外層的item佈局中放一個RecyclerView用來顯示網格佈局: 2.增加一個ImageAdapter,用來展示圖片; 3.在原InfoAdapter中對圖片資料進行處理: if(
Android 混排效果之 ScrollView 巢狀 RecyclerView 巢狀gridview 實現listview 巢狀gridview 效果
RecyclerView 出現以後 很受大家歡迎 漂亮流暢的列表 簡單的操作 可以幫我們完成很多的列表 但是有一種listview 巢狀gridview 的效果 目前還是需要巢狀才能完成 現在就簡單說一下我的思路 本人的需求是例如手機淘寶頁 本人使用老套的實現模
RecyclerView常見問題解決方案,RecyclerView巢狀自動滾動,RecyclerView 高度設定wrap_content 無作用等問題
1,ScrollView或者RecyclerView1 巢狀RecyclerView2 進入頁面自動跳轉到recyclerView2上面頁面會自動滾動貌似是RecyclerView 自動獲得了焦點兩
Android中RecyclerView巢狀RecyclerView或巢狀ListView
效果圖: RecyclerView巢狀RecyclerView RecyclerView巢狀ListView 原理 RecyclerView巢狀RecyclerView的條目,專案中可能會經常有這樣的需求,但是我們將子條目設定為RecyclerView之後,卻顯
RecyclerView巢狀ViewPager再巢狀RecyclerView滑動問題
RecyclerView頭部巢狀ViewPager,ViewPager內放Fragment,Fragment再放RecyclerView時,其實就是RecyclerView巢狀Viewpager再巢狀RecyclerView,這個時候滑動外面的RecyclerView的時候,