Android:使用 MotionEvent 在自定义 ViewGroup 中对视图进行拖放定位

2024-03-21

我在创建的自定义 ViewGroup 上定位视图元素时遇到问题,特别是在拖放情况下。我的目标是 Android 2.2 及更高版本,因此我无法真正使用 Android 3 中出现的拖放 API。

我的自定义 ViewGroup 称为“NodeGrid”,它扩展了“RelativeLayout”。它是onLayout方法被重写,如下所示:

@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) 
{
    //pxConversion is a multiplier to convert 1 dip to x pixels.
    //We will use it to convert dip units into px units.
    Resources r = getResources();
    float pxConversion = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, r.getDisplayMetrics());

    //Layout the children of this viewgroup
    int childCount = this.getChildCount();
    for (int i = 0; i < childCount; i++)
    {
        NodeView view = (NodeView) this.getChildAt(i);

        if (view.DataContext != null)
        {
            int left = (int) (view.DataContext.get_left() * pxConversion);
            int top = (int) (view.DataContext.get_top() * pxConversion);
            int right = left + (int) (view.DataContext.get_width() * pxConversion);
            int bottom = top + (int) (view.DataContext.get_height() * pxConversion);

            view.layout(left, top, right, bottom);
        }
    }   
}

“NodeGrid”的子级的类型为“NodeView”(如上面的代码所示)。 NodeView 只是我创建的一个自定义视图类。它包含一个名为“DataContext”的成员,它是一个视图模型类,其中包含一些 getter/setter 以及有关 NodeGrid 上 NodeView 实例的位置信息。

我的“NodeView”类捕获用户的触摸事件,因此用户可以简单地将节点拖放到网格上的任何位置。事件处理程序如下所示:

@Override
public boolean onTouchEvent(MotionEvent event) {

    if (event.getAction() == MotionEvent.ACTION_DOWN)
    {
        isBeingDragged = true;
    }
    else if (event.getAction() == MotionEvent.ACTION_UP)
    {
        isBeingDragged = false;
    }
    else if (event.getAction() == MotionEvent.ACTION_MOVE)
    {
        if (DataContext != null && isBeingDragged)
        {
            float xPosition = event.getRawX();
            float yPosition = event.getRawY();

            DataContext.set_left(xPosition);
            DataContext.set_top(yPosition);

            this.requestLayout();
        }
    }

    return true;
}

我的问题是,被拖动的视图没有按照我期望的那样定位在“NodeGrid”上。当我拖动它时,x 轴位置似乎是正确的,但 y 轴位置随时都会偏移一些恒定数量的像素。什么会导致这种情况?我尝试使用 getX() 和 getY() 方法而不是 getRawX() 和 getRawY() 方法,但这只会导致情况变得更糟。

我不确定 getRawX() 和 getRawY() 是否返回 px 单位或倾角单位给我,因此期望它返回 px 单位,我尝试将它们转换为倾角单位,然后将新的 x 和 y 值分配给节点,但这只是减少了偏移量,并没有消除它。

是什么导致我触摸的位置和节点所在的位置存在差异?


非常惊讶,显然没有其他人遇到过这种情况......

经过一番研究,我已经部分解决了这个问题。

getRawX() 和 getRawY() 不起作用的原因是它们工作在绝对屏幕位置,而不考虑屏幕上不属于应用程序的任何内容(例如始终位于屏幕顶部的 Android 菜单)除非您处于全屏模式)。使用这些坐标似乎很黑客,尤其是没有明显的方法来证明它们并将它们转换为“我的应用程序”坐标。

据我所知, getX() 和 getY() 似乎与被触摸的对象相关。考虑到这一点,我将 onTouchEvent 中的代码更改为:

float xPosition = event.getX();
float yPosition = event.getY();

DataContext.set_left(DataContext.get_left() + xPosition);
DataContext.set_top(DataContext.get_top() + yPosition);

this.requestLayout();

这肯定有帮助......但它似乎仍然不是一个完美的解决方案。一般来说,它会导致视图对象与我的鼠标光标/手指一起拖动,但它非常不稳定,并且有时它会变得古怪并离开屏幕。

然后我想,也许是因为我没有将“历史坐标”纳入该方法中。我尝试将历史坐标合并到该方法中,方法是将此代码放在上面刚刚显示的代码之前:

int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++)
{
    float xPosition = event.getHistoricalX(i);
    float yPosition = event.getHistoricalY(i);

    DataContext.set_left(DataContext.get_left() + xPosition);
    DataContext.set_top(DataContext.get_top() + yPosition);

    this.requestLayout();
}

不幸的是......这实际上使情况变得更糟,所以要么我没有正确使用历史坐标,要么根本不应该使用它们。我将就此事发布另一个问题,但这应该足以作为我上面问题的部分答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android:使用 MotionEvent 在自定义 ViewGroup 中对视图进行拖放定位 的相关文章

随机推荐

  • Angular 4 - 如何为 ngFor 循环内的标签拥有唯一的 id 值?

    我遇到了一个问题 我需要为我的数据行中的每个数据行提供一个唯一的 id 值 ngFor角度 4 中的循环 我的代码是这样的 div div row myValue div div 假设你的对象中有一个唯一的 id 值 那么你可以这样做 di
  • R data.table 是否记录为通过引用作为参数传递?

    检查这个玩具代码 gt x lt data table a 1 2 gt foo lt function z z b 3 4 gt y lt foo x gt x a b 1 1 3 2 2 4 看来 data table 是通过引用传递的
  • 如何抑制 webdriver-manager 日志

    我正在使用 webdrivermanager 来管理项目中的驱动程序 但在更新到最新版本 2 2 1 后 我的项目中充满了 webdrivermanger 日志 这些日志在日志中搜索我自己的内容时造成了麻烦 我怎样才能停止 抑制这些日志 通
  • 钻石问题真的能解决吗?

    面向对象编程中的一个典型问题是菱形问题 我有父类 A 和两个子类 B 和 C A 有一个抽象方法 B 和 C 实现它 现在我有一个子类D 它继承了BandC 现在的钻石问题是 D应该使用什么实现 B的实现还是C的实现 人们声称 Java 不
  • AJAX post JSON 数据到达为空

    这是我的 AJAX 请求 data JSON stringify data url base url index php home make order alert url var request ajax url url type POS
  • 如何将 python 添加到 Windows 中的 cmd [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我安装了 python 3 1 并且也将其添加到系统路径中 现在我可以打开 cmd 并输入 python 来启动 python 但是每当我
  • 像树一样渲染嵌套列表

    我如何使垂直边框停在最后一个元素处 它只能与 CSS3 现代浏览器兼容 但需要在各种背景下工作 即透明 http jsfiddle net ShgD6 http jsfiddle net ShgD6 由此 To this 我通过修改这个小提
  • 如何在猫头鹰旋转木马的角度中制定指令?

    你能告诉我如何在 Angular js 中制作指令吗 我需要在 js 中使用 owl carousel 插件 就像我在 jqm fiddle 中所做的那样http jsfiddle net ezanker o9foej5L 1 http j
  • Vuetify 离线文档

    我已经开始使用 Vuetify 添加 ui 组件并使用预定义的布局 问题是我必须时不时地查看在线文档 并且要求我永远连接到互联网 有没有办法获取 Vuetify 的离线文档 就像使用 doxygen javadocs 构建的 html 或
  • 如何使用 Scala 的 DataFrame 比较表中的每一列

    有两张桌子 一张是ID表1 一张是属性表2 Table 1 Table 2 如果表1中同一行的ID具有相同的属性 则得到数字1 否则得到0 最终得到结果表3 Table 3 例如 id1和id2具有不同的颜色和大小 因此id1和id2行 表
  • 如何在jQuery中选择所有本地链接

    我需要选择所有本地链接 无论是否以 path to page http mydomain com path to page https mydomain com path to page 并将它们替换为 path to page 感谢您的帮
  • 在仅附加表中设置版本列

    我们有一个表来存储记录的版本 这些列是 Id Guid VersionNumber int Title nvarchar Description nvarchar etc 保存项目将在表中插入具有相同 ID 和增量版本号的新行 我不确定如何
  • 如何使用attachEvent引用调用者对象(“t​​his”)

    使用方法 attachEvent 在 IE 中 如何引用调用者对象 触发事件的元素 this In normal浏览器 使用 addEventListener 变量this指向元素 而在 IE 中它指向window object 我需要它与
  • Visual Studio 2013 Update 2 无法打开 cshtml

    我安装了新的 VS2013 Update 2 只要我打开 cshtml 文件 VS 就会崩溃 I tried 修复VS 停用所有扩展 devenv exe ResetSkipPkgs 重置所有设置 没有成功 安装 Xamarin 后我遇到了
  • 用Python写的3D OpenGL游戏能好看又运行快吗?

    我计划使用 jMonkeyEngine 在 Java 中编写一个简单的 3D 等轴测视图 游戏 没什么好看的 我只是想学习一些有关 OpenGL 的知识并编写高效的算法 随机地图生成算法 当我计划要做什么时 我开始考虑是否要转向 Pytho
  • System.IdentityModel 和 Microsoft.IdentityModel 之间有什么区别,我应该使用哪一个?

    我刚刚开始尝试编写一个联合声明提供程序 我正在使用http claimsid codeplex com http claimsid codeplex com 示例作为我的模板 因此 我启动 VS2010 开始我自己的项目 我注意到的第一件事
  • Bootstrap 中心导航栏项目

    我知道我可以将导航栏项目向左和向右推送 但如何将它们居中呢 text align center 不起作用 也没有我想到的任何其他事情 您将需要修改导航栏组件的一些 CSS 规则 所以添加一个类center to nav navbar以及以下
  • Sql 视图的流畅 Nhibernate 映射

    我在 asp net mvc3 和 c 中使用 Fluent Nhibernate 我正在按以下方式工作来生成和映射一个类 Mapping using FluentNHibernate Mapping using Com Web Domai
  • 如何使用 Gradle 2.0 下载 javadoc 和 jar 源?

    我正在使用 Gradle 2 0 我应该写什么build gradle这样 javadocs 和源代码也会与 jar 一起下载吗 我猜您的问题与开发工作区有关 以下链接解释了如何使用 IDE 插件在 Gradle 中添加所需的配置 For
  • Android:使用 MotionEvent 在自定义 ViewGroup 中对视图进行拖放定位

    我在创建的自定义 ViewGroup 上定位视图元素时遇到问题 特别是在拖放情况下 我的目标是 Android 2 2 及更高版本 因此我无法真正使用 Android 3 中出现的拖放 API 我的自定义 ViewGroup 称为 Node