应用RecyclerView实现Gallery相本效果——注意引入recyclerview-v7的版本
整理总结自鸿洋的博客:http://blog.****.net/lmj623565791/article/details/38173061/
一、初次使用RecyclerView实现”适配器“的功能
1、MainActivity.java
public class MainActivity extends Activity { private RecyclerView mRecyclerView; private GalleryAdapter mAdapter; private List<Integer> mDatas; @Override protected 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 ArrayList<Integer>(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f, R.mipmap.g, R.mipmap.h, R.mipmap.l)); } }
2、activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/id_recyclerview_horizontal" android:layout_width="match_parent" android:layout_height="120dp" android:layout_centerVertical="true" android:background="#FF0000" android:scrollbars="none" /> </RelativeLayout>
3、activity_index_gallery_item.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="120dp" android:layout_height="120dp" android:background="@drawable/item_bg02"> <ImageView android:id="@+id/id_index_gallery_item_image" android:layout_width="80dp" android:layout_height="80dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_margin="5dp" android:scaleType="centerCrop" /> <TextView android:id="@+id/id_index_gallery_item_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/id_index_gallery_item_image" android:layout_centerHorizontal="true" android:layout_marginBottom="5dp" android:layout_marginTop="5dp" android:text="some info" android:textColor="#ff0000" android:textSize="12dp" /> </RelativeLayout>
4、GalleryAdapter.java
/** * Created by jiatao on 2016/06/14 18:26 * Description: 应用RecyclerView的适配器 */ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.ViewHolder> { private LayoutInflater mInflater; private List<Integer> mDatas; public GalleryAdapter(Context context, List<Integer> datats) { mInflater = LayoutInflater.from(context); mDatas = datats; } /** * 创建内部静态类,必须继承RecyclerView.ViewHolder。承上启下。 * 上:RecyclerView.Adapter<GalleryAdapter.ViewHolder> * 下:ViewHolder viewHolder = new ViewHolder(view); * 详细说明: * 我们创建的ViewHolder必须继承RecyclerView.ViewHolder,这个RecyclerView.ViewHolder在构造时必须传入一个View, * 这个View相当于我们ListView getView中的convertView (即:把我们需要inflate的item布局传入) */ public static class ViewHolder extends RecyclerView.ViewHolder { ImageView mImg; TextView mTxt; public ViewHolder(View view) { super(view); } } /** * 获取总条目数,同BaseAdapter */ @Override public int getItemCount() { return mDatas.size(); } /** * 创建ViewHolder */ @Override public 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; } /** * 将数据绑定到ViewHolder */ @Override public void onBindViewHolder(final ViewHolder viewHolder, final int i) { viewHolder.mImg.setImageResource(mDatas.get(i)); } }
二、为RecyclerView添加OnItemClickListener回调
1、MainActivity.java
public class MainActivity extends Activity { private RecyclerView mRecyclerView; private GalleryAdapter mAdapter; private List<Integer> mDatas; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initDatas();//获得数据 initView(); //初始化视图 } private void initDatas() { mDatas = new ArrayList<Integer>(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f, R.mipmap.g, R.mipmap.h, R.mipmap.l)); } private void initView() { //得到控件 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); //添加点击监听 mAdapter.setmOnItemClickListener(new GalleryAdapter.OnItemClickListener() { @Override public void itemClick(View view, int position) { Toast.makeText(MainActivity.this, position+"", Toast.LENGTH_SHORT).show(); } }); mRecyclerView.setAdapter(mAdapter); } }
2、activity_main.xml
同上
3、activity_index_gallery_item.xml
同上
4、GalleryAdapter.java
/** * Created by jiatao on 2016/06/15 7:26 * Description: 应用RecyclerView的适配器 * 添加OnItemClickListener回调接口,实现对条目的点击事件 */ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.ViewHolder> { /**********************添加OnItemClickListener回调接口↓↓******************************/ public interface OnItemClickListener{ void itemClick(View view, int position); } private OnItemClickListener mOnItemClickListener; public void setmOnItemClickListener(OnItemClickListener listener){ this.mOnItemClickListener = listener; } /**********************添加OnItemClickListener回调接口↑↑******************************/ private LayoutInflater mInflater; private List<Integer> mDatas; public GalleryAdapter(Context context, List<Integer> datats) { mInflater = LayoutInflater.from(context); mDatas = datats; } /** * 创建内部静态类,必须继承RecyclerView.ViewHolder。承上启下。 * 上:RecyclerView.Adapter<GalleryAdapter.ViewHolder> * 下:ViewHolder viewHolder = new ViewHolder(view); * 详细说明: * 我们创建的ViewHolder必须继承RecyclerView.ViewHolder,这个RecyclerView.ViewHolder在构造时必须传入一个View, * 这个View相当于我们ListView getView中的convertView (即:把我们需要inflate的item布局传入) */ public static class ViewHolder extends RecyclerView.ViewHolder { ImageView mImg; TextView mTxt; public ViewHolder(View view) { super(view); } } /** * 获取总条目数,同BaseAdapter */ @Override public int getItemCount() { return mDatas.size(); } /** * 创建ViewHolder */ @Override public 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; } /** * 将数据绑定到ViewHolder */ @Override public void onBindViewHolder(final ViewHolder viewHolder, final int position) { viewHolder.mImg.setImageResource(mDatas.get(position)); //如果设置了点击事件的回调 if(mOnItemClickListener != null){ viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mOnItemClickListener.itemClick(viewHolder.itemView, position); } }); } } }
三、自定义RecyclerView实现滚动时内容联动
1、MainActivity.java
public class MainActivity extends Activity { private GalleryAdapter mAdapter; private ImageView id_content; private CustomRecyclerView mCustomRecyclerView; private List<Integer> mDatas; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initDatas();//获得数据 initView();//初始化视图 } private void initDatas() { mDatas = new ArrayList<Integer>(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f, R.mipmap.g, R.mipmap.h, R.mipmap.l)); } private void initView() { //得到控件 id_content = (ImageView) findViewById(R.id.id_content); mCustomRecyclerView = (CustomRecyclerView) findViewById(R.id.id_recyclerview_horizontal); //设置布局管理器 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); mCustomRecyclerView.setLayoutManager(linearLayoutManager); //设置适配器 mAdapter = new GalleryAdapter(this, mDatas); //添加点击监听 mAdapter.setOnItemClickListener(new GalleryAdapter.OnItemClickListener() { @Override public void itemClick(View v, int position) { Toast.makeText(MainActivity.this, position+"", Toast.LENGTH_SHORT).show(); } }); mCustomRecyclerView.setAdapter(mAdapter); //添加滑动监听 mCustomRecyclerView.setOnItemScrollChangeListener(new CustomRecyclerView.OnItemScrollChangeListener() { @Override public void onChange(View view, int position) { id_content.setImageResource(mDatas.get(position)); } }); } }
2、activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1"> <ImageView android:id="@+id/id_content" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:layout_margin="10dp" android:scaleType="centerCrop" /> </FrameLayout> <com.cctvjiatao.recyclerviewgallery.view.CustomRecyclerView android:id="@+id/id_recyclerview_horizontal" android:layout_width="match_parent" android:layout_height="120dp" android:layout_gravity="bottom" android:background="#FF0000" android:scrollbars="none" /> </LinearLayout>
3、activity_index_gallery_item.xml
同上
4、GalleryAdapter.java
同上
5、CustomRecyclerView.java
/** * Created by jiatao on 2016/06/15 09:55 * Description: 自定义RecyclerView */ public class CustomRecyclerView extends RecyclerView { private View mCurrentView; public CustomRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); } /**********************添加OnItemScrollChangeListener回调接口相关↓↓******************************/ //定义一个滚动时回调的接口,然后在onTouchEvent中,监听ACTION_MOVE,用户手指滑动时,不断地把当前第一个View回调回去 public interface OnItemScrollChangeListener { void onChange(View view, int position); } private OnItemScrollChangeListener mItemScrollChangeListener; public void setOnItemScrollChangeListener(OnItemScrollChangeListener listener) { this.mItemScrollChangeListener = listener; } /**********************添加OnItemScrollChangeListener回调接口相关↑↑******************************/ @Override protected 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, getChildLayoutPosition(mCurrentView));//Android 6.0中View.getChildPosition()过时,更新为View.getChildLayoutPosition } } @Override public boolean onTouchEvent(MotionEvent e) { if (e.getAction() == MotionEvent.ACTION_MOVE) { mCurrentView = getChildAt(0); // Log.e("TAG", getChildLayoutPosition(getChildAt(0)) + ""); if (mItemScrollChangeListener != null) { mItemScrollChangeListener.onChange(mCurrentView, getChildLayoutPosition(mCurrentView));//Android 6.0中View.getChildPosition()过时,更新为View.getChildLayoutPosition } } return super.onTouchEvent(e); } }
四、优化与打造真正的Gallery效果效果—— 所用jar包是 recyclerview-v7:23.3.0
1、MainActivity.java
public class MainActivity extends Activity { private GalleryAdapter mAdapter; private ImageView id_content; private CustomRecyclerView mCustomRecyclerView; private List<Integer> mDatas; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initDatas();//获得数据 initView();//初始化视图 } private void initDatas() { mDatas = new ArrayList<Integer>(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f, R.mipmap.g, R.mipmap.h, R.mipmap.l)); } private void initView() { //得到控件 id_content = (ImageView) findViewById(R.id.id_content); mCustomRecyclerView = (CustomRecyclerView) findViewById(R.id.id_recyclerview_horizontal); //设置布局管理器 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); mCustomRecyclerView.setLayoutManager(linearLayoutManager); //设置适配器 mAdapter = new GalleryAdapter(this, mDatas); //添加点击监听 mAdapter.setOnItemClickListener(new GalleryAdapter.OnItemClickListener() { @Override public void itemClick(View v, int position) { // Toast.makeText(MainActivity.this, position+"", Toast.LENGTH_SHORT).show(); id_content.setImageResource(mDatas.get(position)); } }); mCustomRecyclerView.setAdapter(mAdapter); //添加滑动监听 mCustomRecyclerView.setOnItemScrollChangeListener(new CustomRecyclerView.OnItemScrollChangeListener() { @Override public void onChange(View view, int position) { id_content.setImageResource(mDatas.get(position)); } }); } }
2、activity_main.xml
同上
3、activity_index_gallery_item.xml
同上
4、GalleryAdapter.java
同上
5、CustomRecyclerView.java
/** * Created by jiatao on 2016/06/15 09:55 * Description: 自定义RecyclerView,使用 recyclerview-v7-21.0.3 即以上的版本 * 放弃重写onTouchEvent方法,而是让这个类实现RecyclerView.OnScrollListener接口,然后设置监听,在onScrolled里面进行判断。 * 至于优化:使用了一个成员变化存储当前第一个View,只有第一个View发生变化时才回调 */ public class CustomRecyclerView extends RecyclerView { /**********************添加OnItemScrollChangeListener回调接口相关↓↓******************************/ public interface OnItemScrollChangeListener { void onChange(View view, int position); } private OnItemScrollChangeListener mItemScrollChangeListener; public void setOnItemScrollChangeListener(OnItemScrollChangeListener listener) { this.mItemScrollChangeListener = listener; } /**********************添加OnItemScrollChangeListener回调接口相关↑↑******************************/ private View mCurrentView; public CustomRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); this.addOnScrollListener(new MyScrollListener());//从 recyclerview-v7-21.0.3 开始 setOnScrollListener()过时,更新为 addOnScrollListener() } @Override protected 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, getChildLayoutPosition(mCurrentView));//从 recyclerview-v7-21.0.3 开始 getChildPosition()过时,更新为 getChildLayoutPosition } } /**********************添加RecyclerView.OnScrollListener监听相关↓↓******************************/ // 从 recyclerview-v7-21.0.3 开始,RecyclerView.OnScrollListener 已不是接口,而是抽象类了,所以要用如下写法了 // recyclerview-v7-21.0.3 之前的版本可以使用 public class CustomRecyclerView extends RecyclerView implements RecyclerView.OnScrollListener{……}的写法 private class MyScrollListener extends RecyclerView.OnScrollListener { public MyScrollListener() { super(); } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); View newView = getChildAt(0); if(mItemScrollChangeListener != null){ if(newView != null && newView != mCurrentView){ mCurrentView = newView; mItemScrollChangeListener.onChange(mCurrentView, getChildLayoutPosition(mCurrentView)); } } } } /**********************添加RecyclerView.OnScrollListener回调接口相关↑↑******************************/ }
五、优化与打造真正的Gallery效果效果—— 所用jar包是 recyclerview-v7:21.0.3
1、MainActivity.java
同上
2、activity_main.xml
同上
3、activity_index_gallery_item.xml
同上
4、GalleryAdapter.java
同上
5、CustomRecyclerView.java
/** * Created by jiatao on 2016/06/15 09:55 * Description: 自定义RecyclerView,使用 recyclerview-v7-21.0.3 及以下的版本 * 放弃重写onTouchEvent方法,而是让这个类实现RecyclerView.OnScrollListener接口,然后设置监听,在onScrolled里面进行判断。 * 至于优化:使用了一个成员变化存储当前第一个View,只有第一个View发生变化时才回调 */ public class CustomRecyclerView extends RecyclerView implements RecyclerView.OnScrollListener { /**********************添加OnItemScrollChangeListener回调接口相关↓↓******************************/ public interface OnItemScrollChangeListener { void onChange(View view, int position); } private OnItemScrollChangeListener mItemScrollChangeListener; public void setOnItemScrollChangeListener(OnItemScrollChangeListener listener) { this.mItemScrollChangeListener = listener; } /**********************添加OnItemScrollChangeListener回调接口相关↑↑******************************/ private View mCurrentView; public CustomRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); this.setOnScrollListener(this);//从 recyclerview-v7-21.0.3 开始 setOnScrollListener()过时,更新为 addOnScrollListener() } @Override protected 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));//从 recyclerview-v7-21.0.3 开始 getChildPosition()过时,更新为 getChildLayoutPosition } } /**********************添加RecyclerView.OnScrollListener监听相关↓↓******************************/ // recyclerview-v7-21.0.3 之前的版本可以使用这种 implements RecyclerView.OnScrollListener 的写法 // 从 recyclerview-v7-21.0.3 开始,RecyclerView.OnScrollListener 已不是接口,而是抽象类了,就不能用以下写法, @Override public void onScrollStateChanged(int newState) { } @Override public void onScrolled(int dx, int dy) { View newView = getChildAt(0); if(mItemScrollChangeListener != null){ if(newView != null && newView != mCurrentView){ mCurrentView = newView; mItemScrollChangeListener.onChange(mCurrentView, getChildPosition(mCurrentView)); } } } /**********************添加RecyclerView.OnScrollListener回调接口相关↑↑******************************/ }