RecycleView简单介绍
RecycleView相对于原来的ListView和GridView要灵活很多,可以很快的在listView和gridView以及瀑布流之间进行切换,它主要提供了3中布局方式,LinearLayoutManager(ListView)、GridLayoutManager(GridView)、StaggeredGridLayoutManager(瀑布流)
1、主界面,已经写了3个布局类型 只需要简单的切换,就可以看到不同的效果
public class MainActivity extends AppCompatActivity {
private RecyclerView rv;
private ArrayList<String> mDatas;
private MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
initDatas();
initView();
}
public void initDatas(){
mDatas = new ArrayList<>();
for (int i = 'A'; i < 'Z'; i++) {
mDatas.add((char)i+"");
}
}
public void initView(){
rv = (RecyclerView) findViewById(R.id.id_recycler);
adapter = new MyAdapter(getApplicationContext(),mDatas);
LinearLayoutManager manager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);//ListView
GridLayoutManager gm = new GridLayoutManager(this,3);//GridView
StaggeredGridLayoutManager sgm = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);//瀑布流
//这里的点击事件是我们自己在adapter中定义的接口,因为RecycleView的点击事件是在adapter中,所以我们要对外提供一个接口
adapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this,"点击事件",Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position) {
Toast.makeText(MainActivity.this,"长按点击事件"+position,Toast.LENGTH_SHORT).show();
}
});
//这里是定义分割线,如果不需要分割线,可以不用添加addItemDecoration
rv.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));
rv.setLayoutManager(manager);
rv.setAdapter(adapter);
}
}
2、Adapter
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
private Context mContext;
private LayoutInflater mInflater;
private ArrayList<String> mDatas;
public MyAdapter(Context context,ArrayList<String> mDatas){
this.mContext = context;
this.mDatas = mDatas;
mInflater = LayoutInflater.from(mContext);
}
//对外提供的点击接口
public interface OnItemClickListener{
void onItemClick(View view,int position);
void onItemLongClick(View view,int position);
}
private OnItemClickListener mItemClickListener;
public void setOnItemClickListener(OnItemClickListener listener){
this.mItemClickListener = listener;
}
/**
* 创建viewHolder
* @param parent
* @param viewType
* @return
*/
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//这里我们都不需要进行类似于ListView中convertView的复用处理,因为在RecycleView的底层已经对复用进行过处理
View view = mInflater.inflate(R.layout.item_text,parent,false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
/**
* 绑定ViewHolder
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
holder.tv.setText(mDatas.get(position));
final int pos = holder.getLayoutPosition();
//holder.tv.setHeight(300+( pos % 2 ) * 30 );瀑布流时显示大小不同的item布局
if(mItemClickListener != null){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemClickListener.onItemClick(holder.itemView,pos);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mItemClickListener.onItemLongClick(holder.itemView,pos);
return true;//返回true,将点击的动作事件消费掉,防止点击事件和长按事件重复执行
}
});
}
}
/**
* recyclerView的数量
* @return
*/
@Override
public int getItemCount() {
return mDatas.size();
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView tv;
public MyViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv);
}
}
3、在使用RecycleView中,分割线需要自行定义,不像lsitView中那么简单,不过已经有人在github上提供了定义好的,我们可以直接使用,然后使用Shape来自定义自己需要的分割线的颜色和大小
public class DividerItemDecoration extends RecyclerView.ItemDecoration
{
private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public DividerItemDecoration(Context context, int orientation)
{
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation)
{
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST)
{
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
@Override
public void onDraw(Canvas c, RecyclerView parent)
{
Log.v("recyclerview - itemdecoration", "onDraw()");
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent)
{
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
RecyclerView v = new RecyclerView(
parent.getContext());
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent)
{
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition,
RecyclerView parent)
{
if (mOrientation == VERTICAL_LIST)
{
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else
{
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
默认使用的是默认的分割线,如果需要自定义,需要定义shape,并在style的主题中,添加item属性
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:height="4dp"/>
<solid android:color="#ffff00"/>
</shape>
主题中的属性
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
//上面3个是默认的属性,下面的是分割线的属性,引用的是我们自定义的分割线,因为在DividerItemDecoration这个类中,我们的数组属性使用的是默认的listDivider,所以这里的名字必须一致
<item name="android:listDivider">@drawable/divider_line</item>
</style>