【问题标题】:How to pass a view's onClick event to its parent on Android?如何将视图的 onClick 事件传递给 Android 上的父级?
【发布时间】:2010-12-11 06:29:40
【问题描述】:

我的布局中有一个 TextView,其背景是一个选择器。并且 TextView 的文本设置为从 HTML 跨越。 然后我用 LinkMovementMethod 设置 TextView。

现在当我点击 TextView 时,点击事件不会发送到其父布局以触发选择器。

应该如何解决?

【问题讨论】:

    标签: android events onclick textview


    【解决方案1】:

    使用android:clickable="false"android:focusable="false"v.setClickable(false)v.setFocusable(false) 声明您的TextView 不可点击/不可聚焦。现在应该将点击事件分派给TextView 的父级。

    注意:

    为了实现这一点,您必须将点击添加到其直接parent。或设置 android:clickable="false"android:focusable="false" 到其直接父级将侦听器传递给进一步的父级

    【讨论】:

    • 天哪,如果我能给这个+100,我会的。一直试图弄清楚如何使单击仅在 ViewPager 中起作用,而不在使用实现 onTouch 的 TouchImageView 的适配器布局中起作用!这个解决方案就像一个魅力。
    • 但是如果我想处理 EditText 的焦点更改事件呢?
    • 场景是:我有一个包含编辑文本、相对布局、微调器和列表视图的布局。每当我触摸屏幕上除编辑文本和微调器之外的任何位置时,我都想触发父布局的触摸事件
    • 需要牢记的重要一点是,如果您在 TextView 上使用 TextView#setOnClickListener(),即使它被声明为 android:clickable="false",即使 ClickListener 是设置为null (setOnclickListener(null))
    • 有趣的事实:如果在 TextView 中有一个 android:inputType 属性,即使使用 clickable: false & focusable: false; 它也会默默地消耗点击事件。在我的情况下,它被设置为一种风格,我花了 30 分钟来找出原因。
    【解决方案2】:

    我认为您需要使用其中一种方法才能在事件被发送到适当的组件之前拦截它:

    Activity.dispatchTouchEvent(MotionEvent) - 这允许您的 Activity 在将所有触摸事件分派到窗口之前拦截它们。

    ViewGroup.onInterceptTouchEvent(MotionEvent) - 这允许 ViewGroup 在事件被分派到子视图时观察它们。

    ViewParent.requestDisallowInterceptTouchEvent(boolean) - 在父视图上调用它以指示它不应使用 onInterceptTouchEvent(MotionEvent) 拦截触摸事件。

    更多信息here

    希望对您有所帮助。

    【讨论】:

    • 是否有更简单的方法来传递事件以在父视图中触发 onClick 和 onLongClick,或者我必须自己实现它们?
    • 检查一下:stackoverflow.com/questions/2136696/pass-event-to-parent-view 可能您可能想尝试按照建议将相同的点击侦听器传递给其他实例,即使我不知道它是否会起作用,但可能值得一试试试看。
    • 下面的答案更简洁
    • 我应该实例化 MotionEvent 吗?请解释一下,@LuisMiguelSerrano
    • @olegario,通常您重新定义例如 dispatchTouchEvent 的方法,使用 @Override 为其定义新的行为,因此您只需接收系统提供给您的活动(或另一个您的应用程序的组件),并且您根据自己的规则对其进行处理和/或转发给任意数量的子组件。比如:@Override public boolean dispatchTouchEvent(MotionEvent ev) { ... }
    【解决方案3】:

    有时只有这有帮助:

    View child = parent.findViewById(R.id.btnMoreText);
        child.setOnClickListener(new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                View parent = (View) v.getParent();
                parent.performClick();
            }
        });
    

    另一种变体,并不总是有效:

    child.setOnClickListener(null);
    

    【讨论】:

    • 这适用于CardView 作为子视图,因为CardView 似乎忽略了clickable="false"focusable="false"。但是,使用setOnTouchListener 并在父级上调用onTouchEvent 反而允许父级显示触摸反馈(例如波纹效果)。
    • 我在下面贴了相关代码:stackoverflow.com/a/52928884/5652513.
    【解决方案4】:

    android:duplicateParentState="true"
    

    在子视图中,视图从其直接父级而不是从自身获取其可绘制状态(聚焦、按下等)。 您可以为父级设置 onclick 并调用子级点击

    【讨论】:

    • OP 想在孩子被点击时调用父母的点击监听器,反之亦然。
    【解决方案5】:

    如果您的 TextView 创建点击问题,请从您的 xml 文件中删除 android:inputType=""

    【讨论】:

    • 如果你不知道为什么,我建议你不要这样做。只是说……对每个人自己说。
    • 你应该把它设置为android:inputType="none"
    • 我遇到了同样的问题。在 textview 我设置了android:inputType="textCapWords"
    【解决方案6】:

    这个答案类似于Alexander Ukhov's answer,除了它使用触摸事件而不是点击事件。这些事件允许父级显示正确的按下状态(例如,涟漪效应)。这个答案也在 Kotlin 而不是 Java 中。

    view.setOnTouchListener { view, motionEvent ->
        (view.parent as View).onTouchEvent(motionEvent)
    }
    

    【讨论】:

    • 有用的答案,谢谢!但我建议进行以下澄清:1)使用其他名称来触摸视图 - 例如“touchedView”; 2) 调用 performClick() 而不是 onTouchEvent()
    【解决方案7】:

    如果您想同时查看OnTouchOnClick 的父子视图,请使用以下技巧:

    1. 用户 ScrollView 作为父视图并在其中将您的子视图放置在相对/线性布局中。

    2. 使父 ScrollView android:fillViewport="true" 不滚动视图。

    3. 然后将OnTouch 侦听器设置为父视图,将OnClick 侦听器设置为子视图。 并享受这两个监听器回调。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-30
      • 2011-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多