MotionLayout prevents ClickListener on all Views

后端 未结 3 2022
自闭症患者
自闭症患者 2021-01-21 20:46

I am using a MotionLayout with a scene-xml:


    <         


        
相关标签:
3条回答
  • 2021-01-21 21:36

    To setup onClick action on the view, use:

    android:onClick="handleAction"
    

    inside the MotionLayout file, and define "handleAction" in your class.

    0 讨论(0)
  • 2021-01-21 21:41

    @muetzenflo's response is the most efficient solution I've seen so far for this problem.

    However, only checking the Event.Action for MotionEvent.ACTION_MOVE causes the MotionLayout to respond poorly. It is better to differentiate between movement and a single click by the use of ViewConfiguration.TapTimeout as the example below demonstrates.

    public class MotionSubLayout extends MotionLayout {
    
        private long mStartTime = 0;
    
        public MotionSubLayout(@NonNull Context context) {
            super(context);
        }
    
        public MotionSubLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MotionSubLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
            if ( event.getAction() == MotionEvent.ACTION_DOWN ) {
                mStartTime = event.getEventTime();
            } else if ( event.getAction() == MotionEvent.ACTION_UP ) {
                if ( event.getEventTime() - mStartTime <= ViewConfiguration.getTapTimeout() ) {
                    return false;
                }
            }
    
            return super.onInterceptTouchEvent(event);
        }
    }
    
    0 讨论(0)
  • 2021-01-21 21:42

    With the help of this great medium article I figured out that MotionLayout is intercepting click events even though the motion scene only contains an OnSwipe transition.

    So I wrote a customized MotionLayout to only handle ACTION_MOVE and pass all other touch events down the View tree. Works like a charm:

    /**
     * MotionLayout will intercept all touch events and take control over them.
     * That means that View on top of MotionLayout (i.e. children of MotionLayout) will not
     * receive touch events.
     *
     * If the motion scene uses only a onSwipe transition, all click events are intercepted nevertheless.
     * This is why we override onInterceptTouchEvent in this class and only let swipe actions be handled
     * by MotionLayout. All other actions are passed down the View tree so that possible ClickListener can
     * receive the touch/click events.
     */
    class ClickableMotionLayout: MotionLayout {
    
        constructor(context: Context) : super(context)
    
        constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    
        constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    
        override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
            if (event?.action == MotionEvent.ACTION_MOVE) {
                return super.onInterceptTouchEvent(event)
            }
            return false
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题