iOS:处理长按并拖动以选择另一个按钮。 (如键盘)

2024-04-14

我很难找到有关如何处理触摸事件以支持与键盘类似的行为的正确文档。

我想要的是一个按钮,当我长按它时,它会在按钮上方显示一个自定义视图控制器,但我希望用户能够将手指拖动到其他按钮之一(无需将手指离开屏幕) 。

我长按按钮,它是自定义视图控制器的所有设置和工作。我不知道如何支持从视图控制器中的第一个按钮拖动到另一个按钮以便能够选择它。

我尝试使用子类 UIButton 尝试这样做:

[self addTarget:self action:@selector(onDragOver:) forControlEvents:UIControlEventTouchDragEnter];

但这是行不通的。

我也发现了这个问题长按后如何跟踪按钮选择? https://stackoverflow.com/questions/20740411/how-to-track-button-selection-after-long-press这正是我想要复制的功能。但没有答案。


这是我的解决方案。诀窍是你必须使用 hitTest: 。

首先,向普通按钮添加手势识别器 - 您想要打开上下文菜单/自定义视图控制器的按钮。

然后在手势识别器回调中,使用 hitTest: 来确定用户是否位于您的自定义按钮上并手动更新其状态。

- (id) init {
    //add a long press gesture recognizer
    UILongPressureGestureRecognizer * gesture = [[UILongPressureGestureRecognizer alloc] initWithTarget:self action:@selector(onLongTap:)];
    [self.myButton addGestureRecognizer:gesture];
}

- (void) onLongTap:(UIGestureRecognizer *) gesture {

    if(gesture.state == UIGestureRecognizerStateBegan) {
        //display your view controller / context menu over the button
    }

    if(gesture.state == UIGestureRecognizerStateEnded) {
        //gesture stopped, use hitTest to find if their finger was over a context button

        CGPoint location = [gesture locationInView:self.view];
        CGPoint superviewLocation = [self.view.superview convertPoint:location fromView:self.view];
        UIView * view = [self.view.superview hitTest:superviewLocation withEvent:nil];

        if([view isKindOfClass:[MMContextMenuButton class]]) {
            //their finger was over my custom button, tell the button to send actions
            MMContextMenuButton * button = (MMContextMenuButton *) view;
            [self hideAndSendControlEvents:UIControlEventTouchUpInside];
            if(self.draggedContextMenuButton == button) {
                self.draggedContextMenuButton = nil;
            }
        }

        if(self.draggedContextMenuButton) {
            [self sendActionsForControlEvents:UIControlEventTouchUpInside];
        }

        self.draggedContextMenuButton = nil;
    }

    if(gesture.state == UIGestureRecognizerStateChanged) {
        //gesture changed, use hitTest to see if their finger
        //is over a button. Manually have to tell the button
        //that it should update it's state.

        CGPoint location = [gesture locationInView:self.view];
        CGPoint superviewLocation = [self.view.superview convertPoint:location fromView:self.view];
        UIView * view = [self.view.superview hitTest:superviewLocation withEvent:nil];

        if([view isKindOfClass[MMContextMenuButton class]]) {
            MMContextMenuButton * button = (MMContextMenuButton *) view;
            if(self.draggedContextMenuButton != button) {
                [self.draggedContextMenuButton dragOut];
            }
            self.draggedContextMenuButton = button;
            [button dragOver];
        }
    }
}


//////////////


#import "MMContextMenuButton.h"
#import "MMContextMenus.h"

@implementation MMContextMenuButton

- (id) initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    self.layer.cornerRadius = 4;
    self.adjustsImageWhenHighlighted = FALSE;
    self.adjustsImageWhenDisabled = FALSE;
    self.backgroundColor = [UIColor clearColor];
    [self setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
    [self setTitleColor:[UIColor colorWithRed:0.435  green:0.745  blue:0.867 alpha:1] forState:UIControlStateNormal];
    [self addTarget:self action:@selector(onHighlight:) forControlEvents:UIControlEventTouchDown];
    [self addTarget:self action:@selector(onRelease:) forControlEvents:UIControlEventTouchUpOutside&UIControlEventTouchUpOutside];
    return self;
}

- (void) onHighlight:(id) sender {
    self.backgroundColor = [UIColor colorWithRed:0.435  green:0.745  blue:0.867 alpha:1];
}

- (void) onRelease:(id) sender {
    self.backgroundColor = [UIColor clearColor];
}

- (void) hideAndSendControlEvents:(UIControlEvents) events {
    [self dragOut];
    [self sendActionsForControlEvents:events];
    [[MMContextMenus instance] hideContextMenus];
}

- (void) dragOver {
    self.highlighted = TRUE;
    self.backgroundColor = [UIColor colorWithRed:0.435  green:0.745  blue:0.867 alpha:1];
}

- (void) dragOut {
    self.highlighted = FALSE;
    self.backgroundColor = [UIColor clearColor];
}

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

iOS:处理长按并拖动以选择另一个按钮。 (如键盘) 的相关文章

随机推荐

  • 将 JVM 字节码往返于文本表示的故障安全方法

    我正在寻找一种在 JVM 类文件和文本表示之间往返的故障安全方法 一项严格的要求是 只要文本表示形式保持不变 生成的往返 JVM 类文件在功能上与原始 JVM 类文件完全相同 此外 文本表示必须是人类可读和可编辑的 应该可以对文本表示进行小
  • ServiceStack OAuth - 注册而不是登录

    在 servicestack OAuth 实现中 我只看到了自动登录的可能性 例如 脸书账号 但是否能够支持通过 Facebook 登录进行注册过程 我想要的是让用户登录到 facebook 应用程序 然后加载他们的姓名 姓氏和电子邮件 并
  • 如何从命令行创建 Android 项目

    我正在尝试从命令行创建一个 Android 项目 我在以下链接上尝试了它是什么 如何从命令行使用gradle创建android项目 https stackoverflow com questions 20801042 how to crea
  • Laravel 扩展包类

    我在 Laravel 安装中添加了一个购物车包 但我需要向该类添加一个方法 如果我直接修改类 当我更新到新版本时 我的更改会被覆盖吗 如果是这样 在不破坏未来更新的情况下修改软件包的最佳方法是什么 谢谢您的帮助 JB 我不知道是否有任何从供
  • J2EE 中的应用程序管理事务

    有没有人有一个从 J2EE 6 容器内的 CDI 托管 bean 内开始 提交 回滚事务的最佳方法的示例 我遇到了一种特殊情况 其中带注释的方法对我不起作用 我从同一类中的另一个方法调用该方法 并且我需要手动设置事务边界 我想知道我可以在代
  • 错误消息“未终止的字符串文字”

    我使用 jQuery 输出 PHP 从数据库创建的 JSON 字符串的结果 唯一的问题是一些数据位于多行上 我该如何解决这个问题 导致 JavaScript 中出现未终止的字符串文字错误 以下代码将删除所有 r 和 n 字符 preg re
  • 为什么 Haskell [] (list) 不是类型类?

    我正在编写一个 Haskell 函数 它接受一个列表作为输入 也就是说 它没有理由不能是队列或出列 或者任何允许我访问它的 头 和 尾 并检查它是否为空 的东西 所以 a 输入类型似乎太具体了 但据我所知 没有标准库类型类可以准确捕获此接口
  • 返回打开、关闭或从一天中的时间开始关闭的功能

    我有很多小时的操作时间 我想确定商店是否在 30 29 28 27 分钟内打开 关闭或即将关闭 我在 Xcode Objectic C 中执行此操作 现在我必须在 50 个不同的操作小时内执行此操作 我已经制作了一个函数来执行此操作 但它不
  • 我可以从 freebase.com 导出地名翻译吗

    所以我看过 of the freebase http freebase comAPI 和我对它找到的名称的翻译印象深刻 IE 罗马 Roma Rom Rzym Rooma 罗马市 这是因为我有一个包含 5000 多个地点名称的数据库 我非常
  • 如何将 sqlite 3.8.2 升级到 >= 3.8.3

    在使用 Python 3 7 2 的虚拟环境中 我尝试运行 djangopython manage py startap myapp我收到此错误 raise ImproperlyConfigured SQLite 3 8 3 or late
  • PHP mail() 中的空 $_POST

    对于以下方面的一些帮助将不胜感激 我已经在网络和 stackoverflow 上搜索了几个小时 我的php邮件功能有这个问题 我的网站上有一个表单 该网站使用 WordPress 其中包含两个文本字段 姓名和电话号码 表单中还有一个隐藏字段
  • 如何快速有效地调试 CloudFormation 模板?

    CloudFormation 是一项功能强大的 AWS 产品 允许以编程方式创建 AWS 资源堆栈 例如应用程序的网络层 https s3 amazonaws com cloudformation templates us east 1 v
  • Crm 2011 Outlook 客户端 - 设置有关强制

    我们的客户正在使用 Microsoft CRM 2011 Outlook 客户端 他们有独特的业务需求 他们希望所有使用 Outlook 发送电子邮件的员工都必须强制执行 设置相关内容 很奇怪吧 如果用户在发送电子邮件时忘记设置相关内容 O
  • (PostgreSQL)错误:无法打开关系

    我收到这个奇怪的错误 Caused by org postgresql util PSQLException ERROR could not open relation base 17369 1684 No such file or dir
  • 链接静态库后去除名称

    在 iOS 6 的静态库项目中 c 文件中的某些函数被其他函数引用 因此被视为全局符号 但不应向该库的用户公开 我怎么能够strip这些函数名出来了吗 另外 我怎样才能隐藏这些 obj 文件名 以便没有人可以看到 o 名称nm output
  • 清理 PHP/HTML 页面

    有人知道有什么好用的工具可以清理php和html文件吗 我以前使用过 Tidy 但它在单独处理 php 代码方面效果不佳 我知道 tidy 有多种实现 但是有没有专门针对 html 和 php 页面的工具统治冠军 清理代码从将 PHP 与
  • Golang 预处理器类似 C 风格的编译开关

    GO语言有预处理器吗 当我查找互联网时 几乎没有将 pgo 转换为 go 的方法 而且 我想知道这在 Go 中是否可行 ifdef COMPILE OPTION compile this code elif compile another
  • 将 html 表单值传递给 google 搜索查询[重复]

    这个问题在这里已经有答案了 旁注 在每个人告诉我谷歌的自定义搜索引擎之前 我一直在使用它直到现在 但我发现很难设计该搜索框的样式 并且它在我的网站上崩溃了 Hello 我正在尝试创建一个使用 HTML 表单输入的 google 搜索查询 我
  • VBA:运行时错误“91”?

    我在这里想做的就是保存对当前活动窗口的引用 但它似乎不起作用 它在最后一行给了我一个运行时错误 Dim SourceWindow As Window QACheckWindow As Window SourceWindow ActiveWi
  • iOS:处理长按并拖动以选择另一个按钮。 (如键盘)

    我很难找到有关如何处理触摸事件以支持与键盘类似的行为的正确文档 我想要的是一个按钮 当我长按它时 它会在按钮上方显示一个自定义视图控制器 但我希望用户能够将手指拖动到其他按钮之一 无需将手指离开屏幕 我长按按钮 它是自定义视图控制器的所有设