SwipeDismissBehavior 未在以编程方式添加的协调器布局的子项中触发

SwipeDismissBehavior not triggered in Child of programmatically added Coordinator Layout

我有以下视图层次结构:

所以假设我有以下内容:

我以编程方式将我的 MyCoordinatorLayout 膨胀为 LinearLayout 的子项。所以在某个地方发生了这种情况:

linearLayout.addView(myCoordinatorLayout, ..., ...);

现在我有以下代码:

public class MyCoordinatorLayout extends CoordinatorLayout{
   public void inflate() {
       LayoutInflater.from(getContext()).inflate(R.layout.merge_header_custom_layout, this, true);
       WebView newWebView = new WebView(getContext());
       addView(newWebView, 0, new ViewGroup.LayoutParams.MATCH_PARENT, MATCH_PARENT);
   }

}

public class MyCustomLayout extends LinearLayout{
     @Override
     public void onAttachedToWindow() {
         Log.v(TAG, "onAttachedToWindow() called, now adding swipe behavior"); //This is called as expected!
         addSwipeBehavior();
     }

     private void addSwipeBehavior() {
        final SwipeDismissBehavior<View> swipe = new SwipeDismissBehavior<View>();
        swipe.setSwipeDirection(SWIPE_DIRECTION_ANY);
        swipe.setListener(new SwipeDismissBehavior.OnDismissListener() {
           @Override
           public void onDismiss(View view) {
              Log.v(TAG, "onDismiss called!");
           }
           @Override
           public void onDragStateChanged(int i) {
               Log.v(TAG, "onDragStateChanged()");
           }
        }
        CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) get LayoutParams();
        params.setBehavior(swipe);
        Log.v(TAG, "behavior=" + params.getBehavior); //This shows its set.
     }
}

问题来了。滑动关闭根本不起作用。事实上,我添加的那些日志语句从未被打印出来。是否可能是因为我的 CoordinatorLayout 是以编程方式添加的,而不是像我看到的示例那样预先存在于 XML 中?

我真的希望我的行为能够奏效,但就是没有被触发。另外,我检查了 MyCustomLayout 并看到它的 onTouchEvent(MotionEvent e) 被触发了……但是,该行为仍然没有被触发。我还做了一个 getLayoutParams()getBehavior() 并且它 returns 是正确的行为所以我知道 CoordinatorLayout 有正确的行为,但行为根本不只是工作......不确定如果我错过了什么!如果能得到一些帮助或为我指明正确的方向,那就太好了!

我认为第一个问题是 SwipeDismissBehavior 需要与可滑动视图相关联,以及与您想要滑动以关闭的方式相关联的行为,例如,左右滑动 behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_START_TO_END); 然后适当地传播触摸,或者如果在 RecyclerView 中使用类似 ItemTouchHelper.

的东西

这个 SO post 在解释如何正确设置滑动以关闭方面做得更好:How to use SwipeDismissBehavior.OnDismissListener on RecyclerView

希望对您有所帮助。

我能够弄清楚为什么我与 SwipeDismissBehavior 的触摸交互从未被调用过。原因很简单。在我的图表中,我忘记了视图层次结构的顶部和线性布局顶部是一个视图寻呼机。让我重新画图。

实际发生的事情是 ViewPager 拦截了我的触摸并且从不让它到达子布局。有一个修复。我需要做的是:

public class MySwipeDismissBehavior extends SwipeDismissBehavior<View> {
     private float mLastX; 

     @Override
     public boolean onInterceptTouchEvent(CoordinatorLayout parent, FrameLayout child, MotionEvent event) {
         if (parent.isPountInChildBounds(child, event.getX(), event.getY())) {
             ViewPager vp = findViewPager(child);
             switch(event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
                     disableViewPager(vp, true);
                     break;
                 case MotionEvent.ACTION_MOVE:
                     boolean swipingLeftToRight = (x-mLastX) > 0; //Allow the view pager to handle it if I swiping from left to right.
                     if (swipingLeftToRight) {
                         disableViewPager(vp, false);
                     } else { // if swiping from right to left, let the swipe dismiss behavior handle it.
                         disableViewPager(vp, true);
                     }
                     break;
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL: //As soon as it 
                     disableViewPager(vp, true);
                     break;

             }
         }

     }

     private void disableViewPager(ViewPager vp, boolean enable) {
         if (vp != null) {
            vp.requestDisallowInterceptTouchEvent(enable)
         }
     }

     private ViewPager findViewPager(View child) {
          ViewPager parent = child.getParent();
          while (parent != null) {
               parent = child.getParent();
               if (parent instanceof ViewPager) {
                   return (ViewPager) parent;
               } else if(!(parent instanceof View)) {
                   return null;
               } else {
                   child = (View) parent;
               }

          }
          return null;

     }
}

在我将这个新行为添加到我的代码后,我的滑动关闭行为起作用了。我希望这对其他人有帮助。我从这里获得了解决方案的帮助和灵感:。这不是完全相同的问题,但它为我指明了正确的方向