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

标签 ios cocoa-touch keyboard touch

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

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

我有一个长按按钮,它是自定义 View Controller ,所有设置和工作。我想不通的是如何支持从 View Controller 中的第一个按钮拖动到另一个按钮以便能够选择它。

我试过使用子类 UIButton,我试过这个:

[ self 添加目标: self 行动:@selector(onDragOver :) forControlEvents:UIControlEventTouchDragEnter];

但这行不通。

我也发现了这个问题How to track button selection after long press?这正是我要复制的功能。但没有答案。

最佳答案

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

首先,您将手势识别器添加到按钮,这是一个普通按钮 - 您想要打开上下文菜单/自定义 View Controller 的按钮。

然后在您的手势识别器回调中,您使用 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

关于iOS:处理长按并拖动以选择另一个按钮。 (比如键盘),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31578847/

相关文章:

ios - 快速安全的数据传输

android - Flutter 在 StreamBuilder 中显示 SnackBar 并返回空容器会引发错误

objective-c - 如何在不修改其点击矩形的情况下调整 UIButton 的大小

android - 我如何处理 Android 中 Emojipicker 和键盘之间的切换?

keyboard - 如何使用 xset 点亮 Caps Lock 灯?

ios - NSDictionary 和核心数据

ios - 关于可本地化推送负载内容的一些问题

ios - 跟踪在申请中花费的时间

ios - 在没有 Realm 的后台线程中创建 Realm 对象,然后将它们传递给主线程

javascript - Android 键盘在验证后无法在 webview 中工作