Android ListView 滑动删除效果

效果图:

实现:

1.新建ListViewDel 继承自ListView,即自定义的View了,代码如下所示:

 

package com.util;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.ScaleAnimation;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Scroller;

import com.blog.R;

public class ListViewDel extends ListView {
	private int slidePosition, preSlidePosition;
	private int downY;
	private int downX;
	public static View itemView, preItemView;
	private Scroller scroller;
	private static final int SNAP_VELOCITY = 600;
	private VelocityTracker velocityTracker;
	public static boolean isSlide = false;
	private boolean isResponse = true;
	public static boolean isObstruct = true;
	private int mTouchSlop;
	private RemoveListener mRemoveListener;

	private static Animation scaleHideAnimation;
	private static Animation scaleShowAnimation;

	public ListViewDel(Context context) {
		this(context, null);
	}

	public ListViewDel(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public ListViewDel(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		scroller = new Scroller(context);
		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
	}

	public void setRemoveListener(RemoveListener removeListener) {
		this.mRemoveListener = removeListener;
	}

	public boolean dispatchTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN: {

			addVelocityTracker(event);

			downX = (int) event.getX();
			downY = (int) event.getY();

			slidePosition = pointToPosition(downX, downY);

			if (slidePosition == AdapterView.INVALID_POSITION) {
				return super.dispatchTouchEvent(event);
			}

			if (preItemView != null
					&& preItemView.findViewById(R.id.tv_coating)
							.getVisibility() == View.GONE) {
				itemView = preItemView;
				slidePosition = preSlidePosition;
			} else {
				itemView = getChildAt(slidePosition - getFirstVisiblePosition());
				preItemView = itemView;
				preSlidePosition = slidePosition;
			}

			break;
		}
		case MotionEvent.ACTION_MOVE: {
			if (Math.abs(getScrollVelocity()) > SNAP_VELOCITY
					|| (Math.abs(event.getX() - downX) > mTouchSlop && Math
							.abs(event.getY() - downY) < mTouchSlop)) {
				isSlide = true;
			}
			break;
		}
		case MotionEvent.ACTION_UP:
			recycleVelocityTracker();
			isObstruct = true;
			break;
		}

		return super.dispatchTouchEvent(event);
	}

	public boolean onInterceptTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_MOVE:
			if (itemView.findViewById(R.id.tv_coating).getVisibility() == View.VISIBLE) {
				isSlide = false;
			} else {
				isSlide = true;
			}
			break;

		default:
			break;
		}
		return super.onInterceptTouchEvent(ev);
	}

	public boolean onTouchEvent(MotionEvent ev) {
		if (isSlide && slidePosition != AdapterView.INVALID_POSITION) {
			addVelocityTracker(ev);
			final int action = ev.getAction();
			switch (action) {
			case MotionEvent.ACTION_MOVE:

				if (isObstruct) {

					if (itemView.findViewById(R.id.tv_coating).getVisibility() == View.VISIBLE
							&& isResponse == true) {

						scaleHideAnimation = new ScaleAnimation(1.0f, 0.0f,
								1.0f, 1.0f);
						scaleHideAnimation.setDuration(250);
						scaleHideAnimation
								.setAnimationListener(new AnimationListener() {

									public void onAnimationStart(
											Animation animation) {
										isResponse = false;
										isObstruct = false;
									}

									public void onAnimationRepeat(
											Animation animation) {

									}

									public void onAnimationEnd(
											Animation animation) {
										isResponse = true;
										itemView.findViewById(R.id.tv_coating)
												.setVisibility(View.GONE);
										itemView.findViewById(R.id.tv_functions)
												.setClickable(true);
										itemView.findViewById(R.id.tv_functions)
												.setOnClickListener(
														new OnClickListener() {

															public void onClick(
																	View v) {
																mRemoveListener
																		.removeItem(slidePosition);
															}

														});

									}
								});

						itemView.findViewById(R.id.tv_coating).startAnimation(
								scaleHideAnimation);

					} else if (itemView.findViewById(R.id.tv_coating)
							.getVisibility() == View.GONE && isResponse == true) {

						scaleShowAnimation = new ScaleAnimation(0.0f, 1.0f,
								1.0f, 1.0f);
						scaleShowAnimation.setDuration(250);
						scaleShowAnimation
								.setAnimationListener(new AnimationListener() {

									public void onAnimationStart(
											Animation animation) {
										isResponse = false;
										isObstruct = false;
									}

									public void onAnimationRepeat(
											Animation animation) {

									}

									public void onAnimationEnd(
											Animation animation) {
										isSlide = false;
										isResponse = true;
										itemView.findViewById(R.id.tv_coating)
												.setVisibility(View.VISIBLE);
									}
								});

						itemView.findViewById(R.id.tv_coating).startAnimation(
								scaleShowAnimation);
					}
				}
				break;
			case MotionEvent.ACTION_UP:
				isObstruct = true;
				recycleVelocityTracker();
				isSlide = true;
				break;
			}
			return true;
		}

		return super.onTouchEvent(ev);
	}

	public void computeScroll() {
		if (scroller.computeScrollOffset()) {
			postInvalidate();
			if (scroller.isFinished()) {
				if (mRemoveListener == null) {
					throw new NullPointerException(
							"RemoveListener is null, we should called setRemoveListener()");
				}

				itemView.scrollTo(0, 0);
			}
		}
	}

	private void addVelocityTracker(MotionEvent event) {
		if (velocityTracker == null) {
			velocityTracker = VelocityTracker.obtain();
		}
		velocityTracker.addMovement(event);
	}

	private void recycleVelocityTracker() {
		if (velocityTracker != null) {
			velocityTracker.recycle();
			velocityTracker = null;
		}
	}

	private int getScrollVelocity() {
		velocityTracker.computeCurrentVelocity(1000);
		int velocity = (int) velocityTracker.getXVelocity();
		return velocity;
	}

	public interface RemoveListener {
		public void removeItem(int position);
	}

}

自定义View的功能到此就完成了,接下来我们需要看一下如何才能使用这个自定义View。首先需要创建一个ListView子项的布局文件,新建listview_item.xml,代码如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/ll_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#eee"
    android:gravity="center"
    android:orientation="horizontal"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/tv_item"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="left"
        android:padding="8dp"
        android:text="狗狗"
        android:textColor="#000"
        android:textSize="16sp" />

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|center_vertical"
        android:padding="15dp" >

        <TextView
            android:id="@+id/tv_functions"
            android:layout_width="100dp"
            android:layout_height="30dp"
            android:layout_gravity="center"
            android:background="@drawable/btn_del_bg"
            android:gravity="center"
            android:text="删除"
            android:textColor="@android:color/white" />

        <TextView
            android:id="@+id/tv_coating"
            android:layout_width="100dp"
            android:layout_height="30dp"
            android:layout_gravity="center"
            android:background="#eee"
            android:visibility="gone" />
    </FrameLayout>

</LinearLayout>

然后创建一个适配器ListItemAdapter,在这个适配器中去加载listview_item.xml布局,代码如下所示:

package com.util;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.blog.R;

public class ListItemAdapter extends BaseAdapter {

	private LayoutInflater inflater;
	private ArrayList<String> datas;

	public ListItemAdapter(Context context) {
		inflater = LayoutInflater.from(context);
	}

	public void setData(ArrayList<String> datas) {
		this.datas = datas;
	}

	public int getCount() {
		return datas.size();
	}

	public Object getItem(int position) {
		return datas.get(position);
	}

	public long getItemId(int position) {
		return position;
	}

	public View getView(final int position, View convertView, ViewGroup parent) {
		ViewHolder holder = null;
		if (convertView == null) {
			holder = new ViewHolder();
			convertView = inflater.inflate(R.layout.listview_item, null);
			holder.textView = (TextView) convertView.findViewById(R.id.tv_item);
			holder.coating = (TextView) convertView
					.findViewById(R.id.tv_coating);
			holder.functions = (TextView) convertView
					.findViewById(R.id.tv_functions);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		holder.textView.setText(datas.get(position));
		holder.coating.setVisibility(View.VISIBLE);

		holder.functions.setClickable(false);

		return convertView;
	}

	public final class ViewHolder {
		public TextView textView;
		public TextView coating;
		public TextView functions;
	}
}

下面在程序的主布局文件里面引入MyListView这个控件,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#eee"
    android:orientation="vertical" >

    <RelativeLayout
        android:id="@+id/top_relative"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="10.0dp" >

        <LinearLayout
            android:id="@+id/title"
            android:layout_width="fill_parent"
            android:layout_height="45dp"
            android:background="@drawable/android_title_bg"
            android:gravity="center_horizontal|center_vertical" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                android:textColor="#ffffff"
                android:textSize="20sp" />
        </LinearLayout>

        <TextView
            android:id="@+id/typetitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_marginTop="8.0dip"
            android:gravity="center"
            android:lineSpacingExtra="6.0dp"
            android:paddingLeft="20.0dp"
            android:paddingTop="10.0dp"
            android:singleLine="true"
            android:text=""
            android:textColor="#fff"
            android:textSize="16.0sp" />
    </RelativeLayout>

    <TextView
        android:id="@+id/tv_text"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:gravity="center"
        android:text="浏览历史记录"
        android:textSize="18sp" />

    <com.util.ListViewDel
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/tv_text"
        android:cacheColorHint="#00000000"
        android:divider="@drawable/reader_item_divider"
        android:fadingEdge="none"
        android:listSelector="#00000000" >
    </com.util.ListViewDel>

</LinearLayout>

最后在Activity中初始化ListViewDel中的数据,代码如下所示:

package com.blog;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;

import com.util.ListItemAdapter;
import com.util.ListViewDel;
import com.util.ListViewDel.RemoveListener;

public class MainActivity extends Activity implements RemoveListener {
	private ListViewDel list;
	private ListItemAdapter adapter;
	private ArrayList<String> dataSourceList = new ArrayList<String>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();
	}

	private void init() {
		list = (ListViewDel) findViewById(R.id.list);
		list.setRemoveListener(this);

		for (int i = 0; i < 20; i++) {
			dataSourceList.add((i > 2 ? "淘宝" + " " + i : "京东" + " 0" + i));

		}

		adapter = new ListItemAdapter(this);
		adapter.setData(dataSourceList);
		list.setAdapter(adapter);

		list.setOnItemClickListener(new OnItemClickListener() {

			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				Intent intent = new Intent(getApplicationContext(),
						ListItemActivity.class);
				intent.putExtra("item", dataSourceList.get(position));
				startActivity(intent);
				overridePendingTransition(R.anim.slide_in_from_right,
						R.anim.remain_original_location);
			}

		});
	}

	public void removeItem(int position) {
		ListViewDel.isSlide = false;
		ListViewDel.itemView.findViewById(R.id.tv_coating).setVisibility(
				View.VISIBLE);
		dataSourceList.remove(position);
		adapter.notifyDataSetChanged();
	}

}

(本篇完)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值