当起始滑动点位于可点击视图上时,如何允许滑动视图?

问题描述

我正在尝试将滑动功能与布局上的可点击视图结合起来。 我通过遵循 https://github.com/romannurik/Android-SwipeToDismiss

中的库实现来实现 SwipedismisstouchListener

现在我有这个布局(如下),我可以向右或向左滑动它,但我注意到如果我的滑动起点在任何可点击的对象上,如(此处)TextView,我无法滑动整个视图。

enter image description here

我不知道如何才能同时做到:

  1. 当我滑动时 -> 当我的滑动起点在任何可点击对象上时向右滑动
  2. 当我点击 -> 点击 TextView

这是我的代码MainActivity

public class MainActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewGroup parent = findViewById(R.id.parent);
        ViewGroup container = findViewById(R.id.container);

        TextView text1 = findViewById(R.id.text1);
        text1.setonClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(),"Clicked on text1",Toast.LENGTH_SHORT).show();
            }
        });

        container.setClickable(true);
        container.setFocusable(false);
        container.setonTouchListener(
                new SwipedismisstouchListener(parent,new SwipedismisstouchListener.dismissCallbacks() {
                            @Override
                            public boolean candismiss() {
                                return true;
                            }

                            @Override
                            public void ondismiss(View view) {
                                parent.removeView(container);
                            }
                        }));
    }
}

SwipedismisstouchListener

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.view.MotionEvent;
import android.view.VeLocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;

public class SwipedismisstouchListener implements View.OnTouchListener {

    // Cached ViewConfiguration and system-wide constant values
    private int mSlop;
    private int mMinFlingVeLocity;
    private int mMaxFlingVeLocity;
    private long mAnimationTime;

    // Fixed properties
    private View mView;
    private dismissCallbacks mCallbacks;
    private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero

    // Transient properties
    private float mDownX;
    private float mDownY;
    private boolean mSwiping;
    private int mSwipingSlop;
    private VeLocityTracker mVeLocityTracker;
    private float mTranslationX;

    public interface dismissCallbacks {
        boolean candismiss();

        void ondismiss(View view);
    }

    public SwipedismisstouchListener(View view,dismissCallbacks callbacks) {
        ViewConfiguration vc = ViewConfiguration.get(view.getContext());
        mSlop = vc.getScaledTouchSlop();
        mMinFlingVeLocity = vc.getScaledMinimumFlingVeLocity() * 16;
        mMaxFlingVeLocity = vc.getScaledMaximumFlingVeLocity();
        mAnimationTime = view.getContext().getResources().getInteger(
                android.R.integer.config_shortAnimTime);
        mView = view;
        mCallbacks = callbacks;
    }

    @Override
    public boolean onTouch(View view,MotionEvent motionEvent) {

        // offset because the view is translated during swipe
        motionEvent.offsetLocation(mTranslationX,0);

        // not sure what it is
        if (mViewWidth < 2) {
            mViewWidth = mView.getWidth();
        }

        switch (motionEvent.getActionMasked()) {
            case MotionEvent.ACTION_DOWN: {
                mDownX = motionEvent.getRawX();
                mDownY = motionEvent.getRawY();

                if (mCallbacks.candismiss()) {
                    mVeLocityTracker = VeLocityTracker.obtain();
                    mVeLocityTracker.addMovement(motionEvent);
                }

                return false;
            }

            case MotionEvent.ACTION_UP: {
                if (mVeLocityTracker == null) {
                    break;
                }

                float deltaX = motionEvent.getRawX() - mDownX;
                mVeLocityTracker.addMovement(motionEvent);
                mVeLocityTracker.computeCurrentVeLocity(1000);
                float veLocityX = mVeLocityTracker.getXVeLocity();
                float absveLocityX = Math.abs(veLocityX);
                float absveLocityY = Math.abs(mVeLocityTracker.getYVeLocity());
                boolean dismiss = false;
                boolean dismissRight = false;
                if (Math.abs(deltaX) > mViewWidth / 2 && mSwiping) {
                    dismiss = true;
                    dismissRight = deltaX > 0;
                } else if (mMinFlingVeLocity <= absveLocityX && absveLocityX <= mMaxFlingVeLocity
                        && absveLocityY < absveLocityX
                        && absveLocityY < absveLocityX && mSwiping) {
                    // dismiss only if flinging in the same direction as dragging
                    dismiss = (veLocityX < 0) == (deltaX < 0);
                    dismissRight = mVeLocityTracker.getXVeLocity() > 0;
                }
                if (dismiss) {
                    // dismiss
                    mView.animate()
                            .translationX(dismissRight ? mViewWidth : -mViewWidth)
                            .alpha(0)
                            .setDuration(mAnimationTime)
                            .setListener(new AnimatorListenerAdapter() {
                                @Override
                                public void onAnimationEnd(Animator animation) {
                                    performdismiss();
                                }
                            });
                } else if (mSwiping) {
                    // cancel
                    mView.animate()
                            .translationX(0)
                            .alpha(1)
                            .setDuration(mAnimationTime)
                            .setListener(null);
                }

                mVeLocityTracker.recycle();
                mVeLocityTracker = null;
                mTranslationX = 0;
                mDownX = 0;
                mDownY = 0;
                mSwiping = false;
                break;
            }

            case MotionEvent.ACTION_CANCEL: {
                if (mVeLocityTracker == null) {
                    break;
                }

                mView.animate()
                        .translationX(0)
                        .alpha(1)
                        .setDuration(mAnimationTime)
                        .setListener(null);
                mVeLocityTracker.recycle();
                mVeLocityTracker = null;
                mTranslationX = 0;
                mDownX = 0;
                mDownY = 0;
                mSwiping = false;
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                if (mVeLocityTracker == null) {
                    break;
                }

                mVeLocityTracker.addMovement(motionEvent);
                float deltaX = motionEvent.getRawX() - mDownX;
                float deltaY = motionEvent.getRawY() - mDownY;
                if (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < Math.abs(deltaX) / 2) {
                    mSwiping = true;
                    mSwipingSlop = (deltaX > 0 ? mSlop : -mSlop);
                    view.getParent().requestdisallowInterceptTouchEvent(true);

                    // Cancel listview's touch
                    MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
                    cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
                            (motionEvent.getActionIndex() <<
                                    MotionEvent.ACTION_POINTER_INDEX_SHIFT));
                    view.onTouchEvent(cancelEvent);
                    cancelEvent.recycle();
                }

                if (mSwiping) {
                    mTranslationX = deltaX;
                    mView.setTranslationX(deltaX - mSwipingSlop);
                    // Todo: use an ease-out interpolator or such
                    mView.setAlpha(Math.max(0f,Math.min(1f,1f - 2f * Math.abs(deltaX) / mViewWidth)));
                    return true;
                }
                break;
            }
        }
        return false;
    }

    private void performdismiss() {

        final ViewGroup.LayoutParams lp = mView.getLayoutParams();
        final int originalHeight = mView.getHeight();

        ValueAnimator animator = ValueAnimator.ofInt(originalHeight,1).setDuration(mAnimationTime);

        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mCallbacks.ondismiss(mView);
                // Reset view presentation
                mView.setAlpha(1f);
                mView.setTranslationX(0);
                lp.height = originalHeight;
                mView.setLayoutParams(lp);
            }
        });

        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                lp.height = (Integer) valueAnimator.getAnimatedValue();
                mView.setLayoutParams(lp);
            }
        });

        animator.start();
    }
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:background="#7CB342"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:id="@+id/text1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="16dp"
                android:background="#AEEA00"
                android:gravity="center"
                android:text="Test"
                android:textStyle="bold" />

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

解决方法

阅读 onInterceptTouchEvent() 的文档:https://developer.android.com/training/gestures/viewgroup#intercept

提供的代码片段应涵盖您的确切用例。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...