1112滑动解析

今天解决了困惑已久的滑动删除事件
话不多说直接上源码



/**
 * Created by Administrator on 2015/11/10.
 */
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);
    }
/**computeScroll:主要功能是计算拖动的位移量、更新背景、设置要显示的
在view的滑动中会调用他的computeScroll()来进行计算,这里我们重写这个方法并不断重绘,配合Scroller就可以实现屏幕的监听并滑动*/
    @Override
    public void computeScroll() {
    // 会更新Scroller中的当前x,y位置/根据当前已经消逝的时间计算当前的坐标点,保存在mCurrX和mCurrY值中
        if (mScroller.computeScrollOffset()) {
            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);//左移是mLast比较大,所以是正的
                mLastMotionX = x;
                int scrollx = getScrollX() + deltaX;/**getScrollX获得的是当前点击的坐标点,相对于整个view(包括不可见部分)*/
                if (scrollx > 0 && scrollx < back_width) {
                    scrollBy(deltaX, 0);
                } else if (scrollx > back_width) {
                    scrollTo(back_width, 0);//这里是直接把隐藏view推到可视界面中
                } else if (scrollx < 0) {
                    scrollTo(0, 0);
                }
                break;
            case MotionEvent.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;
            }
        }
    }
}

scrollTo(int x, int y)是指移动到view的(x,y)上
scrollBy(int x,int y)是在当前基础上移动x,y;实质上这个方法内部就是scrollTo(getScrollX()+x,getScrollY()+y);
其实主要就是这个类,扩展了LinearLayout的点击事件
这个对象直接拿来用,但是要注意ListItemDelete第一个子view得设置match_parent,他就是靠着这个参数把剩下的view挤出去的,而且只能滑动显示第二个子view,要显示更多得改一下那个onMearsure()

原作者(很抱歉我用的时候没有注意作者,忘了他是谁= =知道的麻烦告诉我,我加个引用)还加了一个判断用的Listview,来装这个ListItemDelete,但是进过实验,普通的Listview就可以达到需求了;
但是还是贴出来,增加见识

/**
 * Created by Administrator on 2015/11/10.
 */
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;
    }

}

android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:

1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent

2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent

3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent

当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由 dispatchTouchEvent 方法进行分发,如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。如果事件传递到某一层的子 view 的 onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的校园二手书交易平台,源码+数据库+毕业论文+视频演示 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的校园二手书交易平台实现了图书信息查询。系统用到了关系型数据库中MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让校园二手书交易平台更能从理念走到现实,确确实实的让人们提升信息处理效率。 关键字:信息管理,时效性,安全性,MySql;Spring Boot
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值