一直都在纠结ScrollView嵌套RecyclerView这个问题。有人说大多数人不会解决。其实是不用解决!!!理由:官方不推荐这样使用,因为这两个控件的高度是不固定的,而且他们两测量高度的方法也不同。在处理的时候很复杂(你得了解ScrollView的绘制过程和RecyclerView的绘制过程),参照当前流行的网站中给出的例子(一般都是重写RecyclerView的布局管理器),而在实际的开发过程中你会发现,在滑动事件上仍然存在冲突。如果你是大神,那就当我啥都没说。
那么如何解决RecyclerView的复杂布局?
开始代码
1、适配器
package com.hs.recyclerviewadd.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.support.v7.widget.RecyclerView;
import com.hs.recyclerviewadd.R;
/**
* Created by zhanghaitao on 2017/6/14.
*/
public class HeaderBottomAdapter extends RecyclerView.Adapter {
//item类型
//在这里还是可以添加其他类型的。
public static final int ITEM_TYPE_HEADER = 0;//头布局
public static final int ITEM_TYPE_CONTENT = 1;//条目布局
public static final int ITEM_TYPE_BOTTOM = 2;//脚布局
//模拟数据(后期可以通过构造函数添加,也可以交给继承HeaderBottomAdapter的子类)
public String[] texts = {"java", "python", "C++", "Php", ".NET", "js", "Ruby", "Swift", "OC",
"java", "python", "C++", "Php", ".NET", "js", "Ruby", "Swift"};
private LayoutInflater mLayoutInflater;
private Context mContext;
private int mHeaderCount = 1;//头部View个数
private int mBottomCount = 1;//底部View个数
/**
* 构造函数(不多解释)
*
* @param context
*/
public HeaderBottomAdapter(Context context) {
mContext = context;
mLayoutInflater = LayoutInflater.from(context);
}
/**
* 获取内容的长度
*
* @return
*/
public int getContentItemCount() {
return texts.length;
}
/**
* 判断当前item是否是HeadView
*
* @param position
* @return
*/
public boolean isHeaderView(int position) {
return mHeaderCount != 0 && position < mHeaderCount;
}
/**
* 判断当前item是否是FooterView
*
* @param position
* @return
*/
public boolean isBottomView(int position) {
return mBottomCount != 0 && position >= (mHeaderCount + getContentItemCount());
}
/**
* 判断当前item类型
*
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
int dataItemCount = getContentItemCount();
if (mHeaderCount != 0 && position < mHeaderCount) {
//头部View
return ITEM_TYPE_HEADER;
} else if (mBottomCount != 0 && position >= (mHeaderCount + dataItemCount)) {
//底部View
return ITEM_TYPE_BOTTOM;
} else {
//内容View
return ITEM_TYPE_CONTENT;
}
}
/**
* 内容 ViewHolder类
*/
public static class ContentViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
public ContentViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.tv_item_text);
}
}
/**
* 头部 ViewHolder
*/
public static class HeaderViewHolder extends RecyclerView.ViewHolder {
public HeaderViewHolder(View itemView) {
super(itemView);
}
}
//底部 ViewHolder
public static class BottomViewHolder extends RecyclerView.ViewHolder {
public BottomViewHolder(View itemView) {
super(itemView);
}
}
//接下来的方法是大家熟悉的方法,不作解释
/**
* 这个方法不能反悔为空,需要继承父类或者返回一个视图。
* @param parent
* @param viewType
* @return
*/
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_TYPE_HEADER) {
return new HeaderViewHolder(mLayoutInflater.inflate(R.layout.rv_header, parent, false));
} else if (viewType == mHeaderCount) {
return new ContentViewHolder(mLayoutInflater.inflate(R.layout.rv_item, parent, false));
} else if (viewType == ITEM_TYPE_BOTTOM) {
return new BottomViewHolder(mLayoutInflater.inflate(R.layout.rv_footer, parent, false));
}
return new ContentViewHolder(mLayoutInflater.inflate(R.layout.rv_item, parent, false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof HeaderViewHolder) {
((HeaderViewHolder) holder).itemView.setVisibility(View.GONE);
} else if (holder instanceof ContentViewHolder) {
((ContentViewHolder) holder).textView.setText(texts[position - mHeaderCount]);
} else if (holder instanceof BottomViewHolder) {
}
}
@Override
public int getItemCount() {
return mHeaderCount + getContentItemCount() + mBottomCount;
}
}
2、在Activity中的使用
package com.hs.recyclerviewadd;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import com.hs.recyclerviewadd.adapter.HeaderBottomAdapter;
/**
* 给RecyclerView添加头布局和脚布局
* RecyclerView通过getItemViewType来实现复杂布局
*/
public class RecyclerActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private LinearLayoutManager layoutManager;
private HeaderBottomAdapter adapter;
private GridLayoutManager gridLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_Recycler);
mRecyclerView = (RecyclerView) findViewById(R.id.rv_list);
//List布局
layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(adapter = new HeaderBottomAdapter(this));
//Grid布局
/*gridLayoutManager = new GridLayoutManager(MainActivity.this, 2);
mRecyclerView.setLayoutManager(gridLayoutManager);//这里用线性宫格显示 类似于grid view
mRecyclerView.setAdapter(adapter = new HeaderBottomAdapter(this));
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return (adapter.isHeaderView(position) || adapter.isBottomView(position)) ? gridLayoutManager.getSpanCount() : 1;
}
});*/
}
}
3、布局
header
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:id="@+id/cv_item" android:foreground="?android:attr/selectableItemBackground" card_view:cardCornerRadius="4dp" card_view:cardElevation="4dp" card_view:cardBackgroundColor="#4CAF50" > <LinearLayout android:layout_width="match_parent" android:layout_height="150dp" > <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="Header" android:textSize="30sp" android:textColor="#ffffff" android:gravity="center" /> </LinearLayout> </android.support.v7.widget.CardView>
item
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/cv_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:foreground="?android:attr/selectableItemBackground" card_view:cardCornerRadius="4dp" card_view:cardElevation="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tv_item_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="8dp" android:text="test" /> </LinearLayout> </android.support.v7.widget.CardView>
footer
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/cv_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:foreground="?android:attr/selectableItemBackground" card_view:cardBackgroundColor="#E91E63" card_view:cardCornerRadius="4dp" card_view:cardElevation="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="150dp"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="Footer" android:textColor="#ffffff" android:textSize="30sp" /> </LinearLayout> </android.support.v7.widget.CardView>