【问题标题】:Custom View Touch Events自定义视图触摸事件
【发布时间】:2025-12-09 02:05:01
【问题描述】:

我正在尝试实现一个自定义视图,用户可以在其中用手指绘图。基本上,我在关注this tutorial

一切似乎都很好,但是,考虑到我在自定义视图下方也有 2 个按钮,如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/background_color"
    tools:context=".MainActivity" 
    android:id="@+id/mainScreen" >

    <Button
        android:id="@+id/buttonSave"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:text="@string/save" />

    <Button
        android:id="@+id/buttonQuery"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:text="@string/query" />

    <com.example.myapp.DrawView
        android:id="@+id/drawView"
        android:background="@color/red"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_above="@id/buttonSave" />

</RelativeLayout>

它实际上甚至在按钮下方绘制,我很难理解为什么它不只捕获发生在 DrawView 而不是在它之外的触摸事件。基本上,我不能从按钮上方开始画线,但是一旦我开始在我的视图上绘制,我什至可以将线延伸到它之外。

据我所知,DrawView 不会在按钮下方溢出,as discussed here 所以我想弄清楚发生了什么。我真的必须检查事件是否超出范围吗?它实际上是否将所有触摸事件委托给当前聚焦的视图?有没有办法改变这种行为?

This simple tutorial 没有描述的问题,但它会逐点绘制。


更新: 调试应用程序时,我确定 drawView 的大小为 480x728,而 mainScreen 的大小为 480x800,因此它们不重叠。一旦获得焦点,即使它们在drawView之外触发,它也会继续注册触摸事件。这是我要避免的,最好不要通过大的 if 语句传递事件坐标...

【问题讨论】:

    标签: android android-layout user-interface touch


    【解决方案1】:

    如果您不希望按钮与DrawView 重叠,请使用LinearLayout 将所有Views 分开。目前,从 XML 布局来看(并假设在代码中以编程方式布局没有任何奇怪的地方),您的按钮 DrawView 重叠。

    我的印象是您将两个按钮并排放置在顶部,DrawView 填充了下方剩余的屏幕区域。为此,请使用垂直方向的外部容器LinearLayout。它的第一个孩子是另一个水平方向的LinearLayout,包含两个按钮。内部LinearLayout 的第二个孩子是DrawView。使用宽度、高度和重量属性来获得所需的尺寸。 (或者,另一种方法是保留您拥有的 XML 布局结构,但在 DrawView 上设置一些上边距以等于按钮的高度,这可以在 XML 布局中固定,或以编程方式完成。)

    编辑对不起,我完全错过了layout_above 属性,这使我的第二句话无效。在那种情况下,我不确定目前是否无法启动 Eclipse。无论如何,按照建议尝试LinearLayout 方法。

    【讨论】:

    • 我只是调试了一下,完全没有重叠。 drawView 的大小为 480x728,而 mainScreen 的大小为 480x800。一旦获得焦点,即使它们在drawView之外触发,它也会继续注册触摸事件。这是我要避免的,最好不要通过大的if 语句传递事件坐标...
    • 也许是个愚蠢的问题,但是您如何确定它正在捕获MotionEvents 并在按钮下方 绘制?你的按钮有透明度吗?
    • 其实真的很奇怪,因为我不明白它画的是什么。我的意思是,传递给 onDraw 的画布不应该与我的 drawView 具有相同的大小吗?我没有为按钮分配任何颜色,所以默认情况下它们是透明的。
    • 确实,画布大小为 800,与 mainScreen 相同。你知道为什么吗?
    • 好的,我找到了原因:*.com/questions/10954798/… 但这仍然不能解释事件问题。我现在将尝试忽略在 drawView 范围之外触发​​的事件。
    【解决方案2】:

    这原来是 Android 模拟器显示界面的方式中的一些奇怪的错误。它可能会在真实设备上执行类似的操作(甚至在侦听器视图之外抛出触摸事件),但由于它将显示限制为 drawView,因此我可以放心地在我的应用程序中忽略它们,因为我只需要提取绘制的形状来自drawView。不过,它可能会在其他应用程序中引起很大的麻烦......

    【讨论】: