【安卓笔记】滑动删除示例

本文将使用上篇文章介绍的Scroller类来完成一个比较常见的效果——滑动删除效果。

代码如下:

simpleSwipeListView:

package cn.edu.chd.simpleswipelistview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.Scroller;
/**
 * @author Rowandjj
 *
 *滑动删除示例
 */
public class SimpleSwipeListView extends ListView
{
	private static final String TAG = "SimpleSwipeListView";
	private static final boolean DEBUG = true;
	private Scroller mScroller = null;
	private int mTouchSlop;

	/**
	 * 屏幕宽度
	 */
	private int mScreenWidth;

	private View targetView;

	/**
	 * 当前item的位置
	 */
	private int position;

	/**
	 * 手指按下的位置
	 */
	private int downX,downY;

	/**
	 * 是否能删除item
	 */
	private boolean canRemove = true;

	private boolean isSwipe;

	/**
	 * item被删除的回调事件
	 */
	private OnItemRemovedListener mListener;
	public interface OnItemRemovedListener
	{
		public void removeItem(int position);
	}

	public void setOnItemRemovedListener(OnItemRemovedListener listener)
	{
		this.mListener = listener;
	}

	public SimpleSwipeListView(Context context)
	{
		this(context, null);
	}
	public SimpleSwipeListView(Context context, AttributeSet attrs)
	{
		this(context, attrs, 0);
	}
	public SimpleSwipeListView(Context context, AttributeSet attrs,
			int defStyleAttr)
	{
		super(context, attrs, defStyleAttr);
		init(context);
	}
	private void init(Context context)
	{
		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
		mScreenWidth = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
		mScroller = new Scroller(context);
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev)
	{

		switch (ev.getAction())
		{
		case MotionEvent.ACTION_DOWN:
			if(!mScroller.isFinished())
				return super.onTouchEvent(ev);

			downX = (int) ev.getX();
			downY = (int) ev.getY();
			//根据坐标得到position
			position = pointToPosition(downX, downY);
			if(position == AbsListView.INVALID_POSITION)
				return super.onTouchEvent(ev);
			//根据position得到代表item的view对象
			targetView = getChildAt(position-getFirstVisiblePosition());
			break;
		case MotionEvent.ACTION_MOVE:
			int x = (int) ev.getX();
			int y = (int) ev.getY();
			if(Math.abs(x-downX)>mTouchSlop&&Math.abs(y-downY)<mTouchSlop)
			{
				int deltaX = downX-x;
				downX = x;
				downY = y;
				targetView.scrollBy(deltaX,0);
				isSwipe = true;
			}
			if(isSwipe)//禁止listView滚动
				return true;
			break;
		case MotionEvent.ACTION_UP:
			scrollByOffset();
			isSwipe = false;
			break;
		}
		return super.onTouchEvent(ev);
	}

	/**
	 * 根据偏移量判断是向左还是向右滚动
	 */
	private void scrollByOffset()
	{
		int scrollX = targetView.getScrollX();//当前偏移
		if(scrollX > mScreenWidth/3)//应该向左滚
		{
			scrollToLeft(scrollX);
		}else if(scrollX < -mScreenWidth/3)//应该向右滚
		{
			scrollToRight(scrollX);
		}else//滚回原点
		{
			scrollToOrigin(scrollX);
		}
	}

	private void scrollToOrigin(int scrollX)
	{
		mScroller.startScroll(scrollX,0,-scrollX,0,Math.abs(scrollX));
		postInvalidate();
		canRemove = false;
	}

	/**
	 * 向右滚动
	 */
	private void scrollToRight(int scrollX)
	{
		int deltaX = mScreenWidth+scrollX;
		mScroller.startScroll(scrollX, 0, -deltaX, 0, Math.abs(deltaX));
		invalidate();
		canRemove = true;
	}

	/**
	 * 向左滚动
	 */
	private void scrollToLeft(int scrollX)
	{
		int deltaX = mScreenWidth - scrollX;
		mScroller.startScroll(scrollX, 0, deltaX, 0, Math.abs(deltaX));
		invalidate();
		canRemove = true;
	}

	@Override
	public void computeScroll()
	{
		if(mScroller != null)
		{
			if(mScroller.computeScrollOffset())
			{
				int currX = mScroller.getCurrX();
				int currY = mScroller.getCurrY();
				targetView.scrollTo(currX,currY);
				postInvalidate();

				if(mScroller.isFinished())
				{
					targetView.scrollTo(0, 0);
					if(canRemove)
					{
						if(mListener == null)
							throw new RuntimeException("you must call setOnRemoveItemListener to set a listener");
						if(DEBUG)
							Log.d(TAG,"position:"+position);
						//删除item
						mListener.removeItem(position);
						canRemove = false;
					}
				}
			}
		}
	}
}

布局:

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:background="#ededed"
    tools:context="cn.edu.chd.simpleswipelistview.MainActivity" >
    <cn.edu.chd.simpleswipelistview.SimpleSwipeListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_marginTop="2dp"
        android:layout_marginBottom="2dp"
        android:layout_height="wrap_content"
        android:listSelector="@android:color/transparent"
        android:cacheColorHint="@android:color/transparent"
        android:divider="@null"
        android:dividerHeight="2dp"
        ></cn.edu.chd.simpleswipelistview.SimpleSwipeListView>

</RelativeLayout>

item.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="3dp"
    android:descendantFocusability="beforeDescendants"
    android:paddingRight="3dp" >
    <!--滚动的是下面的内容-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:background="@drawable/card_background_selector"
        android:gravity="center_vertical|left"
        android:descendantFocusability="afterDescendants"
        android:orientation="vertical" >
        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:textColor="@android:color/black"
            android:textSize="18sp" />
    </LinearLayout>
</FrameLayout>

主界面代码:

package cn.edu.chd.simpleswipelistview;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import cn.edu.chd.simpleswipelistview.SimpleSwipeListView.OnItemRemovedListener;
public class MainActivity extends Activity
{
	private SimpleSwipeListView mListView = null;
	private ArrayAdapter<String> mAdapter = null;
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mListView = (SimpleSwipeListView) findViewById(R.id.lv);
		final List<String> data = new ArrayList<String>();
		for(int i = 0; i < 20; i++)
		{
			data.add("this is text num"+i);
		}
		mAdapter = new ArrayAdapter<>(this,R.layout.item, R.id.tv, data);
		mListView.setAdapter(mAdapter);

		mListView.setOnItemRemovedListener(new OnItemRemovedListener()
		{
			@Override
			public void removeItem(int position)
			{
				//此处并不用调用notifyDataSetChanged,因为remove方法内部调用了
				mAdapter.remove(data.get(position));
			}
		});
	}
}

效果截屏不方便,大家自己看吧。

相信大家结合上篇文章介绍的Scroller理解代码应该很easy。

重点需要注意以下几点:

1.如何根据坐标找到view对象。(pointToPosition和getChildAt方法的使用)

2.Scroller的使用,特别是scrollTo、scrollBy以及computeScroll方法。

3.需要注意如果希望对某个view进行滚动,应该调用其父view的scrollTo、scrollBy方法。

4.处理滑动冲突,横向滑动删除时应避免listView滚动。

github源码:https://github.com/Rowandjj/SimpleSwipeListView

时间: 2024-08-06 20:06:24

【安卓笔记】滑动删除示例的相关文章

仿知乎安卓client滑动删除撤销ListView

标签(空格分隔): Android 新版的知乎安卓client有一个有趣的功能,就是在一个item里.向右滑动时整个item会越来越透明,滑动到一半时,整个item就不见了.放开手指就是删除.删除后还能够撤销,第一次看见这个功能觉得非常有意思,用了几天业余时间,我仿造里一个.效果例如以下: 那以下就来想想看怎么实现的,大概能够先分解为三部分: 手指滑动删除item 删除item后的撤销功能 滑动时的效果处理 提醒一下假设你对scroller不熟悉.能够先看一下scroller实现原理 先来看最基

#仿知乎安卓客户端滑动删除撤销ListView

标签(空格分隔): Android 新版的知乎安卓客户端有一个有趣的功能,就是在一个item里,向右滑动时整个item会越来越透明,滑动到一半时,整个item就不见了,放开手指就是删除,删除后还可以撤销,第一次看见这个功能觉得很有意思,用了几天业余时间,我仿造里一个,效果如下: 那下面就来想想看怎么实现的,大概可以先分解为三部分: 手指滑动删除item 删除item后的撤销功能 滑动时的效果处理 提醒一下如果你对scroller不熟悉,可以先看一下scroller实现原理 先来看最主要的类Cus

【学习笔记】&quot;ListView滑动删除 ,仿腾讯QQ&quot;(二)

今天继续学习"鸿祥_"大神的写的"ListView滑动删除,仿腾讯QQ" . 1.关于dispatchTouchEvent 之前,只用过onTouchEvent,现在才知道一个Touch事件居然如此复杂.OK,集中精力,且看下文(本段内容主要参考Android dispatchTouchEvent介绍): 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_

【学习笔记】&quot;ListView滑动删除 ,仿腾讯QQ&quot;(一)

今天看了"鸿祥_"大神的写的"ListView滑动删除,仿腾讯QQ" .大神果然是大神,第一篇文章,我就看不懂,好多知识需要学习. 1.  文中的一个声明:private LayoutInflater mInflater; 什么是LayoutInflater? 答:主要参考了这篇文章 Android LayoutInflater详解 在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById().不同点是LayoutInfl

【学习笔记】&quot;ListView滑动删除 ,仿腾讯QQ&quot;(三)

今天继续学习"鸿祥_"大神的写的"ListView滑动删除,仿腾讯QQ" . 今天,我准备学习并理清QQListView的逻辑. 1.自定义ListView 先看看布局文件activity_main.xml: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.c

android 继承ListView实现滑动删除功能.

在一些用户体验较好的应用上,可以经常遇见   在ListView中  向左或向右滑动便可删除那一项列表. 具体实现  则是继承ListView实现特定功能即可. (1). 新建 delete_button.xml文件 <?xml version="1.0" encoding="utf-8"?> <Button xmlns:android="http://schemas.android.com/apk/res/android" a

【安卓笔记】抽屉式布局----DrawerLayout

效果如下: DrawerLayout来自support.v4包,所以不用考虑兼容性问题.其次,这种布局类似风靡一时的侧滑菜单,但是比侧滑菜单轻巧许多. 下面介绍这种布局的使用方式. 1.在你的项目中导入support.v4包. 2.编辑一个布局,根节点为android.support.v4.widget.DrawerLayout,此节点下只允许有两个子节点,第一个为将来主页面的内容,第二个节点即为"抽屉"内容,通常是一个ListView.比如: <android.support.

Android Demo 下拉刷新+加载更多+滑动删除

小伙伴们在逛淘宝或者是各种app上,都可以看到这样的功能,下拉刷新和加载更多以及滑动删除,刷新,指刷洗之后使之变新,比喻突破旧的而创造出新的,比如在手机上浏览新闻的时候,使用下拉刷新的功能,我们可以第一时间掌握最新消息,加载更多是什么nie,简单来说就是在网页上逛淘宝的时候,我们可以点击下一页来满足我们更多的需求,但是在手机端就不一样了,没有上下页,怎么办nie,方法总比困难多,细心的小伙伴可能会发现,在手机端中,有加载更多来满足我们的要求,其实加载更多也是分页的一种体现.小伙伴在使用手机版QQ

仿手机QQ列表支持下拉,上滑,滑动删除

一般安卓程序员都知道下拉刷新主键用 com.handmark.pulltorefresh 网站:https://github.com/chrisbanes/Android-PullToRefresh/ 滑动删除用 fortysevendeg 的 swipelistview 但是要实现QQ列表功能,需要把两者叠加起来,我尝试了一下,发现有Bug, fortysevendeg的代码有点复杂,放弃了,后来自己搞了一个,为了方便广大 安卓程序员,我把整个demo贡献出来. 下载地址:http://pan