【问题标题】:Hover Over State for UIButton on iPhoneiPhone上UIButton的悬停状态
【发布时间】:2009-07-28 16:50:31
【问题描述】:

我成功地创建了一个功能类似于 Apple 键盘的自定义键盘。有一件事仍然不同。在 Apple 的 iPhone 键盘上,用户可以用手指在键盘上滑动,他们通过的所有键都会弹出。在我的键盘上,这不会发生。滑动你的手指只会导致我触摸的第一个按钮弹出,当我离开足够远的距离时,它会回落。我目前正在使用此代码作为弹出键:

UIImage *bigLetter = [UIImage imageNamed:@"letter1.png"];
[keyOne setImage:bigLetter forState:UIControlStateHighlighted];

keyOne 是一个 UIButton,当用户“突出显示”或点击键盘上的键时,我会覆盖较大字符的图像。是否有类似的状态只是“悬停”,这样如果用户突出显示 Q 键并将手指滑到 W 键上,W 键就会突出显示?

【问题讨论】:

标签: iphone cocoa-touch uibutton


【解决方案1】:

我为我的应用 Compounds 实现了元素周期表键盘。

不要使用 UIButtons。

要显示您的键盘,请使用: UIViews 或 CALayers 来显示各个键

静态PNG。记忆和“拉链”要容易得多。 (这是我为尚未到来的更新所做的)

您必须使用父视图跟踪所有触摸。 (在底部添加了一个小边来解释为什么会这样)像这样实现 touches 方法:

- (void)touchesBegan: (NSSet *)touches 
           withEvent: (UIEvent *)event {
    NSLog(@"TouchDown");

    CGPoint currentLocation = [[touches anyObject] locationInView:self.view];
    [self magnifyKey:[self keyAtPoint:currentLocation]];
}

-(void)touchesMoved: (NSSet *)touches 
          withEvent: (UIEvent *)event {
    NSLog(@"TouchMoved");

    CGPoint currentLocation = [[touches anyObject] locationInView:self.view];
    [self magnifyKey:[self keyAtPoint:currentLocation]];    
}


-(void) touchesEnded: (NSSet *)touches 
           withEvent: (UIEvent *)event{

    NSLog(@"TouchUp");

    CGPoint currentLocation = [[touches anyObject] locationInView:self.view];

    int key = [self keyAtPoint:currentLocation];
    [self selectKey:aKey];
}

这些方法获取密钥并适当地“放大”选定的密钥。

我针对一个 CGRect 数组运行该点以确定按键(这比点击测试更快)。

- (int)keyAtPoint:(CGPoint)aPoint{

    int aKey=1;
    for(NSString *aRect in keys){
        if(CGRectContainsPoint(CGRectFromString(aRect), aPoint)){
            break;
        }
        aKey++;
    }

    if(aKey==kKeyOutOfBounds)
        aKey=0;
    NSLog([NSString stringWithFormat:@"%i",aKey]); 
    return aKey;
}


- (void)magnifyKey:(int)aKey{

        if(aKey!=0) {

            if(magnifiedKey==nil){

                self.magnifiedKey = [[[MagnifiedKeyController alloc] initWithKey:aKey] autorelease];
                [self.view addSubview:magnifiedKey.view];       

            }else{

                [magnifiedKey setKey:aKey];
                if([magnifiedKey.view superview]==nil)
                    [self.view addSubview: magnifiedKey.view];      

            }

        }else{

            if(magnifiedKey!=nil)
                [magnifiedKey.view removeFromSuperview];
        }
    }


    - (void)selectKey:(int)aKey{

        if(magnifiedKey!=nil){

            if(aKey!=0){

                [magnifiedKey flash];
                [self addCharacterWithKey:aKey];
            }
            [magnifiedKey.view performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0.5];
        }
    }

其中有一些方法供您实现,但非常简单。您基本上是在创建一个放大键的视图。然后在用户滑动手指时移动它。


旁白:

您无法使用子视图跟踪触摸,因为一旦视图跟踪触摸,它就会继续跟踪触摸,直到调用 touchesEnded:(或 touchesCancelled:)。这意味着一旦字母“Q”跟踪触摸,其他键将永远无法访问该触摸。即使您将鼠标悬停在字母“W”上。这是一种您可以在其他地方利用的行为,但在这种情况下,您必须通过“父视图”来解决它,该视图的工作是跟踪触摸。


(已更新以修复内存泄漏)

【讨论】:

  • 不错。如果您立即实例化MagnifiedKeyController 而不是懒惰地实例化,它可能会稍微简化代码。现在,如果magnifiedKey 属性是保留属性,我认为你有内存泄漏。即使是 assign 属性,在 dealloc 期间释放 assign 属性 ivar 也是不常见的。
  • 它是一个保留属性,它在 dealloc 中被释放,但你是对的:当我实例化它时,我需要一个自动释放。您可以在开始时实例化并摆脱一些“如果”。它只是一个对象,所以预加载不是一个坏主意。
【解决方案2】:

看看 UIControlEvents 枚举。这是您可以针对特定视图捕获的所有事件。

如果我不得不猜测,我会说您可以使用 TouchDown 和 TouchDrag 系列的某种组合来复制此功能。使用 TouchUp 捕捉被触摸的按键。

【讨论】:

    【解决方案3】:

    您可以使用容器 UIView 的 touchesMoved:withEvent: 方法并使用以下内容对每个子视图(又名键)进行点击测试:

    for(key in keys){
      location = [touch locationInView:key];
      if([key pointInside:location withEvent:event]){
        // if not already animated or otherwise triggered, trigger
      }
    }
    

    这个想法是使用父视图处理触摸序列。当触摸移动到 (UIControl *) 子视图的“热区”之外时,这是一种避免序列终止的简单方法。

    【讨论】:

      猜你喜欢
      • 2014-04-09
      • 1970-01-01
      • 2016-12-23
      • 1970-01-01
      • 2013-03-17
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-28
      相关资源
      最近更新 更多