当前位置:   article > 正文

Android学习笔记--RecycleView用法_android recycleview findchildviewunder

android recycleview findchildviewunder

1.什么是RecyclerView

RecyclerView是Android 5.0 materials design中的组件之一。通过名字我们就能看出一点端倪,没错,它主要的特点就是复用。我们知道,Listview中的Adapter中可以实现ViewHolder的复用。RecyclerView提供了一个耦合度更低的方式来复用ViewHolder,并且可以轻松的实现ListView、GridView以及瀑布流的效果。

2.RecycleView怎么引用

  Android Studio
  1. dependencies {
  2. compile 'com.android.support:recyclerview-v7:21.0.0'
  3. }
先介绍三个东西:

Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定

ViewHolder:用来保存视图引用的类.(这个与ListView可选不同,必须使用)

LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似

3.基本用法

  1. mRecyclerView = findView(R.id.id_recyclerview);
  2. mRecyclerView.setLayoutManager(layout);//设置布局管理器
  3. mRecyclerView.setAdapter(adapter)//设置adapter
  4. // 设置item动画
  5. mRecyclerView.setItemAnimator(new DefaultItemAnimator());//系统提供的默认动画


最简单的用法(效果ListView一样)

主布局:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5. <android.support.v7.widget.RecyclerView
  6. android:id="@+id/id_recyclerview"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent" />
  9. </RelativeLayout>
Item的布局:

  1. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:background="#fff"
  4. android:layout_height="wrap_content" >
  5. <TextView
  6. android:id="@+id/id_tv_item"
  7. android:layout_width="match_parent"
  8. android:layout_height="50dp"
  9. android:gravity="center"
  10. android:text="" />
  11. </LinearLayout>
MainActiviyu:

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import android.os.Bundle;
  4. import android.support.v7.app.ActionBarActivity;
  5. import android.support.v7.widget.LinearLayoutManager;
  6. import android.support.v7.widget.RecyclerView;
  7. import android.support.v7.widget.RecyclerView.ViewHolder;
  8. import android.view.LayoutInflater;
  9. import android.view.View;
  10. import android.view.ViewGroup;
  11. import android.widget.TextView;
  12. public class MainActivity extends ActionBarActivity
  13. {
  14. private RecyclerView mRecyclerView;
  15. private List<String> mDatas;
  16. private HomeAdapter mAdapter;
  17. @Override
  18. protected void onCreate(Bundle savedInstanceState)
  19. {
  20. super.onCreate(savedInstanceState);
  21. setContentView(R.layout.activity_single_recyclerview);
  22. initData();
  23. mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
  24. mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
  25. mRecyclerView.setAdapter(mAdapter = new HomeAdapter());
  26. }
  27. protected void initData()
  28. {
  29. mDatas = new ArrayList<String>();
  30. for (int i = 0; i < 30; i++)
  31. {
  32. mDatas.add("" + i);
  33. }
  34. }
  35. class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder>
  36. {
  37. @Override
  38. public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
  39. {
  40. MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
  41. HomeActivity.this).inflate(R.layout.item_home, parent,
  42. false));
  43. return holder;
  44. }
  45. @Override
  46. public void onBindViewHolder(MyViewHolder holder, int position)
  47. {
  48. holder.tv.setText(mDatas.get(position));
  49. }
  50. @Override
  51. public int getItemCount()
  52. {
  53. return mDatas.size();
  54. }
  55. class MyViewHolder extends ViewHolder
  56. {
  57. TextView tv;
  58. public MyViewHolder(View view)
  59. {
  60. super(view);
  61. tv = (TextView) view.findViewById(R.id.id_num);
  62. }
  63. }
  64. }
  65. }

4.LayoutManager:

横向布局
如果想要一个横向的List只要设置LinearLayoutManager如下就行,注意要声明mLayoutManager的类型是LinearLayoutManager而不是父类LayoutManager:

mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
Grid布局
如果想要一个Grid布局的列表,只要声明LayoutManager为GridLayoutManager即可:
  1. mLayoutManager = new GridLayoutManager(context,columNum);
  2. mRecyclerView.setLayoutManager(mLayoutManager);
注意,在Grid布局中也可以设置列表的Orientation属性,来实现横向和纵向的Grid布局。

瀑布流布局
瀑布流就使用StaggeredGridLayoutManager吧,具体方法与上面类似,就不介绍了。

你还可以增加添加和删除数据的方法:

  1. public void addData(int position) {
  2. mDatas.add(position, "add add add");
  3. notifyItemInserted(position);
  4. }
  5. public void removeData(int position) {
  6. mDatas.remove(position);
  7. notifyItemRemoved(position);
  8. }


5.点击事件

RecyclerView的api发现虽然没有提供onItemClickListener但是提供了addOnItemTouchListener方法这里我有两种实现点击的方法。第一种是通过mRecyclerView.addOnItemTouchListener去监听然后去判断手势,第二种是通过adapter中自己去提供回调。

第一种:

1.定义一个类OnRecyclerItemClickListener实现OnItemTouchListener,我们需要实现其3个方法:

  1. @Override
  2. public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
  3. }
  4. @Override
  5. public void onTouchEvent(RecyclerView rv, MotionEvent e) {
  6. }
  7. @Override
  8. public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
  9. }

其中第三个方法是处理触摸事件冲突的,跟我们没关系不用管它,前两个方法是不是很熟悉呢,这不就是View的事件分发机制里面的事件拦截和事件处理的两个方法吗,参数里为我们提供了触摸事件的数据MotionEvent,我们要做的就是去解析坐标点和触摸规律来识别触摸手势,然后获取触摸的是哪一个item,再执行我们的回调。

定义一个ItemTouchHelperGestureListener 继承自SimpleOnGestureListener ,实现onSingleTapUp方法:

  1. private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
  2. @Override
  3. public boolean onSingleTapUp(MotionEvent e) {
  4. }
  5. }
获取到了RecyclerView的点击事件和触摸事件数据MotionEvent ,那么我们怎么知道点击的是哪一个item呢?RecyclerView已经为我们提供了这样的方法:findChildViewUnder(),我们可以通过这个方法获得点击的item,同时我们调用RecyclerView的另一个方法getChildViewHolder(),可以获得该item的ViewHolder,最后再回调我们定义的虚方法onItemClick()就ok了,这样我们就可以在外部实现该方法来获得item的点击事件了:

  1. @Override
  2. public boolean onSingleTapUp(MotionEvent e) {
  3. View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
  4. if (child!=null) {
  5. RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
  6. onItemClick(vh);
  7. }
  8. return true;
  9. }
完整代码如下:

  1. public class MainActivity extends AppCompatActivity {
  2. private RecyclerView mRecyclerView;
  3. private List<String> mData;
  4. private myAdapter mAdapter;
  5. @Override
  6. protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. initData();
  10. mRecyclerView= (RecyclerView) findViewById(R.id.recycleView);
  11. mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
  12. //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
  13. mRecyclerView.setHasFixedSize(true);
  14. mRecyclerView.setAdapter(mAdapter=new myAdapter());
  15. mRecyclerView.addOnItemTouchListener(new onRecycleItemClickListener(mRecyclerView) {
  16. @Override
  17. public void onItemClick(RecyclerView.ViewHolder vh) {
  18. //具体点击事件
  19. Toast.makeText(MainActivity.this, "hah",Toast.LENGTH_SHORT).show();
  20. }
  21. });
  22. }
  23. private void initData(){
  24. mData=new ArrayList<String>();
  25. for (int i = 'A'; i < 'Z'; i++) {
  26. mData.add(""+(char)i);
  27. }
  28. }
  29. public abstract class onRecycleItemClickListener implements RecyclerView.OnItemTouchListener{
  30. private GestureDetector mGestureDetector;
  31. private RecyclerView recycleView;
  32. @Override
  33. public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
  34. mGestureDetector.onTouchEvent(e);
  35. return false;
  36. }
  37. //处理触摸冲突的方法
  38. @Override
  39. public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
  40. }
  41. @Override
  42. public void onTouchEvent(RecyclerView rv, MotionEvent e) {
  43. mGestureDetector.onTouchEvent(e);
  44. }
  45. public onRecycleItemClickListener(RecyclerView recycleView) {
  46. this.recycleView = recycleView;
  47. mGestureDetector=new GestureDetector(MainActivity.this,new ItemTouchHelperGestureListener());
  48. }
  49. private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener{
  50. @Override
  51. public boolean onSingleTapUp(MotionEvent e) {
  52. View view=recycleView.findChildViewUnder(e.getX(),e.getY());
  53. if (view!=null){
  54. RecyclerView.ViewHolder holder=recycleView.getChildViewHolder(view);
  55. onItemClick(holder);
  56. }
  57. return true;
  58. }
  59. //长点击事件,本例不需要不处理
  60. //@Override
  61. //public void onLongPress(MotionEvent e) {
  62. // View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
  63. // if (child!=null) {
  64. // RecyclerView.myHolder vh = recyclerView.getChildViewHolder(child);
  65. // onItemLongClick(vh);
  66. // }
  67. //}
  68. }
  69. public abstract void onItemClick(RecyclerView.ViewHolder vh);
  70. //public abstract void onItemLongClick(RecyclerView.myHolder vh);
  71. }
  72. public class myAdapter extends RecyclerView.Adapter<myAdapter.myHolder>{
  73. @Override
  74. public myHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  75. myHolder holder=new myHolder(LayoutInflater.from(MainActivity.this).inflate(R.layout.item,parent,
  76. false));
  77. return holder;
  78. }
  79. @Override
  80. public void onBindViewHolder(myHolder holder, int position) {
  81. holder.item_tv.setText(mData.get(position));
  82. }
  83. //添加item
  84. public void addItem(int position){
  85. mData.add(position,"insert one");
  86. notifyItemInserted(position);
  87. }
  88. //删除item
  89. public void removeData(int position){
  90. mData.remove(position);
  91. notifyItemRemoved(position);
  92. }
  93. @Override
  94. public int getItemCount() {
  95. return mData.size();
  96. }
  97. public class myHolder extends RecyclerView.ViewHolder{
  98. TextView item_tv;
  99. public myHolder(View itemView) {
  100. super(itemView);
  101. item_tv= (TextView) itemView.findViewById(R.id.item_tv);
  102. }
  103. }
  104. }
  105. }
第二种方法:

这个代码比较简单,先在RecyclerView.Adapter中添加回调接口:

  1. public interface OnItemClickLitener
  2. {
  3. void onItemClick(View view, int position);
  4. void onItemLongClick(View view , int position);
  5. }
  6. private OnItemClickLitener mOnItemClickLitener;
  7. public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener)
  8. {
  9. this.mOnItemClickLitener = mOnItemClickLitener;
  10. }
  11. @Override
  12. public void onBindViewHolder(final MyViewHolder holder, final int position)
  13. {
  14. holder.tv.setText(mDatas.get(position));
  15. // 如果设置了回调,则设置点击事件
  16. if (mOnItemClickLitener != null)
  17. {
  18. holder.itemView.setOnClickListener(new OnClickListener()
  19. {
  20. @Override
  21. public void onClick(View v)
  22. {
  23. int pos = holder.getLayoutPosition();
  24. mOnItemClickLitener.onItemClick(holder.itemView, pos);
  25. }
  26. });
  27. holder.itemView.setOnLongClickListener(new OnLongClickListener()
  28. {
  29. @Override
  30. public boolean onLongClick(View v)
  31. {
  32. int pos = holder.getLayoutPosition();
  33. mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
  34. return false;
  35. }
  36. });
  37. }
  38. }
然后再Activity中设置监听:

  1. mAdapter.setOnItemClickLitener(new OnItemClickLitener()
  2. {
  3. @Override
  4. public void onItemClick(View view, int position)
  5. {
  6. Toast.makeText(HomeActivity.this, position + " click",
  7. Toast.LENGTH_SHORT).show();
  8. }
  9. @Override
  10. public void onItemLongClick(View view, int position)
  11. {
  12. Toast.makeText(HomeActivity.this, position + " long click",
  13. Toast.LENGTH_SHORT).show();
  14. mAdapter.removeData(position);
  15. }
  16. });
就OK了。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/286647
推荐阅读
相关标签
  

闽ICP备14008679号