RecyclerView的使用

1.RecyclerView:不仅可以纵向滑动,也可以横向滑动,一个加强的LIstView。

 需要在dependencies中加入


compile 'com.android.support:recyclerview-v7:25.1.0'


2.在布局中加入控件

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

3.同样需要一个子布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_height="50dp">
<ImageView
    android:layout_height="50dp"
    android:layout_width="80dp"
    android:id="@+id/imageView"
    android:src="@mipmap/ic_launcher"/>
    <TextView
        android:id="@+id/textView"
        android:layout_height="50dp"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:text="111"
        android:textColor="#000000"
        android:textSize="20dp"
        android:gravity="center_horizontal|center_vertical" />
</LinearLayout>

4.定义的适配器

public class RecyclerAdapter  extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder>{

    List<MuInfo> data;

    Context context;

    public RecyclerAdapter(List<MuInfo> data, Context context) {
        this.data = data;
        this.context = context;
    }

    @Override
    public RecyclerAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view=LayoutInflater.from(context).inflate(R.layout.itme_layout, parent, false);
        final MyViewHolder holder = new MyViewHolder(view);
        holder.imageView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int postion=holder.getAdapterPosition();
                Toast.makeText(context,postion+"--"+data.get(postion).getName(),Toast.LENGTH_SHORT).show();
            }
        });

        holder.MuinfoitemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int postion=holder.getAdapterPosition();
                Toast.makeText(context,postion+"--"+data.get(postion).getName()+"****",Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }

    @Override
    public void onBindViewHolder(RecyclerAdapter.MyViewHolder holder, final int position) {
        MuInfo muInfo=data.get(position);
        holder.textView.setText(muInfo.getName());
        holder.imageView.setImageDrawable(context.getResources().getDrawable(R.mipmap.a));



    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {
        View  MuinfoitemView;
        ImageView imageView;
        TextView textView;
        public MyViewHolder(View itemView) {
            super(itemView);
            MuinfoitemView=itemView;
            imageView= (ImageView) itemView.findViewById(R.id.imageView);
            textView= (TextView) itemView.findViewById(R.id.textView);
        }
    }
}

5.在MainActivity中实现:下面加粗的控制RecyclerView为横向滑动,如果没有这一行,则默认为纵向滑动,和普通的ListView一样。


public class MainActivity extends AppCompatActivity {

List<MuInfo>data=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MuInfo muInfo=new MuInfo("fgehj","fghjkl");
MuInfo muInfo1=new MuInfo("fghdfj","fghjwertkl");
for(int i=0;i<15;i++){
data.add(muInfo);
data.add(muInfo1);

}

RecyclerView recyclerView= (RecyclerView) findViewById(R.id.recyclerView);
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(linearLayoutManager);
RecyclerAdapter adapter=new RecyclerAdapter(data,getApplicationContext());
recyclerView.setAdapter(adapter);


}
}
 

6.实体类也加上吧:

public class MuInfo {

    private String name;
    private String address;

    public MuInfo(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
View Code

 二、

 1.改变子布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:orientation="vertical"
    android:layout_height="wrap_content">
<ImageView
    android:layout_height="50dp"
    android:layout_width="80dp"
    android:id="@+id/imageView"
    android:src="@mipmap/ic_launcher"/>
    <TextView
        android:id="@+id/textView"
        android:layout_height="wrap_content"
        android:layout_width="80dp"
        android:text="111"
        android:textColor="#000000"
        android:textSize="20dp"
        android:gravity="center_horizontal|center_vertical" />
</LinearLayout>

2.

  for(int i=0;i<80;i++){
            Random random=new Random();
            int x=random.nextInt(5)+1;
            String s="好美的花";
            for(int j=0;j<x;j++){
                s=s+"好美的花";
            }
            data.add(new MuInfo(s,s));



        }

        RecyclerView recyclerView= (RecyclerView) findViewById(R.id.recyclerView);
    // 3:控制显示为3列
StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); RecyclerAdapter adapter=new RecyclerAdapter(data,getApplicationContext()); recyclerView.setAdapter(adapter);

大致如:但是滑动时,并不会出现3列滑动不一致动态效果。

三:如果实现三列,能够单独滑动?

四:RecyclerView的分割线

效果图:

public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
    private int dividerHeight;
    private Paint paint;


    public SpacesItemDecoration(Context context) {
        dividerHeight = context.getResources().getDimensionPixelSize(R.dimen.margin);
        paint=new Paint();
        paint.setColor(context.getResources().getColor(R.color.colorAccent));
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        /**
         * 类似加了一个bottom的padding
         */
        outRect.bottom = dividerHeight;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        int childCount = parent.getChildCount();
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();

        for (int i = 0; i < childCount - 1; i++) {
            View view = parent.getChildAt(i);
            float top = view.getBottom();
            float bottom = view.getBottom() + dividerHeight;
            /**
             * 绘制的矩形也就是从,item的左上角,到右下角,类似于背景,
             * 正好显示出一个横线,就是getItemOffsets空出来的范围
             *
             */
            c.drawRect(left, top, right, bottom, paint);
        }
    }
}

MainActivity只需要在SetAdapter后加入二行代码就可以了:

SpacesItemDecoration decoration=new SpacesItemDecoration(getApplicationContext());
        recyclerView.addItemDecoration(decoration);

上面的代码中SpacesItemDecoration如果不重写OnDraw方法,那么实现的效果只是相当于在item之间空出了距离。

也就是说在ItemDecoration中的方法:

getItemOffsets(),可以实现类似padding的效果

onDraw(),可以实现类似绘制背景的效果,item内容在上面

onDrawOver(),可以绘制在内容的上面,覆盖在item内容

onDrawOver的实现可以一试:想如下:

public class LeftAndRightTagDecoration extends RecyclerView.ItemDecoration{
    private int tagWidth;
    private Paint leftPaint;
    private Paint rightPaint;

    public LeftAndRightTagDecoration(Context context) {
        leftPaint = new Paint();
        leftPaint.setColor(context.getResources().getColor(R.color.colorAccent));
        rightPaint = new Paint();
        rightPaint.setColor(context.getResources().getColor(R.color.colorPrimary));
        tagWidth = context.getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin);
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            int pos = parent.getChildAdapterPosition(child);
            boolean isLeft = pos % 2 == 0;
            if (isLeft) {
                float left = child.getLeft();
                float right = left + tagWidth;
                float top = child.getTop();
                float bottom = child.getBottom();
                c.drawRect(left, top, right, bottom, leftPaint);
            } else {
                float right = child.getRight();
                float left = right - tagWidth;
                float top = child.getTop();
                float bottom = child.getBottom();
                c.drawRect(left, top, right, bottom, rightPaint);

            }
        }
    }
}

在这里 recyclerView.addItemDecoration(decoration);是可以叠加的,可以同时实现加分割线,也可以同时在左右侧加覆盖标签。

<------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->

待续……

根据数据源,分组实现如图的效果:

public class SectionDecoration extends RecyclerView.ItemDecoration {
    private static final String TAG = "SectionDecoration";

    private DecorationCallback callback;
    private TextPaint textPaint;
    private Paint paint;
    private int topGap;
    private Paint.FontMetrics fontMetrics;


    public SectionDecoration(Context context, DecorationCallback decorationCallback) {
        Resources res = context.getResources();
        this.callback = decorationCallback;

        paint = new Paint();
        paint.setColor(res.getColor(R.color.colorAccent));

        textPaint = new TextPaint();
        textPaint.setTypeface(Typeface.DEFAULT_BOLD);
        textPaint.setAntiAlias(true);
        textPaint.setTextSize(80);
        textPaint.setColor(Color.BLACK);
        textPaint.getFontMetrics(fontMetrics);
        textPaint.setTextAlign(Paint.Align.LEFT);
        fontMetrics = new Paint.FontMetrics();
        topGap = res.getDimensionPixelSize(R.dimen.margin1);//32dp


    }


    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int pos = parent.getChildAdapterPosition(view);
        Log.i(TAG, "getItemOffsets:" + pos);
        long groupId = callback.getGroupId(pos);
        if (groupId < 0) return;
        if (pos == 0 || isFirstInGroup(pos)) {//同组的第一个才添加padding
            outRect.top = topGap;
        } else {
            outRect.top = 0;
        }
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View view = parent.getChildAt(i);
            int position = parent.getChildAdapterPosition(view);
            long groupId = callback.getGroupId(position);
            if (groupId < 0) return;
            String textLine = callback.getGroupFirstLine(position).toUpperCase();
            if (position == 0 || isFirstInGroup(position)) {
                float top = view.getTop() - topGap;
                float bottom = view.getTop();
                c.drawRect(left, top, right, bottom, paint);//绘制红色矩形
                c.drawText(textLine, left, bottom, textPaint);//绘制文本
            }
        }
    }


    private boolean isFirstInGroup(int pos) {
        if (pos == 0) {
            return true;
        } else {
            long prevGroupId = callback.getGroupId(pos - 1);
            long groupId = callback.getGroupId(pos);
            return prevGroupId != groupId;
        }
    }

    public interface DecorationCallback {

        long getGroupId(int position);

        String getGroupFirstLine(int position);
    }
}
public interface DecorationCallback {
    long getGroupId(int position);

    String getGroupFirstLine(int position);
}

MainActivity加入代码:

recyclerView.addItemDecoration(new SectionDecoration(this, new SectionDecoration.DecorationCallback() {
            @Override
            public long getGroupId(int position) {
                return Character.toUpperCase(data.get(position).getName().charAt(0));
            }

            @Override
            public String getGroupFirstLine(int position) {
                return data.get(position).getName().substring(0, 1).toUpperCase();
            }
        }));

但是上图中,A,B,C,分组标题也会随着item而不停的移动:

如何实现吸顶效果:看代码:

public class PinnedSectionDecoration extends RecyclerView.ItemDecoration {
    private static final String TAG = "PinnedSectionDecoration";

    private DecorationCallback callback;
    private TextPaint textPaint;
    private Paint paint;
    private int topGap;
    private Paint.FontMetrics fontMetrics;


    public PinnedSectionDecoration(Context context, DecorationCallback decorationCallback) {
        Resources res = context.getResources();
        this.callback = decorationCallback;

        paint = new Paint();
        paint.setColor(res.getColor(R.color.colorAccent));

        textPaint = new TextPaint();
        textPaint.setTypeface(Typeface.DEFAULT_BOLD);
        textPaint.setAntiAlias(true);
        textPaint.setTextSize(80);
        textPaint.setColor(Color.BLACK);
        textPaint.getFontMetrics(fontMetrics);
        textPaint.setTextAlign(Paint.Align.LEFT);
        fontMetrics = new Paint.FontMetrics();
        topGap = res.getDimensionPixelSize(R.dimen.margin1);


    }

    public interface DecorationCallback {

        long getGroupId(int position);

        String getGroupFirstLine(int position);
    }
    private boolean isFirstInGroup(int pos) {
        if (pos == 0) {
            return true;
        } else {
            long prevGroupId = callback.getGroupId(pos - 1);
            long groupId = callback.getGroupId(pos);
            return prevGroupId != groupId;
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int pos = parent.getChildAdapterPosition(view);
        long groupId = callback.getGroupId(pos);
        if (groupId < 0) return;
        if (pos == 0 || isFirstInGroup(pos)) {
            outRect.top = topGap;
        } else {
            outRect.top = 0;
        }
    }


    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
        int itemCount = state.getItemCount();
        int childCount = parent.getChildCount();
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();
        float lineHeight = textPaint.getTextSize() + fontMetrics.descent;

        long preGroupId, groupId = -1;
        for (int i = 0; i < childCount; i++) {
            View view = parent.getChildAt(i);
            int position = parent.getChildAdapterPosition(view);

            preGroupId = groupId;
            groupId = callback.getGroupId(position);
            if (groupId < 0 || groupId == preGroupId) continue;

            String textLine = callback.getGroupFirstLine(position).toUpperCase();
            if (TextUtils.isEmpty(textLine)) continue;

            int viewBottom = view.getBottom();
            float textY = Math.max(topGap, view.getTop());
            if (position + 1 < itemCount) { //下一个和当前不一样移动当前
                long nextGroupId = callback.getGroupId(position + 1);
                if (nextGroupId != groupId && viewBottom < textY ) {//组内最后一个view进入了header
                    textY = viewBottom;
                }
            }
            c.drawRect(left, textY - topGap, right, textY, paint);
            c.drawText(textLine, left, textY, textPaint);
        }

    }

}

MainActivity代码:

        recyclerView.addItemDecoration(new PinnedSectionDecoration(this, new PinnedSectionDecoration.DecorationCallback() {
            @Override
            public long getGroupId(int position) {
                return Character.toUpperCase(data.get(position).getName().charAt(0));
            }

            @Override
            public String getGroupFirstLine(int position) {
                return data.get(position).getName().substring(0, 1).toUpperCase();
            }
        }));
 code地址:
http://pan.baidu.com/s/1eRM2XsI
今天多一点积累,明天少一分烦恼
原文地址:https://www.cnblogs.com/galibujianbusana/p/6394751.html