西丽网站建设,网站的收录情况怎么查,网站地址结构,海外购物网站排名简介#xff1a; RecyclerView是support-v7包中的新组件#xff0c;是一个强大的滑动组件#xff0c;与经典的ListView相比#xff0c;同样拥有item回收复用的功能#xff0c;但是直接把viewholder的实现封装起来#xff0c;用户只要实现自己的viewholder就可以了#x… 简介 RecyclerView是support-v7包中的新组件是一个强大的滑动组件与经典的ListView相比同样拥有item回收复用的功能但是直接把viewholder的实现封装起来用户只要实现自己的viewholder就可以了该组件会自动帮你回收复用每一个item。 它不但变得更精简也变得更加容易使用而且更容易组合设计出自己需要的滑动布局。 要使用RecyclerView请参考 其实你也可以只下载一个jar包添加到自己的libs里就能使用它了Recycler.jar 使用它的理由 RecyclerView is a more advanced and flexible version of ListView. This widget is a container for large sets of views that can be recycled and scrolled very efficiently. Use the RecyclerView widget when you have lists with elements that change dynamically. 简单说它是ListView的进化为了当你需要动态展示一组数据的时候就会需要它。 当然如果只是动态展示数据listview也可以做到用它替代listview的原因有几个·简介中提到的它封装了viewholder的回收复用。·RecyclerView使用布局管理器管理子view的位置目前尚只提供了LinearLayoutManager也就是说你再不用拘泥于ListView的线性展示方式如果之后提供其他custom LayoutManager的支持你能够使用复杂的布局来展示一个动态组件。·自带了ItemAnimation可以设置加载和移除时的动画方便做出各种动态浏览的效果。Google官方最近新增加的RecyclerView据说是ListView的升级版本本篇博客首先介绍RecyclerView的用法然后经行一定的分析最后自定义一下RecyclerView实现我们需要的相册效果。
1、RecyclerView的基本用法
首先主Activity的布局文件RelativeLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent android.support.v7.widget.RecyclerViewandroid:idid/id_recyclerview_horizontalandroid:layout_widthmatch_parentandroid:layout_height120dpandroid:layout_centerVerticaltrueandroid:background#FF0000android:scrollbarsnone //RelativeLayoutItem的布局文件?xml version1.0 encodingutf-8?
RelativeLayout xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_width120dpandroid:layout_height120dpandroid:backgrounddrawable/item_bg02 ImageViewandroid:idid/id_index_gallery_item_imageandroid:layout_width80dpandroid:layout_height80dpandroid:layout_alignParentToptrueandroid:layout_centerHorizontaltrueandroid:layout_margin5dpandroid:scaleTypecenterCrop /TextViewandroid:idid/id_index_gallery_item_textandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_belowid/id_index_gallery_item_imageandroid:layout_centerHorizontaltrueandroid:layout_marginBottom5dpandroid:layout_marginTop5dpandroid:textColor#ff0000android:textsome infoandroid:textSize12dp //RelativeLayout数据适配器package com.example.zhy_horizontalscrollview03;import java.util.List;import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;public class GalleryAdapter extendsRecyclerView.AdapterGalleryAdapter.ViewHolder
{private LayoutInflater mInflater;private ListInteger mDatas;public GalleryAdapter(Context context, ListInteger datats){mInflater LayoutInflater.from(context);mDatas datats;}public static class ViewHolder extends RecyclerView.ViewHolder{public ViewHolder(View arg0){super(arg0);}ImageView mImg;TextView mTxt;}Overridepublic int getItemCount(){return mDatas.size();}/*** 创建ViewHolder*/Overridepublic ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i){View view mInflater.inflate(R.layout.activity_index_gallery_item,viewGroup, false);ViewHolder viewHolder new ViewHolder(view);viewHolder.mImg (ImageView) view.findViewById(R.id.id_index_gallery_item_image);return viewHolder;}/*** 设置值*/Overridepublic void onBindViewHolder(final ViewHolder viewHolder, final int i){viewHolder.mImg.setImageResource(mDatas.get(i));}}
可以看到数据适配器与BaseAdapter比较发生了相当大的变化主要有3个方法 getItemCount 这个不用说获取总的条目数 onCreateViewHolder 创建ViewHolder onBindViewHolder 将数据绑定至ViewHolder 可见RecyclerView对ViewHolder也进行了一定的封装但是如果你仔细观察你会发出一个疑问ListView里面有个getView返回View为Item的布局那么这个Item的样子在哪控制 其实是这样的我们创建的ViewHolder必须继承RecyclerView.ViewHolder这个RecyclerView.ViewHolder的构造时必须传入一个View这个View相当于我们ListView getView中的convertView 即我们需要inflate的item布局需要传入。 还有一点ListView中convertView是复用的在RecyclerView中是把ViewHolder作为缓存的单位了然后convertView作为ViewHolder的成员变量保持在ViewHolder中也就是说假设没有屏幕显示10个条目则会创建10个ViewHolder缓存起来每次复用的是ViewHolder所以他把getView这个方法变为了onCreateViewHolder。有兴趣的自己打印下Log测试下。 最后在Activity中使用 package com.example.zhy_horizontalscrollview03;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Window;public class MainActivity extends Activity
{private RecyclerView mRecyclerView;private GalleryAdapter mAdapter;private ListInteger mDatas;Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);initDatas();//得到控件mRecyclerView (RecyclerView) findViewById(R.id.id_recyclerview_horizontal);//设置布局管理器LinearLayoutManager linearLayoutManager new LinearLayoutManager(this);linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);mRecyclerView.setLayoutManager(linearLayoutManager);//设置适配器mAdapter new GalleryAdapter(this, mDatas);mRecyclerView.setAdapter(mAdapter);}private void initDatas(){mDatas new ArrayListInteger(Arrays.asList(R.drawable.a,R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e,R.drawable.f, R.drawable.g, R.drawable.h, R.drawable.l));}}使用起来也很方便唯一的区别就是要设置LayoutManager目前只有一个实现类就是LinearLayoutManager可以设置为水平或者垂直。 最后效果图 效果很不错这就是RecyclerView的基本用法了但是你会发现一个坑爹的地方竟然没有提供setOnItemClickListener这个回调要不要这么坑爹。。。
2、为RecyclerView添加OnItemClickListener回调 虽然它没有提供但是添加个OnItemClickListener对我们来说还不是小菜一碟~ 我决定在Adapter中添加这个回调接口 package com.example.zhy_horizontalscrollview03;import java.util.List;import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;public class GalleryAdapter extendsRecyclerView.AdapterGalleryAdapter.ViewHolder
{/*** ItemClick的回调接口* author zhy**/public interface OnItemClickLitener{void onItemClick(View view, int position);}private OnItemClickLitener mOnItemClickLitener;public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener){this.mOnItemClickLitener mOnItemClickLitener;}private LayoutInflater mInflater;private ListInteger mDatas;public GalleryAdapter(Context context, ListInteger datats){mInflater LayoutInflater.from(context);mDatas datats;}public static class ViewHolder extends RecyclerView.ViewHolder{public ViewHolder(View arg0){super(arg0);}ImageView mImg;TextView mTxt;}Overridepublic int getItemCount(){return mDatas.size();}Overridepublic ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i){View view mInflater.inflate(R.layout.activity_index_gallery_item,viewGroup, false);ViewHolder viewHolder new ViewHolder(view);viewHolder.mImg (ImageView) view.findViewById(R.id.id_index_gallery_item_image);return viewHolder;}Overridepublic void onBindViewHolder(final ViewHolder viewHolder, final int i){viewHolder.mImg.setImageResource(mDatas.get(i));//如果设置了回调则设置点击事件if (mOnItemClickLitener ! null){viewHolder.itemView.setOnClickListener(new OnClickListener(){Overridepublic void onClick(View v){mOnItemClickLitener.onItemClick(viewHolder.itemView, i);}});}}}很简单创建一个接口提供一个设置入口然后在onBindViewHolder中判断即可。 最后在主Activity中设置监听 mAdapter new GalleryAdapter(this, mDatas);mAdapter.setOnItemClickLitener(new OnItemClickLitener(){Overridepublic void onItemClick(View view, int position){Toast.makeText(MainActivity.this, position, Toast.LENGTH_SHORT).show();}});mRecyclerView.setAdapter(mAdapter);
好了这样就行了看效果图 效果还是不错的接下来我想改成相册效果即上面显示一张大图下面的RecyclerView做为图片切换的指示器。
3、自定义RecyclerView实现滚动时内容联动 首先修改下布局 布局文件
LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:orientationvertical FrameLayoutandroid:layout_widthfill_parentandroid:layout_height0dpandroid:layout_weight1 ImageViewandroid:idid/id_contentandroid:layout_widthfill_parentandroid:layout_heightfill_parentandroid:layout_gravitycenterandroid:layout_margin10dpandroid:scaleTypecenterCropandroid:srcdrawable/ic_launcher //FrameLayoutcom.example.zhy_horizontalscrollview03.MyRecyclerViewandroid:idid/id_recyclerview_horizontalandroid:layout_widthmatch_parentandroid:layout_height120dpandroid:layout_gravitybottomandroid:background#FF0000android:scrollbarsnone //LinearLayout添加一个显示大图的区域把RecyclerView改为自己定义的。 然后看我们自定义RecyclerView的代码
package com.example.zhy_horizontalscrollview03;import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;public class CopyOfMyRecyclerView extends RecyclerView
{public CopyOfMyRecyclerView(Context context, AttributeSet attrs){super(context, attrs);}private View mCurrentView;/*** 滚动时回调的接口*/private OnItemScrollChangeListener mItemScrollChangeListener;public void setOnItemScrollChangeListener(OnItemScrollChangeListener mItemScrollChangeListener){this.mItemScrollChangeListener mItemScrollChangeListener;}public interface OnItemScrollChangeListener{void onChange(View view, int position);}Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b){super.onLayout(changed, l, t, r, b);mCurrentView getChildAt(0);if (mItemScrollChangeListener ! null){mItemScrollChangeListener.onChange(mCurrentView,getChildPosition(mCurrentView));}}Overridepublic boolean onTouchEvent(MotionEvent e){if (e.getAction() MotionEvent.ACTION_MOVE){mCurrentView getChildAt(0);// Log.e(TAG, getChildPosition(getChildAt(0)) );if (mItemScrollChangeListener ! null){mItemScrollChangeListener.onChange(mCurrentView,getChildPosition(mCurrentView));}}return super.onTouchEvent(e);}}定义了一个滚动时回调的接口然后在onTouchEvent中监听ACTION_MOVE用户手指滑动时不断把当前第一个View回调回去~ 关于我咋知道getChildAt(0)和getChildPosition()可用起初我以为有getFirstVisibleItem这个方法后来发现么有但是发现了getRecycledViewPool()看名字我觉得是Viewholder那个缓存队列我想那么直接取这个队列的第一个不就是我要的View么后来没有成功。我就观察它内部的View最后发现第一个显示的始终是它第一个child至于getChildPosition这个看方法就看出来了。 现在的效果 和我之前那个例子的效果是一模一样的不过我还想做一些改变我觉得Gallery或者说相册的指示器下面可能1000来张图片我不仅喜欢手指在屏幕上滑动时图片会自动切换。我还希望如果我给指示器一个加速度即使手指离开下面还在滑动上面也会联动 。而且我还想做些优化直接在ACTION_MOVE中回调触发的频率太高了理论上一张图片只会触发一次~~
4、优化与打造真正的Gallery效果 既然希望手指离开还能联动那么不仅需要ACTION_MOVE需要监听还得监听一个加速度速度到达一定值然后继续移动~~再理一理需要这么麻烦么不是能滚动么那么应该有OnScrollListener啊小看一把果然有哈哈哈~天助我也下面看修改后的代码
package com.example.zhy_horizontalscrollview03;import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.util.AttributeSet;
import android.view.View;public class MyRecyclerView extends RecyclerView implements OnScrollListener
{/*** 记录当前第一个View*/private View mCurrentView;private OnItemScrollChangeListener mItemScrollChangeListener;public void setOnItemScrollChangeListener(OnItemScrollChangeListener mItemScrollChangeListener){this.mItemScrollChangeListener mItemScrollChangeListener;}public interface OnItemScrollChangeListener{void onChange(View view, int position);}public MyRecyclerView(Context context, AttributeSet attrs){super(context, attrs);// TODO Auto-generated constructor stubthis.setOnScrollListener(this);}Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b){super.onLayout(changed, l, t, r, b);mCurrentView getChildAt(0);if (mItemScrollChangeListener ! null){mItemScrollChangeListener.onChange(mCurrentView,getChildPosition(mCurrentView));}}Overridepublic void onScrollStateChanged(int arg0){}/*** * 滚动时判断当前第一个View是否发生变化发生才回调*/Overridepublic void onScrolled(int arg0, int arg1){View newView getChildAt(0);if (mItemScrollChangeListener ! null){if (newView ! null newView ! mCurrentView){mCurrentView newView ;mItemScrollChangeListener.onChange(mCurrentView,getChildPosition(mCurrentView));}}}}我放弃了重写onTouchEvent方法而是让这个类实现RecyclerView.OnScrollListener接口然后设置监听在onScrolled里面进行判断。 至于优化我使用了一个成员变化存储当前第一个View只有第一个View发生变化时才回调~~太完美了~ 看MainActivity: package com.example.zhy_horizontalscrollview03;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.Toast;import com.example.zhy_horizontalscrollview03.GalleryAdapter.OnItemClickLitener;
import com.example.zhy_horizontalscrollview03.MyRecyclerView.OnItemScrollChangeListener;public class MainActivity extends Activity
{private MyRecyclerView mRecyclerView;private GalleryAdapter mAdapter;private ListInteger mDatas;private ImageView mImg ; Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);mImg (ImageView) findViewById(R.id.id_content);mDatas new ArrayListInteger(Arrays.asList(R.drawable.a,R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e,R.drawable.f, R.drawable.g, R.drawable.h, R.drawable.l));mRecyclerView (MyRecyclerView) findViewById(R.id.id_recyclerview_horizontal);LinearLayoutManager linearLayoutManager new LinearLayoutManager(this);linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);mRecyclerView.setLayoutManager(linearLayoutManager);mAdapter new GalleryAdapter(this, mDatas);mRecyclerView.setAdapter(mAdapter);mRecyclerView.setOnItemScrollChangeListener(new OnItemScrollChangeListener(){Overridepublic void onChange(View view, int position){mImg.setImageResource(mDatas.get(position));};});mAdapter.setOnItemClickLitener(new OnItemClickLitener(){Overridepublic void onItemClick(View view, int position){
// Toast.makeText(getApplicationContext(), position , Toast.LENGTH_SHORT)
// .show();mImg.setImageResource(mDatas.get(position));}});}}代码没什么变化~多了个设置回调~ 效果图 可以看到不仅支持手机在上面移动时的变化如果我给了一个加速度下面持续滚动上面也会持续变化~~大赞~每张图片回调一次效率也相当不错。 好了看完这边博客相信大家对于RecyclerView有了一定的认识甚至对于如何改造一个控件也多了一份了解~~