控件:RecyclerView

版权声明:本文为博主原创文章,码字不易,转载时请标明具体出处(博主名+博客页面链接),万分感谢Thanks♪(・ω・)ノ https://blog.csdn.net/An_nAl/article/details/81063764

添加依赖

 compile 'com.android.support:recyclerview-v7:26.+'

Recyclerview.getLayoutPosition()问题

使用Recyclerview 时,如果要添加item的点击监听等功能,可以在Recyclerview.Adapter的onBindViewHolder中设置:

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
    holder.tv.setHeight(150*(1+position%4));
    holder.tv.setWidth(150*(1+position%4));
    holder.tv.setText(data.get(position));
    if(mOnItemClickListener!=null){
        holder.tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos=holder.getLayoutPosition();
                mOnItemClickListener.onItemClick(v,pos);
            }
        });
        holder.tv.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                int pos=holder.getLayoutPosition();
                mOnItemClickListener.onItemLongClick(v,pos);
                return false;
            }
        });
    }
}

注意这里使用了ViewHolder的getLayoutPosition方法,此方法返回的pos值与onBindViewHolder方法传入的position值有可能不同。
根据SDK中的解释,在Recyclerview 进行添加、移除item等操作时,position位置可能会变化,而所有的adapter的刷新并不总是及时的,只有这个方法返回的才是当前item经过一些变换后所处的真正位置。
getLayoutPosition:返回布局中最新的计算位置,和用户所见到的位置一致,当做用户输入(例如点击事件)的时候考虑使用

getAdapterPosition:返回数据在Adapter中的位置(也许位置的变化还未来得及刷新到布局中),当使用Adapter的时候(例如调用Adapter的notify相关方法时)考虑使用

网格布局

xml布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:scrollbars="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

item布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:background="#d4d2d2"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv_item"
        android:layout_width="match_parent"
        android:background="#FFFFFF"
        android:layout_height="200dp"
        android:layout_margin="10dp"
        android:gravity="center"
        android:textSize="22sp"
        android:text="item"/>

</LinearLayout>

Adapter

public class InfoRecyclerViewAdapter extends RecyclerView.Adapter<InfoRecyclerViewAdapter.ViewHolder> {

    private ArrayList<String> mData;
  
    /**
     * 事件回调监听
     */
    private InfoRecyclerViewAdapter.OnItemClickListener onItemClickListener;


    public InfoRecyclerViewAdapter(ArrayList<String> data) {
        this.mData = data;      
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;
        // 实例化展示的view
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list_vertical, parent, false);
        // 实例化viewholder
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        // 绑定数据
        holder.tvItem.setText(mData.get(position));
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                if(onItemClickListener != null) {
                    int pos = holder.getLayoutPosition();
                    onItemClickListener.onItemClick(holder.itemView, pos);
                }
            }
        });

        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if(onItemClickListener != null) {
                    int pos = holder.getLayoutPosition();
                    onItemClickListener.onItemLongClick(holder.itemView, pos);
                }
                //表示此事件已经消费,不会触发单击事件
                return true;
            }
        });
    }

    @Override
    public int getItemCount() {
        return mData == null ? 0 : mData.size();
    }

    /**
     * 新增item
     */
    public void addNewItem() {
        if(mData == null) {
            mData = new ArrayList<>();
        }
        mData.add(0, "new Item");
        notifyItemInserted(0);
    }

    /**
     * 删除item
     */
    public void deleteItem() {
        if(mData == null || mData.isEmpty()) {
            return;
        }
        mData.remove(0);
        notifyItemRemoved(0);
    }

    /**
     * 更新整个列表数据
     * @param data
     */
    public void updateData(ArrayList<String> data) {
        this.mData = data;
        notifyDataSetChanged();
    }

    /**
     * 设置回调监听
     * @param listener
     */
    public void setOnItemClickListener(InfoRecyclerViewAdapter.OnItemClickListener listener) {
        this.onItemClickListener = listener;
    }

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
        void onItemLongClick(View view, int position);
    }

    static class ViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.tv_item)
        TextView tvItem;

        ViewHolder(View view) {
            super( view);
            ButterKnife.bind(this, view);
        }
    }
}

ItemDecoration样式drawable

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:centerColor="#ff00ff00"
        android:endColor="#ff0000ff"
        android:startColor="#ffff0000"
        android:type="linear" />
    <size android:height="4dp"/>

</shape>
 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- 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/bg_divider </item >       
    </style>

ItemDecoration

public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
    private Drawable mDivider;

    public DividerGridItemDecoration(Context context) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, State state) {
        drawHorizontal(c, parent);
        drawVertical(c, parent);
    }

    /**
     * 绘制水平分割线
     */
    public void drawHorizontal(Canvas c, RecyclerView parent) {
        int childCount = parent.getChildCount();//item总个数
        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.getLeft() - params.leftMargin;
            final int right = child.getRight() + params.rightMargin
                    + mDivider.getIntrinsicWidth();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }
    /**
     * 绘制垂直分割线
     */
    public void drawVertical(Canvas c, RecyclerView parent) {
        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.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    /**
     * 列数
     */
    private int getSpanCount(RecyclerView parent) {
        int spanCount = -1;
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
        }
        return spanCount;
    }

    /**
     * 是否是最后一列
     */
    private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
                                int childCount) {
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            if ((pos + 1) % spanCount == 0) // 如果是最后一列,则不需要绘制右边
            {
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                if ((pos + 1) % spanCount == 0) // 如果是最后一列,则不需要绘制右边
                {
                    return true;
                }
            } else {
                childCount = childCount - childCount % spanCount;
                if (pos >= childCount) // 如果是最后一列,则不需要绘制右边
                    return true;
            }
        }
        return false;
    }

    /**
     * 是否是最后一行
     * @param parent
     * @param pos 当前item的位序
     * @param spanCount 列数
     * @param childCount item总个数
     * @return
     */
    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
                              int childCount) {
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            childCount = childCount - childCount % spanCount;
            // 如果是最后一行,则不需要绘制底部
            if (pos >= childCount){
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            // StaggeredGridLayoutManager 且纵向滚动
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                childCount = childCount - childCount % spanCount;
                // 如果是最后一行,则不需要绘制底部
                if (pos >= childCount){
                    return true;
                }
            } else {
                // StaggeredGridLayoutManager 且横向滚动
                // 如果是最后一行,则不需要绘制底部
                if ((pos + 1) % spanCount == 0) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition,
                               RecyclerView parent) {
        int spanCount = getSpanCount(parent);//列数
        int childCount = parent.getAdapter().getItemCount();//item总个数
        if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
        {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
        {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(),
                    mDivider.getIntrinsicHeight());
        }
    }
}

activity

 //竖直滑动,每行只显示四个
        GridLayoutManager infoLayoutManager = new GridLayoutManager( this,4);
        InfoRecyclerViewAdapter infoRecyclerViewAdapter = new InfoRecyclerViewAdapter(getData(), "");

        // 设置布局管理器
        infoRecyclerView.setLayoutManager(infoLayoutManager);
        // 设置adapter
        infoRecyclerView.setAdapter(infoRecyclerViewAdapter);
        //设置间隔样式
        infoRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));

垂直列表(像ListView)

activity

infoLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        // 设置布局管理器
        infoRecyclerView.setLayoutManager(infoLayoutManager);
        // 设置adapter
        infoRecyclerViewAdapter = new InfoRecyclerViewAdapter(getData());
        //item的点击事件
        infoRecyclerViewAdapter.setOnItemClickListener(new InfoRecyclerViewAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(ActVerticalRecycler.this,"click " + position + " item", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onItemLongClick(View view, int position) {
                Toast.makeText(ActVerticalRecycler.this,"long click " + position + " item", Toast.LENGTH_SHORT).show();
            }
        });
        infoRecyclerView.setAdapter(infoRecyclerViewAdapter);
        //设置间隔样式
//        infoRecyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL));
        infoRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));
        // 设置Item添加和移除的动画
        infoRecyclerView.setItemAnimator(new DefaultItemAnimator());

水平列表

activity

 // 设置布局管理器
        infoLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        infoRecyclerView.setLayoutManager(infoLayoutManager);
        // 设置adapter
        infoRecyclerViewAdapter = new InfoRecyclerViewAdapter( getData());
        infoRecyclerView.setAdapter(infoRecyclerViewAdapter);
        //设置间隔样式
//        infoRecyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.HORIZONTAL));
        infoRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));

新增item

infoRecyclerViewAdapter.addNewItem();
                // 由于Adapter内部是直接在首个Item位置做增加操作,增加完毕后列表移动到首个Item位置
                infoLayoutManager.scrollToPosition(0);

删除item

infoRecyclerViewAdapter.deleteItem();
                // 由于Adapter内部是直接在首个Item位置做删除操作,删除完毕后列表移动到首个Item位置
                infoLayoutManager.scrollToPosition(0);

猜你喜欢

转载自blog.csdn.net/An_nAl/article/details/81063764