标签:
1.RecyclerView是什么?
RecylerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,这一点从它的名字recylerview即回收view也可以看出。看到这也许有人会问,不是已经有ListView了吗,为什么还要RecylerView呢?这就牵扯到第二个问题了。
2.RecyclerView的优点是什么?
根据官方的介绍RecylerView是ListView的升级版,既然如此那RecylerView必然有它的优点,现就RecylerView相对于ListView的优点罗列如下:
①RecylerView封装了viewholder的回收复用,也就是说RecylerView标准化了ViewHolder,编写Adapter面向的是ViewHolder而不再是View了,复用的 逻辑被封装了,写起来更加简单。
②提供了一种插拔式的体验,高度的解耦,异常的灵活,针对一个Item的显示RecylerView专门抽取出了相应的类,来控制Item的显示,使其的扩展性非常强。例如:你想控制横向或者纵向滑动列表效果可以通过LinearLayoutManager这个类来进行控制(与GridView效果对应的是GridLayoutManager,与瀑布流对应的还有StaggeredGridLayoutManager等),也就是说RecylerView不再拘泥于ListView的线性展示方式,它也可以实现GridView的效果等多种效果。你想控制Item的分隔线,可以通过继承RecylerView的ItemDecoration这个类,然后针对自己的业务需求去抒写代码。
③可以控制Item增删的动画,可以通过ItemAnimator这个类进行控制,当然针对增删的动画,RecylerView有其自己默认的实现。
使用RecyclerView 需要在build.gradle引入compile ‘com.android.support:design:23.1.0‘
效果图:
每个item布局item.xml:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="#44ff0000" android:layout_height="wrap_content" > <TextView android:id="@+id/id_num" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_gravity="left" android:text="左边" /> <TextView android:id="@+id/id_num2" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_gravity="right" android:text="右边" /> </FrameLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.android.mx.myapplication.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/id_recyclerview" android:divider="#ffff0000" android:dividerHeight="10dp" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>主窗体MainActivity.java:
package com.android.mx.myapplication; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private List<String> mDatas; private HomeAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mAdapter = new HomeAdapter(); mAdapter.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(MainActivity.this, "Click" + mDatas.get(position), Toast.LENGTH_SHORT).show(); } @Override public void onItemLongClick(View view, int position) { mAdapter.remove(position); //remove the item Toast.makeText(MainActivity.this, "LongClick" + mDatas.get(position), Toast.LENGTH_SHORT).show(); } }); mRecyclerView.setAdapter(mAdapter); mRecyclerView.addItemDecoration(new DividerItemDecoration(MainActivity.this, LinearLayoutManager.VERTICAL)); } protected void initData() { mDatas = new ArrayList<String>(); for (int i = 'A'; i < 'z'; i++) { mDatas.add("" + (char) i); } } interface OnItemClickListener { public void onItemClick(View view, int position); public void onItemLongClick(View view, int position); } public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.ItemViewHolder> { private OnItemClickListener mOnItemClickListener; @Override public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ItemViewHolder holder = new ItemViewHolder(LayoutInflater.from( MainActivity.this).inflate(R.layout.item, parent, false)); return holder; } @Override public void onBindViewHolder(final ItemViewHolder itemViewHolder, int position) { itemViewHolder.mTextView.setText(mDatas.get(position)); if (mOnItemClickListener != null) { /** * 这里加了判断,itemViewHolder.itemView.hasOnClickListeners() * 目的是减少对象的创建,如果已经为view设置了click监听事件,就不用重复设置了 * 不然每次调用onBindViewHolder方法,都会创建两个监听事件对象,增加了内存的开销 */ if (!itemViewHolder.itemView.hasOnClickListeners()) { Log.e("ListAdapter", "setOnClickListener"); itemViewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int pos = itemViewHolder.getPosition(); mOnItemClickListener.onItemClick(v, pos); } }); itemViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { int pos = itemViewHolder.getPosition(); mOnItemClickListener.onItemLongClick(v, pos); return true; } }); } } } /** * 移除指定位置元素 * * @param position * @return */ public String remove(int position) { if (position > mDatas.size() - 1) { return null; } String value = mDatas.remove(position); notifyItemRemoved(position); return value; } public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) { this.mOnItemClickListener = mOnItemClickListener; } @Override public int getItemCount() { return mDatas.size(); } /** * 处理item的点击事件和长按事件 */ class ItemViewHolder extends RecyclerView.ViewHolder { private TextView mTextView; public ItemViewHolder(View itemView) { super(itemView); mTextView = (TextView) itemView.findViewById(R.id.id_num); } } } }
public static abstract class ItemDecoration { public void onDraw(Canvas c,RecyclerView parent,State state) { onDraw(c,parent); } public void onDrawOver(Canvas c,RecyclerView parent,State state) { onDrawOver(c,parent); } public void getItemOffsets(RectoutRect, View view,RecyclerView parent,State state) { getItemOffsets(outRect,((LayoutParams)view.getLayoutParams()).getViewLayoutPosition(),parent); } }
package com.android.mx.myapplication; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; /** * Created by mxuan on 2016-07-16. */ 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) { 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); 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); } } }
<resources> <!-- 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> <item name="android:listDivider">@drawable/divider_bg</item> </style> </resources>
标签:
原文地址:http://blog.csdn.net/xiexuan2007/article/details/51925695