版權聲明:本文爲HaiyuKing原創文章,轉載請註明出處!html
對於Recyclerview本身的LinearLayoutManager和GridLayoutManager,在版本23.2.0以後的library庫中已經解決了自適應的問題;java
關於RecyclerView 23.2.0新特性
這個版本給 LayoutManager API 添加了新的特性:自動測量(auto-measurement)!它容許 RecyclerView 根據內容控制高度。
這意味着咱們能夠實現以前沒法實現的情景(好比給 RecyclerView 設置 WRAP_CONTENT 屬性)
基於這個改變,請檢查 item 視圖在以前設置的屬性(舊版的 RecyclerView 的 item 視圖若是設置 MATCH_PARENT 屬性,則會自動佔滿整個視圖)android
可是有個問題就是當列表項超過一個屏幕的時候,Recyclerview的高度就是起始位置到屏幕的底部的高度值。git
Demo中的FullyGridLayoutManager、FullyLinearLayoutManager、MyStaggeredGridLayoutManager,是在Frank-Zhu/AndroidRecyclerViewDemo基礎上進行了優化,解決了上面說到的問題。github
使用FullyGridLayoutManager、FullyLinearLayoutManager、MyStaggeredGridLayoutManager的話,須要注意如下兩點:數組
一、佈局文件中須要給RecyclerView添加一個父佈局LinearLayout【綠色區域是ScrollView的寫法,黃色區域是須要注意的】app
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#F4F4F4"> <!-- 設置區域:可滑動 --> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbarSize="2dp" android:scrollbarThumbVertical="@drawable/scrollbar" android:scrollbars="vertical" > <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:text="對於系統本身的LinearLayoutManager和GridLayoutManager,在版本23.2.0以後的library庫中已經解決了自適應的問題;\n可是有個問題就是當列表項超過一個屏幕的時候,Recyclerview的高度就是起始位置到屏幕的底部的高度值。" android:layout_margin="8dp"/> <!-- 列表區域 --> <LinearLayout android:id="@+id/recycler_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <!-- RecyclerView列表 --> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:cacheColorHint="#00000000" android:divider="@null" android:listSelector="#00000000" android:scrollbars="none" /> </LinearLayout> <Button android:id="@+id/btn_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="添加一個item" android:layout_margin="8dp"/> </LinearLayout> </ScrollView> </RelativeLayout>
二、在代碼中須要執行LayoutManager的setRecyclerViewLayout()方法,將RecyclerView的父佈局傳值過去ide
注意事項:函數
一、 導入類文件後須要change包名以及從新import R文件路徑佈局
二、 Values目錄下的文件(strings.xml、dimens.xml、colors.xml等),若是項目中存在,則複製裏面的內容,不要整個覆蓋
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.why.project.recyclerfullymanagerdemo"
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
//RecyclerView compile "com.android.support:recyclerview-v7:27.1.1"
}
一、建立Bean類
package com.why.project.recyclerfullymanagerdemo.bean; /** * Created by HaiyuKing * Used 列表項的bean類 */ public class NewsBean { private String newsId;//id值 private String newsTitle;//標題 public String getNewsId() { return newsId; } public void setNewsId(String newsId) { this.newsId = newsId; } public String getNewsTitle() { return newsTitle; } public void setNewsTitle(String newsTitle) { this.newsTitle = newsTitle; } }
二、建立Adapter以及item的佈局文件【這個Demo中不須要後續修改】
package com.why.project.recyclerfullymanagerdemo.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import com.why.project.recyclerfullymanagerdemo.R; import com.why.project.recyclerfullymanagerdemo.bean.NewsBean; import java.util.ArrayList; /** * Created by HaiyuKing * Used 列表適配器 */ public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ /**上下文*/ private Context myContext; /**集合*/ private ArrayList<NewsBean> listitemList; /** * 構造函數 */ public NewsAdapter(Context context, ArrayList<NewsBean> itemlist) { myContext = context; listitemList = itemlist; } /** * 獲取總的條目數 */ @Override public int getItemCount() { return listitemList.size(); } /** * 建立ViewHolder */ @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(myContext).inflate(R.layout.news_list_item, parent, false); ItemViewHolder itemViewHolder = new ItemViewHolder(view); return itemViewHolder; } /** * 聲明grid列表項ViewHolder*/ static class ItemViewHolder extends RecyclerView.ViewHolder { public ItemViewHolder(View view) { super(view); listItemLayout = (LinearLayout) view.findViewById(R.id.listitem_layout); mChannelName = (TextView) view.findViewById(R.id.tv_channelName); } LinearLayout listItemLayout; TextView mChannelName; } /** * 將數據綁定至ViewHolder */ @Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int index) { //判斷屬於列表項 if(viewHolder instanceof ItemViewHolder){ NewsBean newsBean = listitemList.get(index); final ItemViewHolder itemViewHold = ((ItemViewHolder)viewHolder); itemViewHold.mChannelName.setText(newsBean.getNewsTitle()); //若是設置了回調,則設置點擊事件 if (mOnItemClickLitener != null) { itemViewHold.listItemLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int position = itemViewHold.getLayoutPosition();//在增長數據或者減小數據時候,position和index就不同了 mOnItemClickLitener.onItemClick(itemViewHold.listItemLayout, position); } }); //長按事件 itemViewHold.listItemLayout.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { int position = itemViewHold.getLayoutPosition();//在增長數據或者減小數據時候,position和index就不同了 mOnItemClickLitener.onItemLongClick(itemViewHold.listItemLayout, position); return false; } }); } } } /** * 添加Item--用於動畫的展示*/ public void addItem(int position,NewsBean listitemBean) { listitemList.add(position,listitemBean); notifyItemInserted(position); } /** * 刪除Item--用於動畫的展示*/ public void removeItem(int position) { listitemList.remove(position); notifyItemRemoved(position); } /*=====================添加OnItemClickListener回調================================*/ public interface OnItemClickLitener { void onItemClick(View view, int position); void onItemLongClick(View view, int position); } private OnItemClickLitener mOnItemClickLitener; public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) { this.mOnItemClickLitener = mOnItemClickLitener; } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/listitem_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_margin="1dp" android:background="#ffffff"> <TextView android:id="@+id/tv_channelName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="標題" android:textSize="18sp" android:padding="20dp"/> </LinearLayout>
三、在Activity佈局文件中引用Recyclerview控件【由於該Demo演示的是ScrollView中嵌套RecyclerView,因此佈局和普通的RecyclerView不太同樣(RecyclerView的高度設置爲wrap_content)】
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#F4F4F4"> <!-- 設置區域:可滑動 --> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbarSize="2dp" android:scrollbarThumbVertical="@drawable/scrollbar" android:scrollbars="vertical" > <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:text="對於系統本身的LinearLayoutManager和GridLayoutManager,在版本23.2.0以後的library庫中已經解決了自適應的問題;\n可是有個問題就是當列表項超過一個屏幕的時候,Recyclerview的高度就是起始位置到屏幕的底部的高度值。" android:layout_margin="8dp"/> <!-- 列表區域 --> <LinearLayout android:id="@+id/recycler_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <!-- RecyclerView列表 --> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:cacheColorHint="#00000000" android:divider="@null" android:listSelector="#00000000" android:scrollbars="none" /> </LinearLayout> <Button android:id="@+id/btn_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="添加一個item" android:layout_margin="8dp"/> </LinearLayout> </ScrollView> </RelativeLayout>
四、在Activity類中初始化recyclerview數據
package com.why.project.recyclerfullymanagerdemo; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import com.why.project.recyclerfullymanagerdemo.adapter.NewsAdapter; import com.why.project.recyclerfullymanagerdemo.bean.NewsBean; import java.util.ArrayList; /** * Created by HaiyuKing * Used */ public class LinearLayoutManagerActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private ArrayList<NewsBean> mNewsBeanArrayList; private NewsAdapter mNewsAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recyclerview); initViews(); initDatas(); initEvents(); } private void initViews() { mRecyclerView = findViewById(R.id.recycler_view); } private void initDatas() { //初始化集合 mNewsBeanArrayList = new ArrayList<NewsBean>(); for(int i=0; i<5;i++){ NewsBean newsBean = new NewsBean(); newsBean.setNewsId("123"+i); newsBean.setNewsTitle("標題"+i); mNewsBeanArrayList.add(newsBean); } //設置佈局管理器 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(linearLayoutManager); //設置適配器 if(mNewsAdapter == null){ //設置適配器 mNewsAdapter = new NewsAdapter(this, mNewsBeanArrayList); mRecyclerView.setAdapter(mNewsAdapter); //添加分割線 //設置添加刪除動畫 //調用ListView的setSelected(!ListView.isSelected())方法,這樣就能及時刷新佈局 mRecyclerView.setSelected(true); }else{ mNewsAdapter.notifyDataSetChanged(); } } private void initEvents() { //列表適配器的點擊監聽事件 mNewsAdapter.setOnItemClickLitener(new NewsAdapter.OnItemClickLitener() { @Override public void onItemClick(View view, int position) { } @Override public void onItemLongClick(View view, int position) { } }); //添加一個item findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { NewsBean newsBean = new NewsBean(); newsBean.setNewsId("123"+20); newsBean.setNewsTitle("標題"+20); mNewsBeanArrayList.add(newsBean); mNewsAdapter.notifyDataSetChanged(); } }); } }
package com.why.project.recyclerfullymanagerdemo.manager; import android.content.Context; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; /** * Author: ZhuWenWu * Version V1.0 * Date: 2015/2/26 14:14. * Description: * Modification History: * Date Author Version Description * ----------------------------------------------------------------------------------- * 2015/2/26 ZhuWenWu 1.0 1.0 * Why & What is modified: * 【在原有的基礎上進行了優化】 */ public class FullyGridLayoutManager extends GridLayoutManager { private static final String TAG = FullyGridLayoutManager.class.getSimpleName(); private LinearLayout mRecyclerViewLayout;//實現固定recyclerview的父佈局的高度值 public FullyGridLayoutManager(Context context, int spanCount) { super(context, spanCount); } public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) { super(context, spanCount, orientation, reverseLayout); } private int[] mMeasuredDimension = new int[2]; @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); int width = 0; int height = 0; int count = getItemCount(); int span = getSpanCount(); Log.d(TAG,"{onMeasure}count="+count+";span="+span); for (int i = 0; i < count; i++) { measureScrapChild(recycler, i, View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), mMeasuredDimension); if (getOrientation() == HORIZONTAL) { if (i % span == 0) { width = width + mMeasuredDimension[0]; } if (i == 0) { height = mMeasuredDimension[1]; } } else { if (i % span == 0) { height = height + mMeasuredDimension[1]; } if (i == 0) { width = mMeasuredDimension[0]; } } } switch (widthMode) { case View.MeasureSpec.EXACTLY: width = widthSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } switch (heightMode) { case View.MeasureSpec.EXACTLY: height = heightSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } Log.w(TAG,"{onMeasure}width="+width+";height="+height); setMeasuredDimension(width, height); //實現固定recyclerview的父佈局的高度值 LinearLayout.LayoutParams parmas = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,height); mRecyclerViewLayout.setLayoutParams(parmas); } private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) { Log.d(TAG,"{measureScrapChild}position="+position+";getItemCount()="+getItemCount()); if (position < getItemCount()) { try { View view = recycler.getViewForPosition(0);//fix 動態添加時報IndexOutOfBoundsException if (view != null) { RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), p.width); int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), p.height); view.measure(childWidthSpec, childHeightSpec); Log.w(TAG,"{measureScrapChild}childWidthSpec="+childWidthSpec+";childHeightSpec="+childHeightSpec); measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; Log.w(TAG,"{measureScrapChild}measuredDimension[0]="+measuredDimension[0]+";measuredDimension[1]="+measuredDimension[1]); recycler.recycleView(view); } } catch (Exception e) { e.printStackTrace(); } } } //實現固定recyclerview的父佈局的高度值 public LinearLayout getRecyclerViewLayout() { return mRecyclerViewLayout; } public void setRecyclerViewLayout(LinearLayout recyclerViewLayout) { mRecyclerViewLayout = recyclerViewLayout; } //實現禁止recyclerview滑動 @Override public boolean canScrollVertically() { //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll return false && super.canScrollVertically(); } }
package com.why.project.recyclerfullymanagerdemo.manager; import android.content.Context; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; /** * @Created HaiyuKing * @Used RecyclerView和ScrollView嵌套使用【在原有的基礎上進行了優化】 * http://www.cnblogs.com/tianzhijiexian/p/4469516.html */ public class FullyLinearLayoutManager extends LinearLayoutManager { private static final String TAG = FullyLinearLayoutManager.class.getSimpleName(); private LinearLayout mRecyclerViewLayout;//實現固定recyclerview的父佈局的高度值 public FullyLinearLayoutManager(Context context) { super(context); } public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } private int[] mMeasuredDimension = new int[2]; @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); Log.i(TAG, "onMeasure called. \nwidthMode " + widthMode + " \nheightMode " + heightSpec + " \nwidthSize " + widthSize + " \nheightSize " + heightSize + " \ngetItemCount() " + getItemCount()); int width = 0; int height = 0; for (int i = 0; i < getItemCount(); i++) { measureScrapChild(recycler, i, View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), mMeasuredDimension); if (getOrientation() == HORIZONTAL) { width = width + mMeasuredDimension[0]; if (i == 0) { height = mMeasuredDimension[1]; } } else { height = height + mMeasuredDimension[1]; if (i == 0) { width = mMeasuredDimension[0]; } } } switch (widthMode) { case View.MeasureSpec.EXACTLY: width = widthSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } switch (heightMode) { case View.MeasureSpec.EXACTLY: height = heightSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } setMeasuredDimension(width, height); //實現固定recyclerview的父佈局的高度值 LinearLayout.LayoutParams parmas = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,height); mRecyclerViewLayout.setLayoutParams(parmas); } private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) { try { View view = recycler.getViewForPosition(0);//fix 動態添加時報IndexOutOfBoundsException if (view != null) { RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), p.width); int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), p.height); view.measure(childWidthSpec, childHeightSpec); measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; recycler.recycleView(view); } } catch (Exception e) { e.printStackTrace(); } finally { } } //實現固定recyclerview的父佈局的高度值 public LinearLayout getRecyclerViewLayout() { return mRecyclerViewLayout; } public void setRecyclerViewLayout(LinearLayout recyclerViewLayout) { mRecyclerViewLayout = recyclerViewLayout; } //實現禁止recyclerview滑動 @Override public boolean canScrollVertically() { //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll return false && super.canScrollVertically(); } }
package com.why.project.recyclerfullymanagerdemo.manager; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.LinearLayout; /** * @Created HaiyuKing * @Used StaggeredGridLayoutManager自適應高度 * http://blog.csdn.net/skyyywerq/article/details/50731134 */ public class MyStaggeredGridLayoutManager extends StaggeredGridLayoutManager { private static final String TAG = MyStaggeredGridLayoutManager.class.getSimpleName(); private LinearLayout mRecyclerViewLayout;//實現固定recyclerview的父佈局的高度值 public MyStaggeredGridLayoutManager(int spanCount, int orientation, Context mContext) { super(spanCount, orientation); mHeightArray = new int[spanCount]; this.mContext = mContext; for (int i = 0; i < spanCount; i++) mHeightArray[i] = 0; } private int[] mMeasuredDimension = new int[2]; private int[] mHeightArray; private Context mContext; @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); int width = 0; int height = 0; int count = getItemCount(); int span = getSpanCount(); for (int i = 0; i < span; i++)//防止屢次調用onMeasure方法形成數據疊加 mHeightArray[i] = 0; for (int i = 0; i < count; i++) { measureScrapChild(recycler, i, View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), mMeasuredDimension); if (getOrientation() == HORIZONTAL) calculatorStaggeredHeight(mMeasuredDimension[0]); else calculatorStaggeredHeight(mMeasuredDimension[1]); } //獲取屏幕高度和寬度 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); if (getOrientation() == HORIZONTAL) { width = sort(mHeightArray); height = outMetrics.widthPixels;//獲取屏幕高度 } else { height = sort(mHeightArray); width = outMetrics.heightPixels;//獲取屏幕寬度 } switch (widthMode) { case View.MeasureSpec.EXACTLY: width = widthSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } switch (heightMode) { case View.MeasureSpec.EXACTLY: height = heightSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } setMeasuredDimension(width, height); //實現固定recyclerview的父佈局的高度值 LinearLayout.LayoutParams parmas = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,height); mRecyclerViewLayout.setLayoutParams(parmas); } /** * 冒泡排序返回數組最大值 * * @param unsorted * @return */ private int sort(int[] unsorted) { for (int i = 0; i < unsorted.length; i++) { for (int j = i; j < unsorted.length; j++) { if (unsorted[i] < unsorted[j]) { int temp = unsorted[i]; unsorted[i] = unsorted[j]; unsorted[j] = temp; } } } return unsorted[0]; } /** * 將傳入的item高度值賦給當前數組中最小的元素 * * @param singleViewHeight 傳入的item高度 */ private void calculatorStaggeredHeight(int singleViewHeight) { int index = 0; int minValue = mHeightArray[0]; for (int i = 1; i < mHeightArray.length; i++) { if (minValue > mHeightArray[i]) { minValue = mHeightArray[i]; index = i; } } mHeightArray[index] += singleViewHeight; } private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) { if (position < getItemCount()) { try { View view = recycler.getViewForPosition(position);//fix 動態添加時報IndexOutOfBoundsException if (view != null) { RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), p.width); int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), p.height); view.measure(childWidthSpec, childHeightSpec); measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; Log.v("p.height", p.height + ""); Log.v("measuredDimension[1]", measuredDimension[1] + ""); recycler.recycleView(view); } } catch (Exception e) { e.printStackTrace(); } } } //實現固定recyclerview的父佈局的高度值 public LinearLayout getRecyclerViewLayout() { return mRecyclerViewLayout; } public void setRecyclerViewLayout(LinearLayout recyclerViewLayout) { mRecyclerViewLayout = recyclerViewLayout; } //實現禁止recyclerview滑動 @Override public boolean canScrollVertically() { //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll return false && super.canScrollVertically(); } }
FullyGridLayoutManager、FullyLinearLayoutManager、MyStaggeredGridLayoutManager的使用方法,就是替換掉以前項目中使用設置佈局管理器代碼部分的GridLayoutManager、LinearLayoutManager、StaggeredGridLayoutManager。
好比使用FullyGridLayoutManager的話,就按照下面的進行替換:
無
ScrollView裏嵌套Recycleview使用StaggeredGridLayoutManager高度不正確的問題
Frank-Zhu/AndroidRecyclerViewDemo