1. 程式人生 > >RecyclerView下實現 ListView巢狀GridView 複雜效果

RecyclerView下實現 ListView巢狀GridView 複雜效果

導言:

         RecyclerView使用也有一段時間了 他的出現是對ListView,GridView的進化。但是我們要實現一些複雜的佈局,比如這個佈局,那我們該怎麼辦呢?別急,不是說了RecyclerView是對ListView,GridView的進化嗎?那麼ListView和GridView能實現的效果,RecyclerView肯定能實現,甚至ListView巢狀GridView這個2B的方式也是能實現的,甚至還有ListView和GridView的複用功能。(如果你急於找答案,那就先提示,請使用GridLayoutManager的setSpanSizeLookup的方法,設定單個Item的跨度,如果你有時間,就往下看,謝謝支援

)

分析:

      當我們美工給我們類似導言裡面的效果圖時,我們不要一臉懵逼,應該對美工妹紙說:你的這效果圖真和你一樣漂亮,今晚下班能一起研究研究嗎?美工妹紙肯定說:哎呀,臭屌絲!滾。  好吧,程式猿果真是苦逼的命啊,那我們只能低頭下來研究技術吧。於是程式猿開始研究了效果圖,這看上去有ListView的效果,又有GridView的效果,能不巢狀起來將就一下呢?但是程式猿又想到嵌套了複用的機制又沒有了,如果Item是圖片,多起來OOM豈不是很沒面子。程式猿又想到了RecyclerView最近不是很火嗎?不是說RecyclerView是對ListView,GridView的進化嗎? 但是RecyclerView的

LayoutManager只有GridLayoutManager(一行多個ITEM) 和LinearLayoutManager(一行一個Item)呀?會不會有第三種佈局管理呢?程式猿好像抓住了生命的稻草似的打開了API文件。找呀找,竟然沒有,哎......一臉失望的開著API,突然眼前好像看到了GridLayoutManager的的構造器有個 int型別的spanCount,還有個setSpanSizeLookup的方法。看了文件描述,臥槽,上天被程式猿的真誠感動了啊。

文件說明:

public GridLayoutManager(android.content.Context context, int spanCount)
Creates a vertical GridLayoutManager
param
context Current context, will be used to access resources.
param
spanCount The number of columns in the grid// <span style="color: rgb(51, 51, 51); font-family: arial; font-size: 18px; line-height: 20px;">網格中的列數</span>
spanCount 就是一行有多少列,比如導言中的圖片一行中最多的有2列,那麼我們應該傳入引數2:,

前方高能,請開啟AndroidStudio:

setSpanSizeLookup(android.support.v7.widget.GridLayoutManager$SpanSizeLookup spanSizeLookup)
Sets the source to get the number of spans occupied by each item in the adapter.
param
spanSizeLookup {@link SpanSizeLookup} instance to be used to query number of spans occupied by each item<span style="font-weight: bold;">

</span>
這方法就是設定單個Item的跨度(跨度?就是相當於一個LinearLayout裡面設定了weightSum為5,一個子控制元件的layout_weight=4  ,那麼這個這個item的跨度就是這個LinearLayout的 4/5),同理導言中的圖片中我們拿出item0 和item1 ,item2出來分析。  item2的寬度大概是item1的一半,item1大概是item0 的2/3, 那麼我們大概知道了,item0的跨度為3,item1的跨度為2,item2的跨度為1。是多少
GridLayoutManager manager = new GridLayoutManager(this, 3);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
  @Override
  public int getSpanSize(int position) {
    return (3 - position % 3);
  }
});
recyclerView.setLayoutManager(manager);
return (3-position%3); 我們來看這個,當position為0的時候,返回的跨度為3,就是說item佔3個跨度。OK,一切都很明朗了。

拓展:

      上面只是demo,到現實的專案中,該怎麼變通呢?? 現實專案的item各種各樣,那麼我們繼續往下看,現實專案中我們可以配合RecyclerView.Adapter<RecyclerView.ViewHolder> 中的
//// 載入Item View的時候根據不同TYPE載入不同的佈局
	@Override
	public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
			int viewType) {
		
		if (viewType == 0) {
			return new ItemTypeViewHolder(mLayoutInflater.inflate(
					R.layout.item_recommend_title, parent, false));
		} else if (viewType == 1 || viewType == 4) {
			return new ItemListViewHolder(mLayoutInflater.inflate(
					R.layout.item_book_info, parent, false));
		} else {
			return new ItemGridViewHolder(mLayoutInflater.inflate(
					R.layout.item_recommend_hor, parent, false));
		}
	}

	// 初始化不同的佈局。
	@Override
	public void onBindViewHolder(RecyclerView.ViewHolder holder,
			final int position) {

		if (holder instanceof ItemTypeViewHolder) {
			ItemTypeViewHolder tempholder = (ItemTypeViewHolder) holder;
			tempholder.mBookNameTv.setText(mBeans.get(position)
					.getRecommendtypename());

			return;
		} else if (holder instanceof ItemListViewHolder) {
			ItemListViewHolder tempholder = (ItemListViewHolder) holder;
			if (mOnItemClickLitener != null) {
				tempholder.itemView.setOnClickListener(new OnClickListener() {

					@Override
					public void onClick(View v) {
						mOnItemClickLitener.onItemClick(v, position);
					}
				});
			}
			tempholder.mBookAuthorTv.setText(mBeans.get(position)
					.getBookauthor());
			tempholder.mBookNameTv.setText(mBeans.get(position).getBookname());
			tempholder.mBookSummry.setText(mBeans.get(position).getSummary());

			Picasso.with(mContext).load(mBeans.get(position).getBookCoverURL())
					.placeholder(R.drawable.bookcover)
					.error(R.drawable.bookcover).into(tempholder.mBookCoverImg);
			return;
		} else if (holder instanceof ItemGridViewHolder) {
			ItemGridViewHolder tempholder = (ItemGridViewHolder) holder;
			if (mOnItemClickLitener != null) {
				tempholder.itemView.setOnClickListener(new OnClickListener() {

					@Override
					public void onClick(View v) {
						mOnItemClickLitener.onItemClick(v, position);
					}
				});
			}
			tempholder.mBookAuthorTv.setText(mBeans.get(position)
					.getBookauthor());
			tempholder.mBookNameTv.setText(mBeans.get(position).getBookname());
			Picasso.with(mContext).load(mBeans.get(position).getBookCoverURL())
					.placeholder(R.drawable.bookcover)
					.error(R.drawable.bookcover).into(tempholder.mBookCoverImg);
			return;
		}
	}

	// 設定ITEM型別,可以自由發揮,返回Item的樣式。
	@Override
	public int getItemViewType(int position) {
		//返回當前的資料型別,可以在bean模型類中設定一個欄位。
		// 
//		return	(3 - position % 3);
		return mBeans.get(position).getRecommendtype();
	}

最後在Fragment或者 Activity中:

mAdapter = new RecommendAdapter(getActivity());
			mAdapter.setOnItemClickLitener(this);
			mListView = (RecyclerView) mRootView.findViewById(R.id.list);
			GridLayoutManager layoutManager = new GridLayoutManager(
					getActivity(), 6);
			layoutManager.setSpanSizeLookup(new SpanSizeLookup() {

				@Override
				public int getSpanSize(int position) {
					switch (mAdapter.getItemViewType(position)) {
					case 0:
						return 6; // 寬度為6, item滿屏
					case 1:
						return 6;// 寬度為6, item滿屏
					case 2:
						return 3;// 寬度為3,item為螢幕的寬的一半,這一行可以顯示2個item
					case 3:
						return 2;// 寬度為3,item為螢幕的寬的1/3,這一行可以顯示3個item
					case 4:
						return 6;// 寬度為6, item滿屏
					default:
						return -1;
					}
				}
			});
			mListView.setLayoutManager(layoutManager);
			mListView.setAdapter(mAdapter);

大功告成。謝謝閱讀.

------Android開發基友群:64026923,眾多妹紙、基友等著你喲。加的是群,漲的是技術: