【问题标题】:Pass click event through the view android通过视图android传递点击事件
【发布时间】:2018-12-28 16:45:21
【问题描述】:

我有框架布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="10dp" >

<LinearLayout
    android:id="@+id/widgetView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:layout_margin="10dp"
    android:gravity="center" >
</LinearLayout>

<LinearLayout
    android:id="@+id/widgetOverlayFrame"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="false" >
</LinearLayout>

第一个布局包含小部件布局,第二个布局是透明的,并接收 onLongClick 用于拖动方法。这有效,问题是当我想与小部件交互时,单击某物时,overlayFrame 会执行单击事件。如何通过overlayFrame将点击事件传递给widgetView?

编辑:

现在我正在尝试将 GestureLister 附加到 overlayFrame LinearLayout,以某种方式查看代表单击和长按的 MotionEvent 之间的区别。我面临的问题是手势监听器中的 OnLongPress 总是被称为无论我做什么,单击或长按。

对这种行为有解释吗?天呐!

【问题讨论】:

    标签: android click


    【解决方案1】:

    在我的例子中,我在视图的 layoutParams 中添加了标志,它应该在下面传递了一个触摸事件:

    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
    

    这种方式视图将忽略所有触摸(例如可见性消失的视图)

    【讨论】:

      【解决方案2】:

      您可以通过这种方式覆盖 onTouchListener,而不是使用 GestureListener。

      这将在计时器用完时调用 longPress,如果在两者之间出现 up 将取消 LongPress

         CountDownTimer c;
          long time=5000;
          @Override
          public boolean onTouchEvent(MotionEvent ev) {
              switch (ev.getAction()) {
                  case MotionEvent.ACTION_DOWN:
                      c= new CountDownTimer(5000, 1000) {
                                public void onTick(long millisUntilFinished) {
                                        time=millisUntilFinished;
                                 }
      
                                public void onFinish() {
                                       Log.i("","LONG PRESS");
                                 }}.start();
      
                  break;
                  case MotionEvent.ACTION_UP:
                      if (time>0) {
                          Log.i("example","short click");
                          c.cancel();
                      }
                  break;
              }
      
              return true;
          }
      

      【讨论】:

      • 好的,这可以完美地检测...我现在如何将点击传递到下面的图层?
      【解决方案3】:

      也许设置覆盖的属性android:focusable="false"android:focusableInTouchMode="false" 就足够了。

      您还可以制作自己的叠加小部件并覆盖其onInterceptTouchEvent 方法以始终返回false。

      public class NotTouchableLinearLayout extends LinearLayout {
      
          // Override constructors
          // ...
      
         @Override
          public boolean onInterceptTouchEvent(MotionEvent ev) {
              return false;
          }
      }
      

      【讨论】:

      • 尝试覆盖 onTouch 而不是 onInterceptTouchEvent。
      • 呵呵,我已经这样做了,但是现在没有调用overlayLayout上的onLongClick。而且我不能拖动项目。
      • 如何在 onTouch 中点击和长按?
      • 我无法完成这项工作。你可以说得更详细点吗。也没有被接受的答案。
      【解决方案4】:

      您应该创建自己的扩展LinearLayout 的类并覆盖它的onTouchEvent 方法,而不是在顶部布局上设置GestureListener。 在那里你可以实现长点击\短点击等的逻辑。

      点击事件将首先被发送到小部件布局,并且只有当它不处理它们时(因此它是onTouchEvent 返回false),您才会在顶部布局中获得它们。

      编辑:

      <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_margin="10dp" >
      
      <LinearLayout
      android:id="@+id/widgetView"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_gravity="center"
      android:layout_margin="10dp"
      android:gravity="center" >
      </LinearLayout>
      
      <com.example.touchtesting.MyLinearLayout
      android:id="@+id/widgetOverlayFrame"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:clickable="false" >
      </com.example.touchtesting.MyLinearLayout>
      
      </FrameLayout>
      

      com.example.touchtesting 更改为您的包的名称。 这是课程:

              public class MyLinearLayout extends LinearLayout{
      
              public MyLinearLayout(Context context, AttributeSet attrs) {
                  super(context, attrs);
              }
      
              private long startClick = 0;
      
              @Override
              public boolean onTouchEvent(MotionEvent ev) {
                  switch (ev.getAction()) {
                      case MotionEvent.ACTION_DOWN:
                          startClick = ev.getEventTime();
                          break;
                      case MotionEvent.ACTION_CANCEL:
                      case MotionEvent.ACTION_UP:
                          if (ev.getEventTime() - startClick < 500) {
                              Log.i("example","short click");
                          }
                          else {
                              Log.i("example","long click");
                          }
                          break;
                  }
      
                  return true;
              }
      
          }
      

      【讨论】:

      • 我现在就试试 ;) tnx...这是有道理的...希望这行得通...我已经为此浪费了一天时间。
      • 小部件层没有得到短按...:/检测工作正常,我在短按时返回 false,但小部件保持静止并且对该操作没有反应。
      • 还有一件事...我需要检测长按Action Down...我正在开发自定义启动器...你知道小部件是如何在屏幕上移动的吗? OnLong 点击开始拖动...
      • 我已经这样做了...如果我不这样做,我的应用程序将崩溃...它正在运行...但是小部件不会拦截点击事件...
      【解决方案5】:

      要让长点击通过widgetView LinearLayout添加android:longClickable="true"。 (普通点击加android:clickable="true"

      所以 widgetView 变成了:

      <LinearLayout
          android:id="@+id/widgetView"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_gravity="center"
          android:layout_margin="10dp"
          android:gravity="center" 
          android:longClickable="true">
      </LinearLayout>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-08
        • 1970-01-01
        • 1970-01-01
        • 2011-07-21
        相关资源
        最近更新 更多