Android的RecyclerView的使用
Android推出RecyclerView的时间不算短了,一直没有具体去了解。前段时间公司做代码优化,用到这个。具体了解之后发现其功能确实强大。下面来基本解释RecyclerView控件
RecyclerView干啥用的?
可以理解为效率更高的ListView和GridView,而且功能更强大。最关键的一个地方,貌似是听说在Adapter中复用之前已经产生的item,这个估计得查看内存方可以看得清楚。
使用RecyclerView,我们需要了解一下三个元素
1、RecyclerView.Adapter
2、LayoutManager
3、ItemAnimator
1、RecyclerView.Adapter
作为这么一个看起来蛮叼的控件,自然用到了各种很厉害的设计模式(这个,我不清楚)。面向接口编程是肯定的,那么我们来看看它的Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
public class ViewHolder extends RecyclerView.ViewHolder {
public VideoListItem txt1;
public VideoListItem txt2;
public VideoListItem txt3;
public VideoListItem txt4;
public ViewHolder(View itemView) {
super(itemView);
}
public VideoListItem getTxt1() {
return txt1;
}
public void setTxt1(VideoListItem txt1) {
this.txt1 = txt1;
}
public VideoListItem getTxt2() {
return txt2;
}
public void setTxt2(VideoListItem txt2) {
this.txt2 = txt2;
}
public VideoListItem getTxt3() {
return txt3;
}
public void setTxt3(VideoListItem txt3) {
this.txt3 = txt3;
}
public VideoListItem getTxt4() {
return txt4;
}
public void setTxt4(VideoListItem txt4) {
this.txt4 = txt4;
}
}
private LayoutInflater inflater;
public MyAdapter() {
inflater = LayoutInflater.from(VideoListActivity.this);
}
@Override
public int getItemCount() {
int size = mVideoList.size();
if (size == 0) {
return 0;
}
int count = mVideoList.size() / COLUMN;
if (size % COLUMN == 0) {
return count + 1;
} else {
return count + 2;
}
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
System.out.println("wangzx**" +"onCreateViewHolder");
int firstIndex = position * COLUMN;
int size = mVideoList.size();
bindItem(firstIndex + 0, size, position, viewHolder.txt1);
bindItem(firstIndex + 1, size, position, viewHolder.txt2);
bindItem(firstIndex + 2, size, position, viewHolder.txt3);
bindItem(firstIndex + 3, size, position, viewHolder.txt4);
}
private void bindItem(int index, int size, int position,
VideoListItem item) {
VideoInfo historyData0 = null;
if (size > index) {
item.setVisibility(View.VISIBLE);
historyData0 = mVideoList.get(index);
item.setCurrentLine(position);
item.setIndex(index);
item.setView_id(historyData0.getVideo_id());
item.getmTextView().setText(historyData0.getVideo_name());
item.getmRoundedImageView().setCornerRadiusDimen(R.dimen.video_list_corner_radius);
item.getmRoundedImageView().setImageResource(R.drawable.history_default);
imageLoader.displayImage(historyData0.getVideo_img_url(),item.getmRoundedImageView());
}
else{
item.setVisibility(View.INVISIBLE);
}
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
System.out.println("wangzx**" +"onCreateViewHolder");
View convertView = inflater.inflate(R.layout.video_list_itemlist, parent,
false);
ViewHolder viewHolder = new ViewHolder(convertView);
viewHolder.txt1 = (VideoListItem) convertView
.findViewById(R.id.item1);
viewHolder.txt2 = (VideoListItem) convertView
.findViewById(R.id.item2);
viewHolder.txt3 = (VideoListItem) convertView
.findViewById(R.id.item3);
viewHolder.txt4 = (VideoListItem) convertView
.findViewById(R.id.item4);
View itemBackground_focus1 = viewHolder.txt1.findViewById(R.id.background_focus);
View itemBackground_focus2 = viewHolder.txt2.findViewById(R.id.background_focus);
View itemBackground_focus3 = viewHolder.txt3.findViewById(R.id.background_focus);
View itemBackground_focus4 = viewHolder.txt4.findViewById(R.id.background_focus);
itemBackground_focus1.setOnFocusChangeListener(mVideoListItemOnFocus);
itemBackground_focus2.setOnFocusChangeListener(mVideoListItemOnFocus);
itemBackground_focus3.setOnFocusChangeListener(mVideoListItemOnFocus);
itemBackground_focus4.setOnFocusChangeListener(mVideoListItemOnFocus); //焦点的变换暂时不考虑在内(焦点的获取同步更新videoCount数据)
itemBackground_focus1.setOnClickListener(mOnClick);
itemBackground_focus2.setOnClickListener(mOnClick);
itemBackground_focus3.setOnClickListener(mOnClick);
itemBackground_focus4.setOnClickListener(mOnClick);
itemBackground_focus1.setOnKeyListener(mWheelKeyListener);
itemBackground_focus2.setOnKeyListener(mWheelKeyListener2);
itemBackground_focus3.setOnKeyListener(mWheelKeyListener2);
itemBackground_focus4.setOnKeyListener(mWheelKeyListener2);
return viewHolder;
}
}
图RecyclerView
public class Byhistory__Adapater extends BaseAdapter {
private ArrayList<Byhistory_Item> byhistorylist;
private LayoutInflater mInflater;
public Byhistory__Adapater(Context context,ArrayList<Byhistory_Item> byhistory_list){
this.byhistorylist = byhistory_list;
this.mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return this.byhistorylist.size();
}
@Override
public Object getItem(int arg0) {
return null;
}
@Override
public long getItemId(int arg0) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup arg2) {
Byhistory_Item holder;
if(convertView == null){
convertView = mInflater.inflate(R.layout.byhistory_item, null);
holder = new Byhistory_Item();
holder.setLayout_Image((ImageView) convertView.findViewById(R.id.history_item_image));
holder.setLayout_ID((TextView) convertView.findViewById(R.id.history_item_name));
// holder.setLayout_price((TextView) convertView.findViewById(R.id.history_item_price));
holder.setLayout_count((TextView) convertView.findViewById(R.id.history_item_count));
holder.setLayout_business((ImageView) convertView.findViewById(R.id.history_item_more));
convertView.setTag(holder);
}else{
holder = (Byhistory_Item) convertView.getTag();
}
Byhistory_Item dd = byhistorylist.get(position);
// holder.getLayout_Image().setBackgroundResource(Integer.valueOf(dd.getItem_Tile_Image()));
holder.getLayout_ID().setText(dd.getItem_Title_ID());
// holder.getLayout_price().setText(dd.getItem_price());
holder.getLayout_count().setText(dd.getItem_count());
// holder.getLayout_business().setBackgroundResource(Integer.valueOf(dd.getItem_business()));
return convertView;
}
}
图 ListView
对比listview的adapater我们立马就能看出来。这里它单独弄出来了一个ViewHolder。这个ViewHolder可以是多个layout的组合,这样做更加灵活,使得布局更加多变(可以仔细想一下是为什么)。
ListView的Adapter通常是直接导入数据,下滑。但是RecyclerView的Adapter就不是下滑这么简单,上下滑动和左右滑动都成为可能。这个关键就是LayoutManager的功劳了。配合ViewHolder的多样性,功能真是很强大。
2、LayoutManager
知道android貌似确实是有不止一种LayoutManager,但是其他的没有接触过,暂就不发表评论,以后可能会补充
LinearLayoutManager
public class MyLinearLayoutManager extends LinearLayoutManager {
public MyLinearLayoutManager(Context context) {
super(context);
}
public MyLinearLayoutManager(Context context, int orientation,
boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public boolean requestChildRectangleOnScreen(RecyclerView parent,
View child, Rect rect, boolean immediate) {
final int parentLeft = getPaddingLeft();
final int parentTop = getPaddingTop();
final int parentRight = getWidth() - getPaddingRight();
final int parentBottom = getHeight() - getPaddingBottom();
final int childLeft = child.getLeft() + rect.left;
final int childTop = child.getTop() + rect.top;
final int childRight = childLeft + rect.right;
final int childBottom = childTop + rect.bottom;
final int offScreenLeft = Math.min(0, childLeft - parentLeft);
final int offScreenTop = Math.min(0, childTop - parentTop);
final int offScreenRight = Math.max(0, childRight - parentRight);
final int offScreenBottom = Math.max(0, childBottom - parentBottom);
// Favor the "start" layout direction over the end when bringing one
// side or the other
// of a large rect into view.
final int dx;
if (ViewCompat.getLayoutDirection(parent) == ViewCompat.LAYOUT_DIRECTION_RTL) {
dx = offScreenRight != 0 ? offScreenRight : offScreenLeft;
} else {
dx = offScreenLeft != 0 ? offScreenLeft : offScreenRight;
}
// Favor bringing the top into view over the bottom
int dy = offScreenTop != 0 ? offScreenTop : offScreenBottom;
if (dy > 0) {
//偏移量是40,焦点计算的高是360,比整体高少40,原因是焦点的view是item的子View,item的高度是400
dy += 40;
// dy += 400;
}
if (dy < 0) {
// dy -= 400;
}
if (dx != 0 || dy != 0) {
if (immediate) {
parent.scrollBy(dx, dy);
} else {
parent.smoothScrollBy(dx, dy);
}
return true;
}
return false;
}
@Override
public int scrollHorizontallyBy(int dx, Recycler recycler, State state) {
return dx;
}
}
public
boolean requestChildRectangleOnScreen(RecyclerView parent,
View child, Rect rect, boolean immediate)函数是相当重要的,它基本就能够确定在布局中滚动或者滑动时候,子Item和parent之间的位置。仔细查看这个函数的父类源码我们可以知道,dy,dx的实际意义就是在滚动中下滑和左右滑动的距离。而这个值的确定会严重影响滑动的流畅程度(我一直在调试这两个值……)
public int scrollHorizontallyBy(int dx, Recycler recycler, State state)这个函数是滑动中的回调函数。见到的人肯定很多,不足为奇。
3、ItemAnimator
是滑动进行中的动画,听别人说很炫,但是自己貌似没有亲手去实现,知道有这么个东西而已吧。