RecyclerView 使用全体验

来源:互联网 发布:json和javascript 编辑:程序博客网 时间:2024/05/17 09:11

RecyclerView是谷歌support-V7包下新增的控件,用来替代ListView的使用,在RecyclerView标准化了ViewHolder类似于ListView中convertView用来做视图缓存

体验流程:

  • 设置布局管理器(layoutManager)以控制Item的布局方式 <垂直水平ListView,垂直水平GridView,瀑布流>
  • 设置Item的间隔样式
  • 设置Item删除和添加的动画
  • 实现Item的点击和长按事件
app/build.gradle

implementation 'com.android.support:appcompat-v7:25.3.1'implementation 'com.android.support:recyclerview-v7:25.3.1'

RecyclerViewActivity.java

package com.example.testnewas.activity;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.DefaultItemAnimator;import android.support.v7.widget.GridLayoutManager;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.StaggeredGridLayoutManager;import android.view.View;import android.widget.TextView;import android.widget.Toast;import com.example.testnewas.R;import com.example.testnewas.adapters.Radapter;import com.example.testnewas.views.DividerGridItemDecoration;import com.example.testnewas.views.MyDividerItemDecoration;import java.util.ArrayList;public class RActivity extends AppCompatActivity implements View.OnClickListener{    private RecyclerView recyclerView;    private Radapter adapter;    private RecyclerView.LayoutManager layoutManager;    private TextView addItem;    private TextView deleteItem;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_r);                initConfig();        initView();            }    private void initView() {        recyclerView = (RecyclerView) findViewById(R.id.my_recycle_view);        recyclerView.setAdapter(adapter);        //设置布局管理器以控制Item的布局方式,横向、竖向以及瀑布流方式。        recyclerView.setLayoutManager(layoutManager);        //间隔线样式//        recyclerView.addItemDecoration(new MyDividerItemDecoration(this, MyDividerItemDecoration.VERTICAL_LIST));        recyclerView.addItemDecoration(new DividerGridItemDecoration(this));        //默认的Item删除和添加的动画        recyclerView.setItemAnimator(new DefaultItemAnimator());        addItem = (TextView) findViewById(R.id.add_item);        deleteItem = (TextView) findViewById(R.id.delete_item);        addItem.setOnClickListener(this);        deleteItem.setOnClickListener(this);    }    private void initConfig() {        adapter = new Radapter(initData());        //Item点击事件        adapter.setOnItemClickListener(new Radapter.OnItemClickListener() {            @Override            public void onClick(int position) {                Toast.makeText(RActivity.this, "click " + position + " item", Toast.LENGTH_SHORT).show();            }            @Override            public void onLongClick(int position) {                Toast.makeText(RActivity.this, "long click " + position + " item", Toast.LENGTH_SHORT).show();
//长按删除当前item
adapter.deleteItem(position);            }        });        //垂直水平线性列表ListView//        layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);        //垂直滚动GridView(每行4)//        layoutManager = new GridLayoutManager(this, 4);        //水平滚动GridView(每列4)//        layoutManager = new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.HORIZONTAL);        //瀑布流        layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);    }    //模拟数据    private ArrayList<String> initData() {        ArrayList<String> data = new ArrayList<>();        String str = "item-";        for (int i = 0; i< 30; i++) {            data.add(str + i);        }        return data;    }    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.add_item:                adapter.addItem(1);                break;            case R.id.delete_item:                adapter.deleteItem(1);                break;        }    }}

activity_recyclerview.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.example.testnewas.activity.RActivity">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical">        <TextView            android:id="@+id/add_item"            android:layout_width="match_parent"            android:layout_height="50dp"            android:gravity="center"            android:background="#fff000"            android:text="添加item"/>        <TextView            android:id="@+id/delete_item"            android:layout_width="match_parent"            android:layout_height="50dp"            android:gravity="center"            android:background="#cccccc"            android:text="删除item"/>    </LinearLayout>    <android.support.v7.widget.RecyclerView        android:id="@+id/my_recycle_view"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:scrollbars="vertical">    </android.support.v7.widget.RecyclerView></LinearLayout>

RecyclerViewAdapter.java

package com.example.testnewas.adapters;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import com.example.testnewas.R;import java.util.ArrayList;import java.util.List;/** * Created by ylh on 2017/11/7 0007. */public class Radapter extends RecyclerView.Adapter<Radapter.ViewHodler> {    private ArrayList<String> mData;    private OnItemClickListener onItemClickListener;    private ArrayList<Integer> heights;    /**     * 设置回调监听     * @param onItemClickListener     */    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {        this.onItemClickListener = onItemClickListener;    }    public Radapter(ArrayList<String> mData) {        this.mData = mData;        getRandomHeight(this.mData);    }    public void updateData(ArrayList<String> mData) {        this.mData = mData;        notifyDataSetChanged();    }    @Override    public ViewHodler onCreateViewHolder(ViewGroup parent, int viewType) {        //实例化展示的view        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_item, parent, false);        //实例化viewhodler        ViewHodler viewHodler = new ViewHodler(view);        return viewHodler;    }    @Override    public void onBindViewHolder(ViewHodler holder, final int position) {        /**         *瀑布流实现         */        // 得到item的LayoutParams布局参数        ViewGroup.LayoutParams params= holder.itemView.getLayoutParams();        //把随机的高度赋予item布局        params.height = heights.get(position);        // 把params设置给item布局        holder.itemView.setLayoutParams(params);        //绑定数据        holder.mTv.setText(mData.get(position));        if (onItemClickListener != null) {            holder.itemView.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View view) {                    onItemClickListener.onClick(position);                }            });            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {                @Override                public boolean onLongClick(View view) {                    onItemClickListener.onLongClick(position);                    //表示此事件已经消费,不会触发单击事件                    return true;                }            });        }    }    //得到随机item的高度    private void getRandomHeight(List<String> datas) {        heights = new ArrayList<Integer>();        for (int i = 0; i < datas.size(); i++) {            heights.add((int) (200+Math.random()*100));        }    }    @Override    public int getItemCount() {        return mData == null?0:mData.size();    }    public void addItem(int position) {        if (mData == null) {            mData = new ArrayList<>();        }        mData.add(position, "new Item");        //注意,这里更新数据集不是用adapter.notifyDataSetChanged()而是        //notifyItemInserted(position)与notifyItemRemoved(position) 否则没有动画效果。        notifyItemInserted(position);        getRandomHeight(mData);    }    public void deleteItem(int position) {        if (mData == null || mData.isEmpty()) {            return;        }        mData.remove(position);        notifyItemRemoved(position);        getRandomHeight(mData);    }    public interface OnItemClickListener {        void onClick(int position);        void onLongClick(int position);    }    public static class ViewHodler extends RecyclerView.ViewHolder{        TextView mTv;        public ViewHodler(View itemView) {            super(itemView);            mTv = (TextView) itemView.findViewById(R.id.item_tv);        }    }}

view_rv_item.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="100dp"    android:orientation="vertical">    <TextView        android:id="@+id/item_tv"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:gravity="center"        android:background="#fccfcc"        android:layout_margin="5dp"        android:text="item"/></LinearLayout>

MyDividerItemDecoration.java

package com.example.testnewas.views;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.v4.view.ViewCompat;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;/** * Created by ylh on 2017/11/7 0007. * * RecyclerView的间隔样式 */public class MyDividerItemDecoration 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 MyDividerItemDecoration(Context context, int orientation) {        // 获取默认主题的属性        final TypedArray a = context.obtainStyledAttributes(ATTRS);        mDivider = a.getDrawable(0);        a.recycle();        setOrientation(orientation);    }    @Override    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {        // 绘制间隔        if (mOrientation == VERTICAL_LIST) {            drawVertical(c, parent);        } else {            drawHorizontal(c, parent);        }    }    @Override    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {        if (mOrientation == VERTICAL_LIST) {            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());        } else {            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);        }    }    private void setOrientation(int orientation) {        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {            throw new IllegalArgumentException("invalid orientation");        }        mOrientation = orientation;    }    /**     * 绘制间隔     */    private 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 +                    Math.round(ViewCompat.getTranslationY(child));            final int bottom = top + mDivider.getIntrinsicHeight();            mDivider.setBounds(left, top, right, bottom);            mDivider.draw(c);        }    }    /**     * 绘制间隔     */    private 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 +                    Math.round(ViewCompat.getTranslationX(child));            final int right = left + mDivider.getIntrinsicHeight();            mDivider.setBounds(left, top, right, bottom);            mDivider.draw(c);        }    }}

DividerGridItemDecoration.java

package com.example.testnewas.views;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.GridLayoutManager;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.StaggeredGridLayoutManager;import android.view.View;/** * @author zhy * * RecyclerView-GridView的间隔样式 */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, RecyclerView.State state)    {        drawHorizontal(c, parent);        drawVertical(c, parent);    }    private int getSpanCount(RecyclerView parent)    {        // 列数        int spanCount = -1;        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();        if (layoutManager instanceof GridLayoutManager)        {            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();        } else if (layoutManager instanceof StaggeredGridLayoutManager)        {            spanCount = ((StaggeredGridLayoutManager) layoutManager)                    .getSpanCount();        }        return spanCount;    }    public void drawHorizontal(Canvas c, RecyclerView parent)    {        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.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 boolean isLastColum(RecyclerView parent, int pos, int spanCount,                                int childCount)    {        RecyclerView.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;    }    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,                              int childCount)    {        RecyclerView.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();        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());        }    }}

自定义间隔样式
<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</item >    </style>
divider.xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"    android:shape="rectangle" >    <!-- 填充的颜色 -->    <solid android:color ="#ff0000"/>    <!--  线条大小 -->    <size android:height ="1dp" android:width ="1dp"/></shape>

自定义的各种动画效果,github上已经有很多类似的项目了,这里我们直接引用下:RecyclerViewItemAnimators,大家自己下载查看。 
提供了SlideInOutLeftItemAnimator,SlideInOutRightItemAnimator, 
SlideInOutTopItemAnimator,SlideInOutBottomItemAnimator等动画效果。

瀑布流效果.png





阅读全文
0 0
原创粉丝点击