Android的RecyclerView的使用
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
是滑动进行中的动画,听别人说很炫,但是自己貌似没有亲手去实现,知道有这么个东西而已吧。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。