Android 模仿QQ侧滑删除ListView功能示例

作者:qsky2012 时间:2023-10-27 21:03:43 

需求:

1、listView可以侧滑item,展示删除按钮,点击删除按钮,删除当前的item

2、在删除按钮展示时,点击隐藏删除按钮,不响应item的点击事件

3、在删除按钮隐藏时,点击item响应点击事件

根据以上需求在网络上查找响应的例子,也有仿QQ侧滑代码,但不能满足2和3的要求,因此修改了一把,代码如下,共大家拍砖

第一步:重写ListView


public class SwipeListView extends ListView {
 private final static String TAG = "SwipeListView";
 private int mScreenWidth;  // 屏幕宽度
 private int mDownX;      // 按下点的x值
 private int mDownY;      // 按下点的y值
 private int mDeleteBtnWidth;// 删除按钮的宽度
 private boolean isDeleteShown = false;  // 删除按钮是否正在显示
 private boolean isOnClick = false;
 private ViewGroup mPointChild;  // 当前处理的item
 private LinearLayout.LayoutParams mLayoutParams;  // 当前处理的item的LayoutParams
 public SwipeListView(Context context, AttributeSet attrs) {
   this(context, attrs, 0);
 }
 public SwipeListView(Context context, AttributeSet attrs, int defStyle) {
   super(context, attrs, defStyle);
   // 获取屏幕宽度
   WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
   DisplayMetrics dm = new DisplayMetrics();
   wm.getDefaultDisplay().getMetrics(dm);
   mScreenWidth = dm.widthPixels;
 }
 @Override
 public boolean onTouchEvent(MotionEvent ev) {
   switch (ev.getAction()) {
     case MotionEvent.ACTION_DOWN:
       performActionDown(ev);
       break;
     case MotionEvent.ACTION_MOVE:
       return performActionMove(ev);
     case MotionEvent.ACTION_UP:
       return performActionUp(ev);
//        break;
   }
   return super.onTouchEvent(ev);
 }
 // 处理action_down事件
 private void performActionDown(MotionEvent ev) {
//    Log.e(TAG,"performActionDown===="+isDeleteShown);
   if (isDeleteShown) {
     turnToNormal();
   }
   isOnClick = true;
   mDownX = (int) ev.getX();
   mDownY = (int) ev.getY();
   // 获取当前点的item
   int downPosition = pointToPosition(mDownX, mDownY);
   int firstPosition= getFirstVisiblePosition();
   Log.e(TAG,"performActionDown====downPosition:"+downPosition+"==firstPosition"+firstPosition);
   if(downPosition < 0) return;
   mPointChild = (ViewGroup) getChildAt(downPosition-firstPosition);
   // 获取删除按钮的宽度
   mDeleteBtnWidth = mPointChild.getChildAt(1).getLayoutParams().width;
   mLayoutParams = (LinearLayout.LayoutParams) mPointChild.getChildAt(0)
       .getLayoutParams();
   // 为什么要重新设置layout_width 等于屏幕宽度
   // 因为match_parent时,不管你怎么滑,都不会显示删除按钮
   // why? 因为match_parent时,ViewGroup就不去布局剩下的view
   mLayoutParams.width = mScreenWidth;
   mPointChild.getChildAt(0).setLayoutParams(mLayoutParams);
 }
 // 处理action_move事件
 private boolean performActionMove(MotionEvent ev) {
//    Log.e(TAG, "performActionMove====" + isDeleteShown);
   int nowX = (int) ev.getX();
   int nowY = (int) ev.getY();
   isOnClick = false;
   if (Math.abs(nowX - mDownX) > Math.abs(nowY - mDownY)) {
     // 如果向左滑动
     if (nowX < mDownX) {
       // 计算要偏移的距离
       int scroll = (nowX - mDownX) / 2;
       // 如果大于了删除按钮的宽度, 则最大为删除按钮的宽度
       if (-scroll >= mDeleteBtnWidth) {
         scroll = -mDeleteBtnWidth;
       }
       // 重新设置leftMargin
       mLayoutParams.leftMargin = scroll;
       mPointChild.getChildAt(0).setLayoutParams(mLayoutParams);
     }
     return true;
   }
   return super.onTouchEvent(ev);
 }
 // 处理action_up事件
 private boolean performActionUp(MotionEvent ev) {
   boolean falg = false;
   if(isOnClick && !isDeleteShown)
   {
     falg = true;
   }
   // 偏移量大于button的一半,则显示button
   // 否则恢复默认
   if (-mLayoutParams.leftMargin >= mDeleteBtnWidth / 2) {
     mLayoutParams.leftMargin = -mDeleteBtnWidth;
     isDeleteShown = true;
   } else {
     turnToNormal();
     isDeleteShown = false;
   }
   mPointChild.getChildAt(0).setLayoutParams(mLayoutParams);
//    Log.e(TAG, "performActionUp====" + isDeleteShown);
   if(falg)
   {
     return super.onTouchEvent(ev);
   }
   return true;
 }
 /**
  * 变为正常状态
  */
 public void turnToNormal() {
   mLayoutParams.leftMargin = 0;
   mPointChild.getChildAt(0).setLayoutParams(mLayoutParams);
 }
 /**
  * 当前是否可点击
  *
  * @return 是否可点击
  */
 public boolean canClick() {
   return !isDeleteShown;
 }
}

第二步:适配器


class SwipeListAdapter extends BaseAdapter {
 @Override
 public int getCount() {
   return mData.size();
 }
 @Override
 public Object getItem(int position) {
   return mData.get(position);
 }
 @Override
 public long getItemId(int position) {
   return position;
 }
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
   ViewHolder holder = null;
   if (null == convertView) {
     holder = new ViewHolder();
     convertView = View.inflate(TestListViewActivity.this, R.layout.item_swipe_list, null);
     holder.tv = (LinearLayout) convertView.findViewById(R.id.tv);
     holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
     holder.delete = (TextView) convertView.findViewById(R.id.delete);
     convertView.setTag(holder);
   }
   else {
     holder = (ViewHolder) convertView.getTag();
   }
   holder.tvName.setText(mData.get(position));
   final int pos = position;
   holder.delete.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
       mData.remove(pos);
       notifyDataSetChanged();
       mListView.turnToNormal();
     }
   });
   return convertView;
 }
}
static class ViewHolder {
 LinearLayout tv;
 TextView tvName;
 TextView delete;
}

第三步:写一个TestListViewActivity


private SwipeListView mListView;
 private ArrayList<String> mData = new ArrayList<String>() {
   {
     for (int i = 0; i < 20; i++) {
       add("hello world, hello android " + i);
     }
   }
 };
 @Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_test_list_view);
   Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
   setSupportActionBar(toolbar);
   FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
   fab.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View view) {
       Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
           .setAction("Action", null).show();
     }
   });
   mListView = (SwipeListView) findViewById(R.id.list);
   mListView.setAdapter(new SwipeListAdapter());
//    mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
//      @Override
//      public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
//        Toast.makeText(TestListViewActivity.this, mData.get(position) + "被点击了",
//            Toast.LENGTH_SHORT).show();
//        return false;
//      }
//    });
   mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
       Log.e("SwipeListView", "setOnItemClickListener====" + mListView.canClick());
//        Toast.makeText(TestListViewActivity.this, mData.get(position) + "被点击了",
//            Toast.LENGTH_SHORT).show();
     }
   });
 }

第四步:布局文件


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
 android:layout_height="match_parent"
 app:layout_behavior="@string/appbar_scrolling_view_behavior"
 tools:showIn="@layout/activity_test_list_view"
 tools:context="com.kimascend.ledappd1.activity.TestListViewActivity">
 <com.kimascend.ledappd1.view.SwipeListView
   android:id="@+id/list"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:cacheColorHint="@android:color/transparent"
   android:listSelector="@android:color/transparent"
   android:divider="@android:color/darker_gray"
   android:dividerHeight="2dp">
 </com.kimascend.ledappd1.view.SwipeListView>
</RelativeLayout>

第五步:item的布局文件


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="horizontal">
 <LinearLayout
   android:id="@+id/tv"
   android:orientation="horizontal"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@android:color/white"
   android:paddingBottom="20dp"
   android:paddingLeft="10dp"
   android:paddingTop="20dp">
   <ImageView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:background="@drawable/group_name_rgb"
     android:id="@+id/imageView8" />
   <TextView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:textAppearance="?android:attr/textAppearanceLarge"
     android:text="Large Text"
     android:layout_gravity="center_vertical"
     android:id="@+id/tv_name" />
 </LinearLayout>
 <TextView
   android:id="@+id/delete"
   android:layout_width="80dp"
   android:layout_height="match_parent"
   android:background="#FFFF0000"
   android:gravity="center"
   android:paddingLeft="20dp"
   android:paddingRight="20dp"
   android:text="删除"
   android:textColor="@android:color/white" />
</LinearLayout>

重点注意:


int downPosition = pointToPosition(mDownX, mDownY);

downPosition 在使用过程中得到-1,导致后面方法调用异常!

以上所述是小编给大家介绍的Android 模仿QQ侧滑删除ListView功能示例网站的支持!

来源:http://blog.csdn.net/qsky001/article/details/60871823

标签:android,qq,侧滑删除,listview
0
投稿

猜你喜欢

  • c# 通过wbemtest和WMI Code Cretor更加高效的访问WMI

    2022-11-17 16:30:16
  • Flutter 使用fluro的转场动画进行页面切换

    2023-06-17 11:49:26
  • java常量字符串过长报错的解决办法以及原因分析

    2023-10-18 10:15:25
  • Java8 HashMap遍历方式性能探讨

    2022-01-31 08:48:11
  • Unity实现ScrollView滑动吸附功能

    2022-07-07 00:38:14
  • C#针对xml基本操作及保存配置文件应用实例

    2022-11-24 05:51:17
  • Android实现通话自动录音

    2021-08-29 20:33:35
  • 深入理解Java 类加载全过程

    2023-10-20 12:34:23
  • Android 显示刷新频率的实现代码

    2023-09-18 07:01:34
  • C#设计模式之Builder生成器模式解决带老婆配置电脑问题实例

    2021-07-09 03:22:59
  • Java Struts图片上传至指定文件夹并显示图片功能

    2023-03-15 10:48:51
  • java开发之读写txt文件操作的实现

    2023-11-17 06:00:23
  • Java常用函数式接口总结

    2022-02-02 00:02:50
  • Android Activity通用悬浮可拖拽View封装的思路详解

    2023-08-08 15:31:48
  • 利用Lambda表达式创建新线程案例

    2023-08-26 23:16:00
  • JAVA 根据设置的概率生成随机数的方法

    2023-07-15 00:13:37
  • 剖析SpringCloud Feign中所隐藏的坑

    2023-11-19 05:32:03
  • Java字母加数字组合比较大小

    2023-02-27 15:27:52
  • SpringBoot集成redis实现分布式锁的示例代码

    2022-08-24 19:21:56
  • 了解Java线程池执行原理

    2022-10-12 13:00:23
  • asp之家 软件编程 m.aspxhome.com