Scroller应用:ListView滑动删除

1、设计思路

Scroller的应用--滑屏实现中使用Scroller实现滑屏效果,这里使用Scroller与ListView实现类似QQ滑动,然后点击删除功能,设计思路是Item使用Scroller实现滑动,ListView根据触摸判断是横向滑动还是竖直滑动,关于点击事件处理思路:对于View的onClick事件跟平常一样,里面针对OnItemClick做了处理,判断触摸距离来判断,如果小于5的话,在Item的onTouchEvent方法中的MotionEvent.ACTION_UP里面返回false,这样ListView里面的dispatchTouchEvent的super.dispatchTouchEvent(event)就会返回false,根据x,y获取当前position以及点击的view,调用super.performItemClick(view, position, view.getId());来告诉ListView出发onItemClick事件。

2、Item的代码

package com.jwzhangjie.scrollview;  
  
import android.content.Context;  
import android.util.AttributeSet;  
import android.util.Log;  
import android.view.MotionEvent;  
import android.view.View;  
import android.widget.LinearLayout;  
import android.widget.Scroller;  
  
public class ListItemDelete extends LinearLayout {  
  
    private Scroller mScroller;// 滑动控制  
    private float mLastMotionX;// 记住上次触摸屏的位置  
    private int deltaX;  
    private int back_width;  
    private float downX;  
  
    public ListItemDelete(Context context) {  
        this(context, null);  
    }  
  
    public ListItemDelete(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        init(context);  
    }  
  
    private void init(Context context) {  
        mScroller = new Scroller(context);  
    }  
  
    @Override  
    public void computeScroll() {  
        if (mScroller.computeScrollOffset()) {// 会更新Scroller中的当前x,y位置  
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  
            postInvalidate();  
        }  
    }  
  
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
        int count = getChildCount();  
        for (int i = 0; i < count; i++) {  
            measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);  
            if (i == 1) {  
                back_width = getChildAt(i).getMeasuredWidth();  
            }  
        }  
  
    }  
  
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        int action = event.getAction();  
        float x = event.getX();  
        switch (action) {  
        case MotionEvent.ACTION_DOWN:  
            Log.e("test", "item  ACTION_DOWN");  
            mLastMotionX = x;  
            downX = x;  
            break;  
        case MotionEvent.ACTION_MOVE:  
            Log.e("test", back_width + "  item  ACTION_MOVE  " + getScrollX());  
            deltaX = (int) (mLastMotionX - x);  
            mLastMotionX = x;  
            int scrollx = getScrollX() + deltaX;  
            if (scrollx > 0 && scrollx < back_width) {  
                scrollBy(deltaX, 0);  
            } else if (scrollx > back_width) {  
                scrollTo(back_width, 0);  
            } else if (scrollx < 0) {  
                scrollTo(0, 0);  
            }  
            break;  
        case MotionEvent.ACTION_UP:  
            Log.e("test", "item  ACTION_UP");  
            int scroll = getScrollX();  
            if (scroll > back_width / 2) {  
                scrollTo(back_width, 0);  
            } else {  
                scrollTo(0, 0);  
            }  
            if (Math.abs(x - downX) < 5) {// 这里根据点击距离来判断是否是itemClick  
                return false;  
            }  
            break;  
        case MotionEvent.ACTION_CANCEL:  
            scrollTo(0, 0);  
            break;  
        }  
        return true;  
    }  
  
    @Override  
    protected void onLayout(boolean changed, int l, int t, int r, int b) {  
        int margeLeft = 0;  
        int size = getChildCount();  
        for (int i = 0; i < size; i++) {  
            View view = getChildAt(i);  
            if (view.getVisibility() != View.GONE) {  
                int childWidth = view.getMeasuredWidth();  
                // 将内部子孩子横排排列  
                view.layout(margeLeft, 0, margeLeft + childWidth,  
                        view.getMeasuredHeight());  
                margeLeft += childWidth;  
            }  
        }  
    }  
}  

3、ListView的代码

package com.jwzhangjie.scrollview;  
  
import android.content.Context;  
import android.util.AttributeSet;  
import android.util.Log;  
import android.view.MotionEvent;  
import android.view.View;  
import android.widget.ListView;  
  
public class ScrollListviewDelete extends ListView {  
  
    private float minDis = 10;  
    private float mLastMotionX;// 记住上次X触摸屏的位置  
    private float mLastMotionY;// 记住上次Y触摸屏的位置  
    private boolean isLock = false;  
  
    public ScrollListviewDelete(Context context, AttributeSet attrs) {  
        super(context, attrs);  
    }  
  
    /** 
     * 如果一个ViewGroup的onInterceptTouchEvent()方法返回true,说明Touch事件被截获, 
     * 子View不再接收到Touch事件,而是转向本ViewGroup的 
     * onTouchEvent()方法处理。从Down开始,之后的Move,Up都会直接在onTouchEvent()方法中处理。 
     * 先前还在处理touch event的child view将会接收到一个 ACTION_CANCEL。 
     * 如果onInterceptTouchEvent()返回false,则事件会交给child view处理。 
     */  
    @Override  
    public boolean onInterceptTouchEvent(MotionEvent ev) {  
        if (!isIntercept(ev)) {  
            return false;  
        }  
        return super.onInterceptTouchEvent(ev);  
    }  
  
    @Override  
    public boolean dispatchTouchEvent(MotionEvent event) {  
        boolean dte = super.dispatchTouchEvent(event);  
        if (MotionEvent.ACTION_UP == event.getAction() && !dte) {//onItemClick  
            int position = pointToPosition((int)event.getX(), (int)event.getY());  
            View view = getChildAt(position);  
            super.performItemClick(view, position, view.getId());  
        }  
        return dte;  
    }  
  
    @Override  
    // 处理点击事件,如果是手势的事件则不作点击事件 普通View  
    public boolean performClick() {  
        return super.performClick();  
    }  
  
    @Override  
    // 处理点击事件,如果是手势的事件则不作点击事件 ListView  
    public boolean performItemClick(View view, int position, long id) {  
        return super.performItemClick(view, position, id);  
    }  
  
    /** 
     * 检测是ListView滑动还是item滑动 isLock 一旦判读是item滑动,则在up之前都是返回false 
     */  
    private boolean isIntercept(MotionEvent ev) {  
        float x = ev.getX();  
        float y = ev.getY();  
        int action = ev.getAction();  
        switch (action) {  
        case MotionEvent.ACTION_DOWN:  
            Log.e("test", "isIntercept  ACTION_DOWN  "+isLock);  
            mLastMotionX = x;  
            mLastMotionY = y;  
            break;  
        case MotionEvent.ACTION_MOVE:  
            Log.e("test", "isIntercept  ACTION_MOVE  "+isLock);  
            if (!isLock) {  
                float deltaX = Math.abs(mLastMotionX - x);  
                float deltay = Math.abs(mLastMotionY - y);  
                mLastMotionX = x;  
                mLastMotionY = y;  
                if (deltaX > deltay && deltaX > minDis) {  
                    isLock = true;  
                    return false;  
                }  
            } else {  
                return false;  
            }  
            break;  
        case MotionEvent.ACTION_UP:  
            Log.e("test", "isIntercept  ACTION_UP  "+isLock);  
            isLock = false;  
            break;  
        case MotionEvent.ACTION_CANCEL:  
            Log.e("test", "isIntercept  ACTION_CANCEL  "+isLock);  
            isLock = false;  
            break;  
        }  
        return true;  
    }  
  
}  


4、Activity代码

package com.jwzhangjie.scrollview;  
  
import java.util.ArrayList;  
import java.util.List;  
  
import android.os.Bundle;  
import android.support.v4.app.FragmentActivity;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.ViewGroup;  
import android.widget.AdapterView;  
import android.widget.AdapterView.OnItemClickListener;  
import android.widget.BaseAdapter;  
import android.widget.Button;  
import android.widget.TextView;  
import android.widget.Toast;  
  
public class ScrollerDeleteActivity extends FragmentActivity implements  
        OnItemClickListener {  
  
    private Toast mToast;  
    private ScrollListviewDelete listviewDelete;  
    private DeleteAdapter adapter;  
    private String[] datas = { "第一项", "第二项", "第三项", "第四项", "第五项", "第六项", "第七项",  
            "第八项", "第九项", "第十项" };  
    private List<String> listDatas = new ArrayList<String>();  
  
    @Override  
    protected void onCreate(Bundle bundle) {  
        super.onCreate(bundle);  
        setContentView(R.layout.activity_scroller_delete);  
        int len = datas.length;  
        for (int i = 0; i < len; i++) {  
            listDatas.add(datas[i]);  
        }  
        listviewDelete = (ScrollListviewDelete) findViewById(android.R.id.list);  
        adapter = new DeleteAdapter();  
        listviewDelete.setAdapter(adapter);  
        listviewDelete.setOnItemClickListener(this);  
    }  
  
    class DeleteAdapter extends BaseAdapter {  
  
        @Override  
        public int getCount() {  
            return listDatas.size();  
        }  
  
        @Override  
        public Object getItem(int position) {  
            return listDatas.get(position);  
        }  
  
        @Override  
        public long getItemId(int position) {  
            return position;  
        }  
  
        @Override  
        public View getView(final int position, View convertView,  
                ViewGroup parent) {  
            ViewHolder holder;  
            if (convertView == null) {  
                holder = new ViewHolder();  
                convertView = LayoutInflater.from(getApplicationContext())  
                        .inflate(R.layout.item_delete, null);  
                holder.itemData = (TextView) convertView  
                        .findViewById(R.id.itemData);  
                holder.btnDelete = (Button) convertView  
                        .findViewById(R.id.btnDelete);  
                holder.btnNao = (Button) convertView.findViewById(R.id.btnNao);  
                convertView.setTag(holder);  
            } else {  
                holder = (ViewHolder) convertView.getTag();  
            }  
            holder.btnDelete.setOnClickListener(new OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    showInfo("点击删除了");  
                }  
            });  
            holder.itemData.setOnClickListener(new OnClickListener() {  
  
                @Override  
                public void onClick(View v) {  
                    showInfo("点击了数据: " + listDatas.get(position));  
                }  
            });  
            holder.btnNao.setOnClickListener(new OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    showInfo("点击了闹铃");  
                }  
            });  
            holder.itemData.setText(listDatas.get(position));  
            return convertView;  
        }  
  
        class ViewHolder {  
            TextView itemData;  
            Button btnDelete;  
            Button btnNao;  
        }  
    }  
  
    @Override  
    public void onItemClick(AdapterView<?> parent, View view, int position,  
            long id) {  
        showInfo("onItemClick : " + position);  
    }  
  
    public void showInfo(String text) {  
        if (mToast == null) {  
            mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT);  
        } else {  
            mToast.setText(text);  
            mToast.setDuration(Toast.LENGTH_SHORT);  
        }  
        mToast.show();  
    }  
  
}  

5、XML代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical" >  
  
    <com.jwzhangjie.scrollview.ScrollListviewDelete  
        android:id="@android:id/list"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent" />  
  
</LinearLayout>

<com.jwzhangjie.scrollview.ListItemDelete 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/front"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:background="@drawable/bg_item_list_8"  
        android:gravity="center"  
        android:orientation="horizontal" >  
  
        <TextView  
            android:id="@+id/itemData"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:text="测试数据" />  
    </LinearLayout>  
  
    <LinearLayout  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:gravity="center"  
        android:orientation="horizontal" >  
  
        <Button  
            android:id="@+id/btnNao"  
            android:layout_width="wrap_content"  
            android:layout_height="match_parent"  
            android:background="@drawable/bg_item_list_4"  
            android:text="闹铃" />  
  
        <Button  
            android:id="@+id/btnDelete"  
            android:layout_width="wrap_content"  
            android:layout_height="match_parent"  
            android:background="@drawable/bg_item_list_5"  
            android:text="删除" />  
    </LinearLayout>  
  
</com.jwzhangjie.scrollview.ListItemDelete>

6、界面效果


不保证上面的代码是最新的,更新代码地址:https://github.com/jwzhangjie/-ScrollerDelete


V1.0版本:解决提供修改数据多时,item滑动底部数据重复,解决方案:判断是否有滑动的item,如果有则复位

地址:https://github.com/jwzhangjie/-ScrollerDelete  里面有编译好的apk




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值