8

I am building my Keyboard Extension app and i have added key pop animation on button when user tap on it. It works fine for inside image but for top row image pop up area become hidden as it clip the subview. I tried with ClipToBound property and set as False. But still not working. Anyone have any idea how to fix this? adding subview on superview also not works.

Image A is showing correct pop up as it is inside frame of keyboard. Image B is wrong as pop up clip inside frame.

Image A is showing correct pop up as it is inside frame of keyboard. Image B is wrong as pop up clip inside frame.

Muzammil
  • 1,529
  • 1
  • 15
  • 24
  • How were you able to add the pop animation when tapping the keyboard? I also think this is possible in the top keys as I see many keyboard apps implementing similar approach that they were able to adjust the keyboard view to accommodate more controls or options for their custom keyboard. Check this link: http://stackoverflow.com/questions/25010193/how-to-toggle-a-word-selection-view-change-height-in-ios-custom-keyboard/25675775#25675775 – jaytrixz Aug 24 '15 at 11:52
  • I was adding a custom draw layer of that shape on top of button which is pressed. – Muzammil Aug 28 '15 at 10:34
  • Can you share your custom draw layer code here: http://stackoverflow.com/questions/32179015/implement-keyboard-key-pop-animation-in-ios-8-keyboard-extension – jaytrixz Aug 28 '15 at 14:44
  • Hi, can you share your popup shape ? – TomSawyer Oct 15 '15 at 18:40
  • Check my answer below. I have added the code for pop up shape. – Muzammil Oct 26 '15 at 20:51

3 Answers3

5

I don't think you are allowed to display anything outside of the keyboard view; it will get automatically clipped.

https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/Keyboard.html

Ben
  • 739
  • 6
  • 25
  • Thanks Ben. I tried with many possible cases but unable to get this working, so for now i drop this idea :( – Muzammil Oct 11 '14 at 19:25
4

//Those who are looking for pop up shaped image:

// I have used some constants for button width etc, you can adjust as per new keyboard.

**#define _UPPER_WIDTH (52.0 * [[UIScreen mainScreen] scale])

**#define _LOWER_WIDTH (32.0 * [[UIScreen mainScreen] scale])

**#define _PAN_UPPER_RADIUS (7.0 * [[UIScreen mainScreen] scale])

**#define _PAN_LOWER_RADIUS (7.0 * [[UIScreen mainScreen] scale])

**#define _PAN_UPPDER_WIDTH (_UPPER_WIDTH-_PAN_UPPER_RADIUS*2)

**#define _PAN_UPPER_HEIGHT (61.0 * [[UIScreen mainScreen] scale])

**#define _PAN_LOWER_WIDTH (_LOWER_WIDTH-_PAN_LOWER_RADIUS*2)

**#define _PAN_LOWER_HEIGHT (30.0 * [[UIScreen mainScreen] scale])

**#define _PAN_UL_WIDTH ((_UPPER_WIDTH-_LOWER_WIDTH)/2)

**#define _PAN_MIDDLE_HEIGHT (11.0 * [[UIScreen mainScreen] scale])

**#define _PAN_CURVE_SIZE (7.0 * [[UIScreen mainScreen] scale])

**#define _PADDING_X (15 * [[UIScreen mainScreen] scale])

**#define _PADDING_Y (10 * [[UIScreen mainScreen] scale])

**#define _WIDTH (_UPPER_WIDTH + _PADDING_X*2)

**#define _HEIGHT (_PAN_UPPER_HEIGHT + _PAN_MIDDLE_HEIGHT + _PAN_LOWER_HEIGHT + _PADDING_Y*2)

**#define _OFFSET_X -25 * [[UIScreen mainScreen] scale])

**#define _OFFSET_Y 59 * [[UIScreen mainScreen] scale])

- (UIImage *)createKeytopImageOfType:(ButtonType)type
{

CGMutablePathRef path = CGPathCreateMutable();


CGPoint p = CGPointMake(_PADDING_X, _PADDING_Y);
CGPoint p1 = CGPointZero;
CGPoint p2 = CGPointZero;

p.x += _PAN_UPPER_RADIUS;
CGPathMoveToPoint(path, NULL, p.x, p.y);

p.x += _PAN_UPPDER_WIDTH;
CGPathAddLineToPoint(path, NULL, p.x, p.y);

p.y += _PAN_UPPER_RADIUS;

CGPathAddArc(path, NULL,
             p.x, p.y,
             _PAN_UPPER_RADIUS,
             3.0*M_PI/2.0,
             4.0*M_PI/2.0,
             false);

p.x += _PAN_UPPER_RADIUS;

p.y += _PAN_UPPER_HEIGHT - _PAN_UPPER_RADIUS - _PAN_CURVE_SIZE;

CGPathAddLineToPoint(path, NULL, p.x, p.y);

p1 = CGPointMake(p.x, p.y + _PAN_CURVE_SIZE);

switch (type) 
{
    case LeftButton:
        p.x -= _PAN_UL_WIDTH*2;
        break;

    case InnerButton:
        p.x -= _PAN_UL_WIDTH;
        break;

    case RightButton:
        break;
}

p.y += _PAN_MIDDLE_HEIGHT + _PAN_CURVE_SIZE*2;
p2 = CGPointMake(p.x, p.y - _PAN_CURVE_SIZE);
CGPathAddCurveToPoint(path, NULL,
                      p1.x, p1.y,
                      p2.x, p2.y,
                      p.x, p.y);

p.y += _PAN_LOWER_HEIGHT - _PAN_CURVE_SIZE - _PAN_LOWER_RADIUS;
CGPathAddLineToPoint(path, NULL, p.x, p.y);

p.x -= _PAN_LOWER_RADIUS;
CGPathAddArc(path, NULL,
             p.x, p.y,
             _PAN_LOWER_RADIUS,
             4.0*M_PI/2.0,
             1.0*M_PI/2.0,
             false);

p.x -= _PAN_LOWER_WIDTH;
p.y += _PAN_LOWER_RADIUS;
CGPathAddLineToPoint(path, NULL, p.x, p.y);

p.y -= _PAN_LOWER_RADIUS;
CGPathAddArc(path, NULL,
             p.x, p.y,
             _PAN_LOWER_RADIUS,
             1.0*M_PI/2.0,
             2.0*M_PI/2.0,
             false);

p.x -= _PAN_LOWER_RADIUS;
p.y -= _PAN_LOWER_HEIGHT - _PAN_LOWER_RADIUS - _PAN_CURVE_SIZE;
CGPathAddLineToPoint(path, NULL, p.x, p.y);

p1 = CGPointMake(p.x, p.y - _PAN_CURVE_SIZE);

switch (kind) {
    case PKNumberPadViewImageLeft:
        break;

    case PKNumberPadViewImageInner:
        p.x -= _PAN_UL_WIDTH;
        break;

    case PKNumberPadViewImageRight:
        p.x -= _PAN_UL_WIDTH*2;
        break;
}

p.y -= _PAN_MIDDLE_HEIGHT + _PAN_CURVE_SIZE*2;
p2 = CGPointMake(p.x, p.y + _PAN_CURVE_SIZE);
CGPathAddCurveToPoint(path, NULL,
                      p1.x, p1.y,
                      p2.x, p2.y,
                      p.x, p.y);

p.y -= _PAN_UPPER_HEIGHT - _PAN_UPPER_RADIUS - _PAN_CURVE_SIZE;
CGPathAddLineToPoint(path, NULL, p.x, p.y);

p.x += _PAN_UPPER_RADIUS;
CGPathAddArc(path, NULL,
             p.x, p.y,
             _PAN_UPPER_RADIUS,
             2.0*M_PI/2.0,
             3.0*M_PI/2.0,
             false);
//----
CGContextRef context;
UIGraphicsBeginImageContext(CGSizeMake(_WIDTH,
                                       _HEIGHT));
context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0.0, _HEIGHT);
CGContextScaleCTM(context, 1.0, -1.0);

CGContextAddPath(context, path);
CGContextClip(context);

//----

// draw gradient
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceGray();
CGFloat components[] = {
    0.95f, 1.0f,
    0.85f, 1.0f,
    0.675f, 1.0f,
    0.8f, 1.0f};

size_t count = sizeof(components)/ (sizeof(CGFloat)* 2);

CGRect frame = CGPathGetBoundingBox(path);
CGPoint startPoint = frame.origin;
CGPoint endPoint = frame.origin;
endPoint.y = frame.origin.y + frame.size.height;

CGGradientRef gradientRef =
CGGradientCreateWithColorComponents(colorSpaceRef, components, NULL, count);

CGContextDrawLinearGradient(context,
                            gradientRef,
                            startPoint,
                            endPoint,
                            kCGGradientDrawsAfterEndLocation);

CGGradientRelease(gradientRef);
CGColorSpaceRelease(colorSpaceRef);

CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage * image = [UIImage imageWithCGImage:imageRef scale:[[UIScreen mainScreen] scale] orientation:UIImageOrientationDown];
CGImageRelease(imageRef);

UIGraphicsEndImageContext();

CFRelease(path);

return image;
}
Muzammil
  • 1,529
  • 1
  • 15
  • 24
  • 1
    Thanks a lot Sir Muzammil! :) – jaytrixz Oct 27 '15 at 10:28
  • what's a ButtonType here? Like LeftButton, InnerButton etc. What are those? i can;t seem to relate :( – sudoExclaimationExclaimation Feb 03 '16 at 06:25
  • @PranoyC: Shape of left, right and inner buttons are different. So we have to define them too. – Muzammil Feb 03 '16 at 07:20
  • @Muzammil Thanks! Very helpful. – iOS Dev Mar 31 '16 at 11:50
  • I had a question regarding fixed sizes. These don't scale across screen sizes, right? I finally got my layout working using stackviews across all screens, but I'm trying to figure out how to get this popup show up and with good width/height across different widths. – VDog Mar 13 '17 at 05:42
  • @VDog I did't checked but it should work with different screen. The only problem with the top row of the keyboard. Progrmr (below) already explained this well. – Muzammil Mar 13 '17 at 07:52
  • Why would they scale if we are setting fixed widths/heights... that means the keys will not match the respective key width/heights as those vary depending on screen size. – VDog Mar 14 '17 at 01:47
1

@Ben is correct, you're not allowed to display anything outside the keyboard window.

If you examine the view hierarchy you can see that the UIWindow holding the keyboard extension doesn't extend above the keyboard, so even if you turn off clipsToBounds in the entire view hierarchy up to the window, you still can't display outside the window.

progrmr
  • 75,956
  • 16
  • 112
  • 147