美文网首页安卓开发博客
可拖拽的view 与 viewpager 一起使用时的尴尬

可拖拽的view 与 viewpager 一起使用时的尴尬

作者: 靛蓝小孩 | 来源:发表于2018-06-28 14:38 被阅读43次

    (1):可拖拽的view 的实现:(实现一)

    package com.mishou.health.widget;
    import android.app.Activity;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import com.mishou.common.utils.PhoneUtils;

    public class DragImageView extends View {
    private int x, y;
    private int mTabHeight;
    
    private int mScreenWidth, mScreenHeight;
    private Context mContext;
    
    public DragImageView(Context context) {
        super(context);
        this.mContext = context;
    
        initScreenParams();
    }
    
    public DragImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
    
        initScreenParams();
    }
    
    public DragImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
    
        initScreenParams();
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 记录触摸点坐标
                x = (int) event.getRawX();// 获取触摸事件触摸位置的原始X坐标
                y = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                mTabHeight = getTabHeight();
                //计算偏移量
                int dx = (int) event.getRawX() - x;
                int dy = (int) event.getRawY() - y;
                int l = getLeft() + dx;
                int b = getBottom() + dy;
                int r = getRight() + dx;
                int t = getTop() + dy;
                // 下面判断移动是否超出屏幕
                if (l < 0) {
                    l = 0;
                    r = l + getWidth();
                }
                if (t < 0) {
                    t = 0;
                    b = t + getHeight();
                }
                if (r > mScreenWidth) {
                    r = mScreenWidth;
                    l = r - getWidth();
                }
                if (b > mScreenHeight - mTabHeight) {
                    b = mScreenHeight - mTabHeight;
                    t = b - getHeight();
                }
                layout(l, t, r, b);
                x = (int) event.getRawX();
                y = (int) event.getRawY();
                postInvalidate();
                break;
        }
        return true;
    }
    
    private void initScreenParams() {
        mScreenWidth = PhoneUtils.getScreenWidth(mContext);
        mScreenHeight = PhoneUtils.getScreenHeight(mContext);
    }
    
    private int getTabHeight() {       
        return 90;
    }}
    

    问题:点击事件就无法触发

    (2):可拖拽view 的实现二

    package com.mishou.health.widget;
    import android.app.Activity;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewConfiguration;
    import com.mishou.common.utils.PhoneUtils;

    public class DragImageView extends View {
    private static final String TAG = "DragImageView";
    private int mTabHeight;
    private boolean mMove = false;
    private int mSlop;
    
    private int mScreenWidth, mScreenHeight;
    private Context mContext;
    
    public DragImageView(Context context) {
        super(context);
        this.mContext = context;
    
        initScreenParams();
    }
    
    public DragImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
    
        initScreenParams();
    }
    
    public DragImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
    
        initScreenParams();
    }
    
    private void initScreenParams() {
    
        mSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
        mScreenWidth = PhoneUtils.getScreenWidth(mContext);
        mScreenHeight = PhoneUtils.getScreenHeight(mContext);
    }
    
    private boolean hasTouchFloatBall = false;
    
    private float mLastX;
    private float mLastY;
    
    private boolean isIntercepted = false;
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        int action = event.getActionMasked();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mLastX = event.getRawX();
                mLastY = event.getRawY();
                if (onTouchEvent(event)) {
                    hasTouchFloatBall = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = (int) ((int) event.getRawX() - mLastX);
                int deltaY = (int) ((int) event.getRawY() - mLastY);
                if (!isIntercepted) {
                    if (Math.abs(deltaX) > mSlop || Math.abs(deltaY) > mSlop) {
                        sendCancelEvent(event);
                        isIntercepted = true;
                    } else {
                        return super.dispatchTouchEvent(event);
                    }
                }
                if (hasTouchFloatBall) {
                    mTabHeight = getTabHeight();
                    //计算偏移量
    
                    int l = getLeft() + deltaX;
                    int b = getBottom() + deltaY;
                    int r = getRight() + deltaX;
                    int t = getTop() + deltaY;
                    // 下面判断移动是否超出屏幕
                    if (l < 0) {
                        l = 0;
                        r = l + getWidth();
                    }
                    if (t < 0) {
                        t = 0;
                        b = t + getHeight();
                    }
                    if (r > mScreenWidth) {
                        r = mScreenWidth;
                        l = r - getWidth();
                    }
                    if (b > mScreenHeight - 2 * mTabHeight) {
                        b = mScreenHeight - 2 * mTabHeight;
                        t = b - getHeight();
                    }
                    layout(l, t, r, b);
                    mLastX = (int) event.getRawX();
                    mLastY = (int) event.getRawY();
                    postInvalidate();
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                hasTouchFloatBall = false;
                isIntercepted = false;
                break;
            default:
                break;
        }
        return super.dispatchTouchEvent(event);
    }
    
    private void sendCancelEvent(MotionEvent lastEvent) {
        MotionEvent last = lastEvent;
        MotionEvent e = MotionEvent.obtain(
                last.getDownTime(),
                last.getEventTime()
                        + ViewConfiguration.getLongPressTimeout(),
                MotionEvent.ACTION_CANCEL, last.getX(), last.getY(),
                last.getMetaState());
        super.dispatchTouchEvent(e);
    }
    private int getTabHeight() {     
        return 90;
    }}
    

    问题:可拖拽,可点击,但是,在viewpager 切换页面的时候,会调用requestlayout,导致view回到了初始的view 位置,熟悉的朋友会知道,这个方法强制刷新UI 的经过,这里不多做说明。

    (3):可拖拽view 的实现三:既然知道了重置到初始位置的问题,如果去更改viewpager 的实现,不仅困难,而是非常困难,有可能会多出更多的问题,为此,可拖拽的view 的实现,我们可以换种方法,利用属性动画,这里就是属性动画的特点,使得它可以解决这里的问题,实现如下:

    package com.mishou.health.widget;
    import android.app.Activity;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewConfiguration;
    import com.mishou.common.utils.PhoneUtils;

    public class DragImageView extends View {
    private static final String TAG = "DragImageView";
    private int mTabHeight;
    private boolean mMove = false;
    private int mSlop;
    
    private int mScreenWidth, mScreenHeight;
    private Context mContext;
    
    public DragImageView(Context context) {
        super(context);
        this.mContext = context;
    
        initScreenParams();
    }
    
    public DragImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
    
        initScreenParams();
    }
    
    public DragImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
    
        initScreenParams();
    }
    
    private void initScreenParams() {
    
        mSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
        mScreenWidth = PhoneUtils.getScreenWidth(mContext);
        mScreenHeight = PhoneUtils.getScreenHeight(mContext);
    }
    
    private boolean hasTouchFloatBall = false;
    
    private float mLastX;
    private float mLastY;
    
    private boolean isIntercepted = false;
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        int action = event.getActionMasked();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mLastX = event.getRawX();
                mLastY = event.getRawY();
                if (onTouchEvent(event)) {
                    hasTouchFloatBall = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = (int) ((int) event.getRawX() - mLastX);
                int deltaY = (int) ((int) event.getRawY() - mLastY);
                if (!isIntercepted) {
                    if (Math.abs(deltaX) > mSlop || Math.abs(deltaY) > mSlop) {
                        sendCancelEvent(event);
                        isIntercepted = true;
                    } else {
                        return super.dispatchTouchEvent(event);
                    }
                }
                if (hasTouchFloatBall) {
                    mTabHeight = getTabHeight();
                    //计算偏移量
    
                    int l = getLeft() + deltaX;
                    int b = getBottom() + deltaY;
                    int r = getRight() + deltaX;
                    int t = getTop() + deltaY;
                    // 下面判断移动是否超出屏幕
                    if (l < 0) {
                        l = 0;
                        r = l + getWidth();
                    }
                    if (t < 0) {
                        t = 0;
                        b = t + getHeight();
                    }
                    if (r > mScreenWidth) {
                        r = mScreenWidth;
                        l = r - getWidth();
                    }
                    if (b > mScreenHeight - 2 * mTabHeight) {
                        b = mScreenHeight - 2 * mTabHeight;
                        t = b - getHeight();
                    }
                    layout(l, t, r, b);
                    mLastX = (int) event.getRawX();
                    mLastY = (int) event.getRawY();
                    postInvalidate();
    
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                hasTouchFloatBall = false;
                isIntercepted = false;
                break;
            default:
                break;
        }
        return super.dispatchTouchEvent(event);
    }
    
    private void sendCancelEvent(MotionEvent lastEvent) {
        MotionEvent last = lastEvent;
        MotionEvent e = MotionEvent.obtain(
                last.getDownTime(),
                last.getEventTime()
                        + ViewConfiguration.getLongPressTimeout(),
                MotionEvent.ACTION_CANCEL, last.getX(), last.getY(),
                last.getMetaState());
        super.dispatchTouchEvent(e);
    }
    
    private int getTabHeight() {
        return 90;
    }}
    

    总结:这样就完美的实现当前页面即有viewpager ,也有拖拽的view 的控件。

    相关文章

      网友评论

        本文标题:可拖拽的view 与 viewpager 一起使用时的尴尬

        本文链接:https://www.haomeiwen.com/subject/vmpgyftx.html