2

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

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

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

4

3 回答 3

6

我为我的应用程序 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];
}

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

我针对 CGRects 数组运行该点以确定按键(与命中测试相比,这更快)。

- (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”上。这是一种你可以在其他地方利用的行为,但在这种情况下,你必须通过一个“父视图”来解决它,它的工作是跟踪触摸。


(更新以修复内存泄漏)

于 2009-07-29T06:27:28.090 回答
0

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

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

于 2009-07-28T16:59:41.630 回答
0

您可以使用容器 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 *) 子视图的“热区”之外时,这是一种避免序列终止的简单方法。

于 2009-07-28T20:30:38.367 回答