经常在遇到问题第一时间都会在网上搜索解决的方法,因此看到很多前辈们的比较精辟的技术文章,学习了很多东西,现在将自己平时工作中开发的一些小功能坐下总结,也写出来,既方便自己理清思路记忆功能块实现思路,又能与大家一起交流分享技术。
第一次写文章,哪里有不对的希望大家多多包涵!

通过ListView + PopupWindow的方式实现了仿微信的侧滑删除、取消关注功能。

实现的效果图如下:

下面贴出代码:

1、列表子项的“取消关注”和“删除”按钮的布局,文件名“layout_del_cancel_btn.xml”,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="wrap_content"android:layout_height="match_parent"><Button
        android:id="@+id/id_item_cancel_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="取消关注"android:background="@android:color/darker_gray"android:textColor="#ffffff"android:layout_alignParentRight="true"android:layout_centerVertical="true"/><Button
        android:id="@+id/id_item_btn"android:layout_width="60dp"android:layout_height="wrap_content"android:text="删除"android:background="@android:color/holo_red_light"android:textColor="#ffffff"android:layout_alignParentRight="true"android:layout_centerVertical="true"/></LinearLayout>

2、自定义的ListView,文件名“SlideDeleteCancelListView.java”,代码如下:

package com.record2text.vitospc.deletelistview;import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;/*** 仿微信删除/取消关注列表* @author 马文涛 技术群:317922608*/
public class SlideDeleteCancelListView extends ListView {private static final String TAG = "SlideDelListView";private LayoutInflater mInflater = null;/*** 用户滑动的最小距离*/private int touchSlop;/*** 是否响应滑动*/private boolean isSliding;/*** 手指按下时的x坐标*/private int xDown;/*** 手指按下时的y坐标*/private int yDown;/*** 手指移动时的x坐标*/private int xMove;/*** 手指移动时的y坐标*/private int yMove;/*** 当前手指触摸的View*/private View mCurrentView;/*** 单签手指触摸的位置*/private int mCurrentViewPos;/*** 为删除按钮提供一个回调接口*/private DelButtonClickListener mDelListener = null;private CancelButtonClickListener mCancelListener = null;private PopupWindow mPopupWindow = null;private Button mDelBtn = null,mCancelBtn = null;private int mPopupWindowWidth, mPopupWindowHeight;/** 自定义ListView的构造方法 在里面做一些必要的一些初始化* @param context* @param attrs*/public SlideDeleteCancelListView(Context context, AttributeSet attrs) {super(context, attrs);mInflater = LayoutInflater.from(context);//用户手指移动的最小距离,用来判断是否响应触发移动事件touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();View view = mInflater.inflate(R.layout.layout_del_cancel_btn,null);//删除按钮mDelBtn = (Button) view.findViewById(R.id.id_item_btn);//取消按钮mCancelBtn = (Button) view.findViewById(R.id.id_item_cancel_btn);mPopupWindow = new PopupWindow(view,LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);/*** 先调用下measure,否则拿不到宽和高*/mPopupWindow.getContentView().measure(0,0);mPopupWindowHeight = mPopupWindow.getContentView().getMeasuredHeight();mPopupWindowWidth = mPopupWindow.getContentView().getMeasuredWidth();}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {int action = ev.getAction();int x = (int) ev.getX();int y = (int) ev.getY();switch (action){case MotionEvent.ACTION_DOWN://手指按下时水平方向x的位置xDown = x;//手指按下时垂直方向y的位置yDown = y;/** 如果当前popupWindow显示,则直接隐藏,然后屏蔽ListView的Touch事件的下传* */if (mPopupWindow.isShowing()){dismissPopWindow();return false;}// 获得当前手指按下时的item的位置mCurrentViewPos = pointToPosition(xDown,yDown);// 获得当前手指按下时的ListView的item项mCurrentView = getChildAt(mCurrentViewPos - getFirstVisiblePosition());break;case MotionEvent.ACTION_MOVE://手指移动时x的位置xMove = x;//手指一动时y的位置yMove = y;//水平滑动的距离(可能为负值)int dx = xMove - xDown;//垂直滑动的距离(可能为负值)int dy = yMove - yDown;/** 判断是否是从右到左的滑动* */if ( xMove < xDown && Math.abs(dx) > touchSlop && Math.abs(dy) < touchSlop ){Log.e(TAG, "touchslop = " + touchSlop + " , dx = " + dx + " , dy = " + dy);isSliding = true;}break;}return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {int action = ev.getAction();/** 如果是从右到左的滑动才响应,之前已在 dispatchTouchEvent 中获得了是否是从右向左滑动* */if ( isSliding ){switch (action){case MotionEvent.ACTION_MOVE:int []location = new int[2];//获得当前item的位置x与ymCurrentView.getLocationOnScreen(location);//设置PopupWindow的动画mPopupWindow.setAnimationStyle(R.style.popwindow_delete_btn_anim_style);mPopupWindow.update();Log.e(TAG,"width location[0]: " + location[0]);Log.e(TAG,"height location[1]: " + location[1]);Log.e(TAG,"mCurrentView.getWidth(): " + mCurrentView.getWidth());Log.e(TAG,"mCurrentView.getHeight(): " + mCurrentView.getHeight());Log.e(TAG,"mPopupWindowHeight: " + mPopupWindowHeight);//设置“取消关注”、“删除”按钮PopWindow的显示位置//相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移//相对某个控件的位置,有偏移;xoff表示x轴的偏移,正值表示向左,负值表示向右;yoff表示相对y轴的偏移,正值是向下,负值是向上;mPopupWindow.showAtLocation(mCurrentView,Gravity.LEFT | Gravity.TOP,location[0] + mCurrentView.getWidth() ,location[1] + mCurrentView.getHeight()/2 - mPopupWindowHeight /2);//设置删除按钮的回调mDelBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//通过接口对象调用当前Item上删除按钮的点击方法mDelListener.onDelClick(mCurrentViewPos);mPopupWindow.dismiss();}});//设置取消按钮的回调mCancelBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//通过接口对象调用当前Item上取消按钮的点击方法mCancelListener.onCancelClick(mCurrentViewPos);mPopupWindow.dismiss();}});Log.e(TAG, "mPopupWindow.getHeight()=" + mPopupWindowHeight);break;case MotionEvent.ACTION_UP://设置侧滑关闭isSliding = false;break;}// 相应滑动期间屏幕itemClick事件,避免发生冲突return true;}return super.onTouchEvent(ev);}/*** 隐藏popupWindow*/private void dismissPopWindow(){if (mPopupWindow != null && mPopupWindow.isShowing()){mPopupWindow.dismiss();}}/** 设置删除按钮点击事件监听* @param listener DelButtonClickListener 删除按钮监听接口对象*/public void setDelButtonClickListener(DelButtonClickListener listener){mDelListener = listener;}/** 设置取消按钮点击事件监听* @param listener CancelButtonClickListener 按钮点击事件监听接口对象*/public void setCancelButtonClickListener(CancelButtonClickListener listener){mCancelListener = listener;}/*** 删除按钮监听接口*/interface DelButtonClickListener{void onDelClick(int position);}/*** 取消按钮监听接口*/interface CancelButtonClickListener{void onCancelClick(int position);}
}

3、滑动展示“删除”、“取消关注”时需要展示和隐藏的动画,在自定义的ListView类“SlideDeleteCancelListView”中用到了,分别如下:
a.展示动画,文件名“delete_btn_show.xml”,代码如下:

<?xml version="1.0" encoding="utf-8"?>http://schemas.android.com/apk/res/android"><scale android:interpolator="@android:anim/accelerate_decelerate_interpolator"android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="1.0"
android:toYScale="1.0"
android:pivotX="100%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="200" ></scale></set>

b.隐藏动画,文件名“delete_btn_hide.xml”,代码如下:

<?xml version="1.0" encoding="utf-8"?>http://schemas.android.com/apk/res/android"><scale android:interpolator="@android:anim/accelerate_decelerate_interpolator"android:fromXScale="1.0"
android:toXScale="0.0"
android:fromYScale="1.0"
android:toYScale="1.0"
android:pivotX="100%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="200" ></scale></set>

4、以上部分已经完成了自定义有删除和取消关注功能的ListView,紧接着我们看一下如何使用这个ListView吧,首先贴上布局文件中的调用代码,文件名“activity_main.xml”,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.record2text.vitospc.deletelistview.MainActivity"><com.record2text.vitospc.deletelistview.SlideDeleteCancelListViewandroid:id="@+id/id_listview"android:layout_width="match_parent"android:layout_height="match_parent">
</com.record2text.vitospc.deletelistview.SlideDeleteCancelListView>
</RelativeLayout>

5、下来我们看一下主页面“MainActivity.java”中如何调用该段代码,并给响应的部分添加事件的,代码如下:

package com.record2text.vitospc.deletelistview;import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Toast;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** 仿微信删除/取消关注列表* @author 马文涛 技术群:317922608*/
public class MainActivity extends AppCompatActivity {private SlideDeleteCancelListView mListView = null;private List<String> mDatas = null;private ArrayAdapter mAdapter = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mListView = (SlideDeleteCancelListView) findViewById(R.id.id_listview);mDatas = new ArrayList<>(Arrays.asList("北京市", "天津市", "上海市", "重庆市", "安徽省", "福建省","甘肃省", "广东省", "贵州省", "海南省", "河北省","河南省","黑龙江省","湖北省","湖南省","吉林省"));mAdapter = new ArrayAdapter(MainActivity.this,android.R.layout.simple_list_item_1, mDatas);mListView.setAdapter(mAdapter);//设置列表项Item删除按钮的点击监听事件mListView.setDelButtonClickListener(new SlideDeleteCancelListView.DelButtonClickListener() {@Overridepublic void onDelClick(int position) {Toast.makeText(MainActivity.this, "删除:" + position + " : " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show();//从列表中移除当前项mAdapter.remove(mAdapter.getItem(position));}});//设置列表项Item的取消按钮点击监听事件mListView.setCancelButtonClickListener(new SlideDeleteCancelListView.CancelButtonClickListener() {@Overridepublic void onCancelClick(int position) {Toast.makeText(MainActivity.this, "取消关注:" + position + " : " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show();}});//设置列表项Item点击监听事件mListView.setOnItemClickListener(new AdapterView.OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id){Toast.makeText(MainActivity.this, "您点击的是第 " + position + " 项: " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show();}});}
}

已经完成了一个自定义的具有侧滑“删除”、“取消关注”的自定义ListView控件,在使用过程中大家只需要结合自己的项目进行修改即可。

新人初次发文章,有不足之处希望大家多多海涵,有兴趣的朋友可以加QQ群317922608,大家一起多多交流,多多指教,相互学习!

源码地址:http://download.csdn.net/detail/laker10070/9735811

Android自定义ListView实现仿微信侧滑删除相关推荐

  1. android 仿微信侧滑删除SwipeListView实例

    原帖地址:http://www.eoeandroid.com/thread-540337-1-1.html Android微信5.0以前某个版本(具体哪个忘记了)实现了和IOS上面一样的效果--侧滑删 ...

  2. 名片夹android布局代码,Android自定义布局实现仿qq侧滑部分代码

    自定义布局实现仿qq侧滑部分Android代码,供大家参考,具体内容如下 实现说明: 通过自定义布局实现: SlidingLayout继承于 HorizontalScrollView /** * Cr ...

  3. android仿qq布局,Android自定义布局实现仿qq侧滑部分代码

    自定义布局实现仿qq侧滑部分android代码,供大家参考,具体内容如下 实现说明: 通过自定义布局实现: slidinglayout继承于 horizontalscrollview /** * cr ...

  4. Android 自定义ListView控件,滑动删除

    1.触摸事件 dispatchTouchEvent 判断是否处理触摸动作 onTouchEvent 处理触摸动作 2.Android对于控制和获取View在屏幕很强大 ListView: pointT ...

  5. Android自定义View分享——仿微信朋友圈图片合并效果

    写在前面 笔者近来在学习Android自定义View,收集了一些不算复杂但又"长得"还可以的自定义View效果实现,之前分享过两个效果:一个水平的进度条,一个圆形温度显示器,如果你 ...

  6. Android自定义View之仿QQ侧滑菜单实现

    最近,由于正在做的一个应用中要用到侧滑菜单,所以通过查资料看视频,学习了一下自定义View,实现一个类似于QQ的侧滑菜单,顺便还将其封装为自定义组件,可以实现类似QQ的侧滑菜单和抽屉式侧滑菜单两种菜单 ...

  7. Android 自定义seekbar【仿微信联系人】

    /** *  * 转载请标明出处:http://blog.csdn.net/u013598111/article/details/50452578 *   @author:[JunTao_sun]   ...

  8. Android自定义view之仿微信录制视频按钮

    本文章只写了个类似微信的录制视频的按钮,效果图如下:            一.主要的功能: 1.长按显示进度条,单击事件,录制完成回调 2.最大时间和最小时间控制 3.进度条宽度,颜色设置 二.实现 ...

  9. Android 自定义Switch,仿微信开关键Switch

    switch (changeFragmentEvent.getViewId()) {//启动设备(安卓接收)case 1:textView.setText("vvvvv555"+c ...

最新文章

  1. android开机启动代码
  2. 本人常用的基础 linux命令
  3. 二十四、TextCNN的原理和实现
  4. 西瓜显示服务器错误,西瓜云服务器
  5. 测试Flex代码覆盖率工具---FlexCover
  6. openlayers3 根据经纬度 自动画框_Power Query获取上海市各区的经纬度
  7. D1、D系列分辨率是多少
  8. win7站点服务器配置,IIS 7.0安装配置方法图文教程(win7)
  9. 线程启动、结束,创建线程多法、join,detach
  10. python-lambda(匿名函数)原理与应用
  11. 单张像片空间后方交会
  12. 02.Rocky8安装KVM
  13. android渠道占有率,硬核联盟分发量在安卓渠道占比高达64%,2019年将发力四大方向...
  14. 记一次亚马逊扩容报错data size unchanged, skipping问题
  15. 高仿知乎android客户端,仿知乎分享界面
  16. RocketMQ——顺序消费(代码)
  17. JS微信打飞机游戏(一)
  18. 关于大学计算机相关专业学习路线的见解与分析
  19. 写给前端初学者的Vue入门教程
  20. Leetcode 597. 好友申请 I:总体通过率(round,计数)

热门文章

  1. 深入浅出TDD测试驱动
  2. Bluetooth Framework2022更新,新的错误代码
  3. JPA 深度刘宝宝剖析版
  4. 字符编码详解及利用C++ STL string遍历中文字符串
  5. 源代码license介绍
  6. usb hub 要驱动 linux,Linux驱动中配置支持特定USB HUB
  7. 求一到一百的总偶数奇数总数和的C语言程序,C语言程序求1—100之间的奇数和和偶数和...
  8. PKU1734 sightseeing trip
  9. modbus tcp通讯 在springboot中的实现
  10. Large Displacement Optical Flow: Descriptor Matching in Variational Motion Estimation