RecyclerView作为升级版的ListView和GridView,更加的先进和灵活。接下来就介绍下RecyclerView的用法。
首先,在gradle脚本中添加,
compile 'com.android.support:recyclerview-v7:23.0.1'
在布局中引用
<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=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
RecyclerView是没有divider属性的。
Adapter的编写,这里的Adapter应该继承public static abstract class Adapter {},可以看到,这里内部就有一个ViewHolder,我们只需要实现自己的ViewHolder就好,我们必须要实现Adapter的3个方法:
getItemCount 得到view的数目
最终的代码我会在后面给出。
设置分割线
recyclerView.addItemDecoration(new DividerItemDecoration(MainActivity.this, DividerItemDecoration.VERTICAL_LIST));
我们通过addItemDecoration来添加分割线,DividerItemDecoration这个类就是实现分割线的。
这个类我是抄网上的。。。
package gl.com.as;
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 mac on 15-10-9. */
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 orienttation){
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orienttation);
}
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, RecyclerView.State state) {
if (mOrientation==VERTICAL_LIST){
drawVertival(c,parent);
}else{
drawHorizontal(c,parent);
}
}
/** * draw vertival line * @param c * @param parent */
public void drawVertival(Canvas c,RecyclerView parent){
final int left = parent.getPaddingLeft();
final int right = 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,bottom,right);
mDivider.draw(c);
}
}
/** * draw horizaontal line * @param c * @param parent */
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.getIntrinsicWidth();
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);
}
}
}
上面的类就实现了横 竖2中分割线,想实现其他样式的参考张鸿洋,
LayoutManager
这里有3种:
1.LinearLayoutManager(..) listview风格
2.GridLayoutManager(..) GridView
3.StaggeredGridLayoutManager(..) 同样可以实现gridview,还可以实现瀑布流,只要设置好高度就行。
添加增加删除动画
recyclerView.setItemAnimator(new DefaultItemAnimator());
这是系统默认的动画,我们当然也可以定制自己的动画啦。具体实现参考DefaultItemAnimator类的实现,不过github上 有很多牛人已经做了很多了。小伙伴们可以去github上找找。Github上的动画
public interface OnItemClickListener {
void onClick(int pos);
void onLongClick(int pos);
}
private OnItemClickListener listener;
public void setOnclickListener(OnItemClickListener listener){
this.listener=listener;
}
//然后在onBindViewHolder中添加
if (listener!=null){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos=holder.getLayoutPosition();
listener.onClick(pos);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos = holder.getLayoutPosition();
listener.onLongClick(pos);
return false;
}
});
}
接下来,在Activity中
mAdapter.setOnclickListener(new RecyclerViewAdapter.OnItemClickListener() {
@Override
public void onClick(int pos) {
Toast.makeText(MainActivity.this,pos+"click",Toast.LENGTH_SHORT).show();
}
@Override
public void onLongClick(int pos) {
Toast.makeText(MainActivity.this,pos+"long click",Toast.LENGTH_SHORT).show();
}
});
package gl.com.as;
import android.content.Context;
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 java.util.ArrayList;
import java.util.List;
/** * Created by mac on 15-10-9. */
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>{
private Context context;
private List<String> mDatas;
private List<Integer> mHeight;
public RecyclerViewAdapter(Context context,List<String> mDatas){
this.context=context;
this.mDatas=mDatas;
mHeight = new ArrayList<Integer>();
for (int i =0;i<mDatas.size();i++){
mHeight.add((int) (100+Math.random()*300));
}
}
public interface OnItemClickListener {
void onClick(int pos);
void onLongClick(int pos);
}
private OnItemClickListener listener;
@Override
public int getItemViewType(int position) {
if (position%2==0){
return 0;
}else{
return 1;
}
}
public void setOnclickListener(OnItemClickListener listener){
this.listener=listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewHolder holder=null;
Log.e("tag","this is on onCreateViewHolder"+viewType);
switch (viewType){
case 0:
holder = new ViewHolder(LayoutInflater.from(context).inflate(R.layout.rccyclerview_item,parent,false));
break;
default:
holder = new ViewHolder(LayoutInflater.from(context).inflate(R.layout.rccyclerview_item2,parent,false));
break;
}
return holder;
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
ViewGroup.LayoutParams lp = holder.textView.getLayoutParams();
lp.height=mHeight.get(position);
holder.textView.setLayoutParams(lp);
holder.textView.setText(mDatas.get(position));
if (listener!=null){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos=holder.getLayoutPosition();
listener.onClick(pos);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos = holder.getLayoutPosition();
listener.onLongClick(pos);
return false;
}
});
}
}
@Override
public int getItemCount() {
return mDatas.size();
}
public void addData(int position){
mDatas.add(position,"Insert One");
notifyItemInserted(position);
}
public void removeData(int position){
mDatas.remove(position);
notifyItemRemoved(position);
}
class ViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
public ViewHolder(View itemView) {
super(itemView);
textView= (TextView) itemView.findViewById(R.id.id_text);
}
}
}
<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=".MainActivity">
<android.support.v4.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/image"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:divider="#dddd0000"
android:dividerHeight="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</android.support.v4.widget.SwipeRefreshLayout>
<ImageView
android:id="@+id/image"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/ic_launcher"
android:visibility="gone"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
其实这里用FrameLayout更好一点,我这里为了省事。下拉刷新实现SwipeRefreshLayout.OnRefreshListener接口就好。上拉刷新的话
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int lastVisiableItem = ((LinearLayoutManager)manager) .findLastVisibleItemPosition();
if (lastVisiableItem+1==mDatas.size()){
image.setVisibility(View.VISIBLE);
//do something
}
}
});
这里是LinearLayoutManager,其他2个的话做相应的逻辑处理。关于SwipeRefreshLayout封装上拉加载更多,网上很多人写了。百度。。。
private ArrayList<FixedViewInfo> mHeaderViewInfos = Lists.newArrayList();
private ArrayList<FixedViewInfo> mFooterViewInfos = Lists.newArrayList();
public void addHeaderView(View v, Object data, boolean isSelectable) {
final FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = data;
info.isSelectable = isSelectable;
mHeaderViewInfos.add(info);
mAreAllItemsSelectable &= isSelectable;
// Wrap the adapter if it wasn't already wrapped.
if (mAdapter != null) {
if (!(mAdapter instanceof HeaderViewListAdapter)) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
}
// In the case of re-adding a header view, or adding one later on,
// we need to notify the observer.
if (mDataSetObserver != null) {
mDataSetObserver.onChanged();
}
}
}
关键就在于HeaderViewListAdapter。根据HeaderViewListAdapter的代码依葫芦画瓢就行了。小弟在这里就不献丑了。给出参考资料,去看这位大神的代码吧。添加头部尾部
好累,到这里就完了。
参考资料:添加头尾
参考资料:张鸿洋