高仿 美团 向左滑动删除条目

1、效果图

       
   

2、功能实现

2.1 布局结构

<?xml version="1.0" encoding="UTF-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="80dip"
    android:background="#FF5555" >

    <TextView
        android:id="@+id/tv_show_info"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginRight="10dip"
        android:gravity="right|center_vertical"
        android:padding="15dip"
        android:text="向左滑动删除"
        android:textColor="#FFFFFF" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:background="#00FFFFFF" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:background="#FFFFFF" >

            <TextView
                android:id="@+id/list_item"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:padding="15dip"
                android:text="ad"
                android:textSize="18sp" />
        </LinearLayout>
    </LinearLayout>

</FrameLayout>

在这里使用了FrameLayout布局,它的第一个孩子TextView是显示的文字,当向左滑动时,它的字体大小慢慢变大,透明度也慢慢变清晰,向右滑动时则相反,文字最终被隐藏。第二个孩子里面有用了一个LinearLayout并且它为透明,因为当view移动时移动的是其子View,如果不加LinearLayout那么整个布局向左滑动,看不到下面的字。

2.2 需要用到的类

首先需要继承ListView对其进行扩展,思路就是根据用户按下时的坐标获取当前item的位置position,在根据位置获取其对应的view项,继而操作view使其移动。

其次,有滚动自然想到使用Scroller类,可以使布局能够向左滑动,在这里为了方便加入了GestureDetector手势识别类。

最后,重写computeScroll方法使其完成滚动动画。

2.3 实现

package com.example.customui.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Scroller;

import com.example.customui.util.Logger;

public class SwipeListView extends ListView {
	/**
	 * 手势识别
	 */
	private GestureDetector mGestureDetector;
	/**
	 * 滑动类
	 */
	private Scroller mScroller;
	/**
	 * 需要移动的view
	 */
	private View currentMoveView;

	private int downX;

	private int downY;

	/**
	 * 将手指按下时的坐标转换成listview的item的位置
	 */
	private int slidePosition;

	/**
	 * 是否在滑动
	 */
	private boolean isSlide;
	//快速滑动
//	private boolean isFling;

	private int mTouchSlop;
	/**
	 * 屏幕宽度
	 */
	private int screenWidth;
	/**
	 * listview item
	 */
	private ViewGroup viewGroup;

	private static final int SNAP_VELOCITY = 600;
	public SwipeListView(Context context) {
		super(context);
		init(context);
	}

	public SwipeListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);

	}
	private void init(Context context){
		mScroller = new Scroller(context);
		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
		screenWidth = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
		mGestureDetector = new GestureDetector(context,new OnGestureListener() {
			@Override
			public boolean onSingleTapUp(MotionEvent e) {
				return false;
			}

			@Override
			public void onShowPress(MotionEvent e) {

			}

			@Override
			public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
					float distanceY) {
				if (isSlide && currentMoveView!=null) {
					if (listener!=null) {
						listener.scroll(currentMoveView.getScrollX(), viewGroup);
					}
					currentMoveView.scrollBy((int)distanceX, 0);
				}
				return false;
			}

			@Override
			public void onLongPress(MotionEvent e) {

			}

			@Override
			public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
					float velocityY) {
//				if (isSlide && (e2.getX()-e1.getX())<0) {
//					isFling = true;
//					Logger.getLogger().i("==============> 快速滑动"+(e2.getX()-e1.getX()));
//				}
				return false;
			}

			@Override
			public boolean onDown(MotionEvent e) {
				return false;
			}
		});
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN: {
				Logger.getLogger().i("--------dispatchTouchEvent down--------> ");
				if (!mScroller.isFinished()  || isSlide) {
					return super.dispatchTouchEvent(event);
				}
				downX = (int) event.getX();
				downY = (int) event.getY();
				Logger.getLogger().i("-------------downX= "+downX);
				slidePosition = pointToPosition(downX, downY);
				// 无效的position, 不做任何处理;isSlide防止多个手指按下时影响isFling的值,导致被删除
				if (slidePosition == AdapterView.INVALID_POSITION) {
					return super.dispatchTouchEvent(event);
				}
				// 获取我们点击的item view
			   viewGroup = (ViewGroup) getChildAt(slidePosition - getFirstVisiblePosition());
			    //需要一定的view
				currentMoveView = viewGroup.getChildAt(1);
				break;
			}
			case MotionEvent.ACTION_MOVE:{
				int x = (int) (event.getX()-downX);
				int y = (int) (event.getY() -downY);
//				Logger.getLogger().i("-------------x= "+x+" y= "+y+" mTouchSlop:"+mTouchSlop);
				if (Math.abs(x)>mTouchSlop && Math.abs(x)>Math.abs(y) && x<0 ) {
					isSlide = true;
				}
				break;
			}

		}
		return super.dispatchTouchEvent(event);
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		mGestureDetector.onTouchEvent(ev);
		if (isSlide) {
			if (!mScroller.isFinished()) {
				return true;
			}
			switch (ev.getAction()) {
				case MotionEvent.ACTION_DOWN:{
					downX = (int) ev.getX();
					break;
				}
				case MotionEvent.ACTION_CANCEL:
				case MotionEvent.ACTION_UP:{
					/*if (isFling || isRemoveItem()) {
						if (isFling && this.listener!=null ) {
		            		Logger.getLogger().i("滑动删除。。");
							this.listener.removeItem(slidePosition);
						}else*/
					if (isRemoveItem() && this.listener!=null) {
						this.listener.removeItem(slidePosition);
						mScroller.startScroll(currentMoveView.getScrollX(), 0,screenWidth, 0,Math.abs(300));
					}else {
						int delta = currentMoveView.getScrollX();
						mScroller.startScroll(currentMoveView.getScrollX(), 0,-delta, 0,Math.abs(500));
					}
					postInvalidate();

				}
			}
			return true;
		}
		return super.onTouchEvent(ev);
	}

	@Override
	public void computeScroll() {
		// 调用startScroll的时候scroller.computeScrollOffset()返回true,
        if (mScroller.computeScrollOffset()) {
            // 让ListView item根据当前的滚动偏移量进行滚动
            currentMoveView.scrollTo(mScroller.getCurrX(), 0);
            postInvalidate();
            // 滚动动画结束的时候调用回调接口
            if (mScroller.isFinished()) {
            	currentMoveView.scrollTo(0, 0);
            	if (this.listener!=null && isSlide) {
            		this.listener.scrollFinish();
            	}
            	isSlide = false;
            }
        }
	}

	private boolean isRemoveItem(){
		if (currentMoveView.getScrollX()>screenWidth/2) {
			return true;
		}
		return false;
	}

	private RemoveItemListViewListener listener;
	public void setRemoveItemListViewListener(RemoveItemListViewListener listener){
		this.listener = listener;
	}
	public interface RemoveItemListViewListener{
		public void removeItem(int pos);
		public void scroll(float scrollX,View view);
		public void scrollFinish();
	}

}

2.4 activity代码

通过滚动的距离来设置textview的字体大小和透明度。

package com.example.customui.activity;

import java.util.ArrayList;
import java.util.List;

import android.R.integer;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import com.example.customui.BaseActivity;
import com.example.customui.R;
import com.example.customui.adapter.CommonAdapter;
import com.example.customui.adapter.ViewHolder;
import com.example.customui.util.DensityUtil;
import com.example.customui.util.Logger;
import com.example.customui.view.SwipeListView;
import com.example.customui.view.SwipeListView.RemoveItemListViewListener;

public class SwipeListViewActivity extends BaseActivity {

	private SwipeListView mListView;
	private List<String> dataSourceList;
	private ArrayAdapter mAdapter;
	private int screenWidth;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.swipe_listview_main);
		mListView = (SwipeListView) findViewById(R.id.lv_data);
		screenWidth = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
		dataSourceList = new ArrayList<String>();

		for (int i = 0; i < 20; i++) {
			dataSourceList.add("item "+i);
		}
		mAdapter = new ArrayAdapter(getApplicationContext(), R.layout.list_view_item,R.id.list_item,dataSourceList);
		mListView.setAdapter(mAdapter);

		mListView.setRemoveItemListViewListener(new RemoveItemListViewListener() {
			private TextView textView;

			@Override
			public void removeItem(int pos) {
				position = pos;
			}

			@Override
			public void scroll(float scrollX, View view) {
				if (textView==null) {
					textView = (TextView) view.findViewById(R.id.tv_show_info);
				}
				int fontSize=1;
				float alpha=0.0f;

				if (scrollX>screenWidth/3) {
					alpha=1.0f;
					fontSize=maxFontSize;
				}else {
					alpha = scrollX/(screenWidth/3);
					fontSize = (int) (alpha * maxFontSize);
				}
				textView.setAlpha(alpha);
				textView.setTextSize(fontSize);
			}

			@Override
			public void scrollFinish() {
				textView=null;
				if (position>=0) {
					Logger.getLogger().i("----------------------->删除的位置: "+position);
					dataSourceList.remove(position);
					mAdapter.notifyDataSetChanged();
					position= -1;
				}
			}

		});
	}

	private int position=-1;

	private int maxFontSize=22;

}
时间: 2024-08-29 04:37:56

高仿 美团 向左滑动删除条目的相关文章

关于高仿微信对话列表滑动删除效果代码优化

原文:http://blog.csdn.net/singwhatiwanna/article/details/17515543 最近公司项目需用到微信滑动拉出按钮的效果,发现一位牛人已经实现了相关效果,但控件仍与业务代码存有耦合,于是花了点时间做了些去耦合,并于此进行记录,以防遗忘. 个人认为耦合主要在于两点: 第一点是SlideListView中的onTouchEvent 通过获取item间接得到SlideView,但这样会引入外部数据类MessageItem.          @Overr

高仿微信对话列表滑动删除效果(转)

前言 用过微信的都知道,微信对话列表滑动删除效果是很不错的,这个效果我们也可以有.思路其实很简单,弄个ListView,然后里面的每个item做成一个可以滑动的自定义控件即可.由于ListView是上下滑动而item是左右滑动,因此会有滑动冲突,也许你需要了解下android中点击事件的派发流程,请参考Android源码分析-点击事件派发机制.我的解决思路是这样的:重写ListView的onInterceptTouchEvent方法,在move的时候做判断,如果是左右滑动就返回false,否则返

【转】高仿微信对话列表滑动删除效果--不错

原文网址:http://blog.csdn.net/singwhatiwanna/article/details/17515543 转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17515543 前言 用过微信的都知道,微信对话列表滑动删除效果是很不错的,这个效果我们也可以有.思路其实很简单,弄个ListView,然后里面的每个item做成一个可以滑动的自定义控件即可.由于ListView是上下滑动而item是左右滑动,因

高仿微信对话列表滑动删除效果

前言 用过微信的都知道.微信对话列表滑动删除效果是非常不错的,这个效果我们也能够有. 思路事实上非常easy,弄个ListView.然后里面的每一个item做成一个能够滑动的自己定义控件就可以.由于ListView是上下滑动而item是左右滑动,因此会有滑动冲突.或许你须要了解下android中点击事件的派发流程,请參考Android源代码分析-点击事件派发机制.我的解决思路是这种:重写ListView的onInterceptTouchEvent方法,在move的时候做推断,假设是左右滑动就返回

android QQ消息左滑动删除实例(优化版SwipeListViewEX)

仿 QQ消息左滑动删除item消息实例 源代码参考:http://blog.csdn.net/gaolei1201/article/details/42677951 自己作了一些调整,全部代码下载地址: http://download.csdn.net/detail/jenson138/8490067 效果图: 以下只有适配器类: 1 package com.ryg.slideview; 2 3 import java.util.List; 4 5 import com.ryg.slidevie

android 下拉刷新上拉加载更多,高仿ios左滑动删除item,解决了众多手势问题

一.前言 老规矩,别的不说,这demo是找了很相关知识集合而成的,可以说对我这种小白来说是绞尽脑汁!程序员讲的是无图无真相!现在大家一睹为快! 二.比较关键的还是scroller这个类的 package com.icq.slideview.view; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; i

高仿美团应用客户端项目源码

源码Tuan,这个案例是模仿MJ老师ipad版美团(swift版),高仿美团iOS版,版本号:5.7, 已更新到Swift 2.0 基于Xcode 7 源码下载: http://code.662p.com/view/11383.html <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore

高仿美团应用客户端布局源码

高仿美团框架基本已搭好.代码简单易懂,适合新人.适合新人. 源码下载:http://code.662p.com/list/12_1.html新人. <ignore_js_op> <ignore_js_op> 详细说明:http://ios.662p.com/thread-2774-1-1.html

高仿美团iOS版,版本号5.7

高仿美团iOS版,版本号:5.7 github链接:https://github.com/lookingstars/meituan 如果你觉得不错,欢迎star 哦 1.团购首页: 1.1  团购-->猜你喜欢->右上角分享 到微信朋友圈,新浪微博等 2.商家 3.名店抢购 4.推荐: 5.热门排队 6.团购详情 7.上门服务 8.上门洗车 9.地图:附近美食 10.商家分类显示 11.启动页广告: 12.我的 13.更多: 版权声明:本文为博主原创文章,未经博主允许不得转载.