我正在构建一个Watch应用程序,其中我要覆盖WKInterface
Image与一组WKInterfaceLabel对象.在StoryBoard编辑器中似乎无法做到这一点.
有没有人能够为Watch App设计出相互之间的观点?
PS.我知道WKInterfaceGroup setBackgroundImage方法.因为我想在WKInterfaceImage里面做一些动画,所以setBackgroundImage不会让我失望
解决方法
您无法将WKInterfaceObjects布置在彼此之上.您可以将标签渲染在图像上,然后进行设置.您将必须为动画的每个帧渲染标签.我在手表应用程序中执行此按钮.我生成一个我的UI的大块图像,然后生成动画的每一帧,并覆盖每个帧的按钮文本.然后剪切每个框架的图像,以便我可以在每个按钮上的动画.当您使用该应用程序时,它看起来像是在按钮下的动画,实际上它是4种不同的动画在4个不同的按钮.
编辑
我想我会添加一些更多的细节.这是我的应用程序的屏幕截图.我猜你想做类似的事情.
首先在我的故事板上,您需要确保您的组的间距为零.
要创建这个UI,我使用这个助手类.我已经编辑了这个课程,只关注所需的部分.
typedef struct { CGRect top; CGRect left; CGRect right; CGRect bottom; } ButtonRects; @interface GPWatchMapImage () @property (readwrite,nonatomic) UIImage* topImage; @property (readwrite,nonatomic) UIImage* bottomImage; @property (readwrite,nonatomic) UIImage* leftImage; @property (readwrite,nonatomic) UIImage* rightImage; @property (readwrite,nonatomic) CGRect topRect; @property (readwrite,nonatomic) CGRect bottomRect; @property (readwrite,nonatomic) CGRect leftRect; @property (readwrite,nonatomic) CGRect rightRect; @property (readwrite,nonatomic) UIImage* fullImageWithoutArrows; @property BOOL addedArrows; @end @implementation GPWatchMapImage -(instancetype)init { self = [super init]; if (self) { } return self; } -(UIImage*)leftImage { if (_leftImage == nil) { [self breakUpForButtons]; } return _leftImage; } -(UIImage*)rightImage { if (_rightImage == nil) { [self breakUpForButtons]; } return _rightImage; } -(UIImage*)topImage { if (_topImage == nil) { [self breakUpForButtons]; } return _topImage; } -(UIImage*)bottomImage { if (_bottomImage == nil) { [self breakUpForButtons]; } return _bottomImage; } -(UIImage*)fullImageWithoutArrows { [self fullImage]; //make sure we have the full image if (_fullImageWithoutArrows != nil) { return _fullImageWithoutArrows; } return _fullImage; } -(UIImage*)fullImage { if (_fullImage == nil) { //This is the rect to create the image in CGRect rect = CGRectMake(0,self.watchSize.width,self.watchSize.height); //This is how I generate map images. You will need to do something else self.generatedMapInfo = [[GPCustomMapMaker instance] makeCustomMapFromConfig:self.mapConfig]; _fullImage = self.generatedMapInfo.mapImage; } if (self.showMapArrows && !self.addedArrows) { //Add the arrows [self addButtonArrowsToFullImage]; } return _fullImage; } -(void)addButtonArrowsToFullImage { self.addedArrows = YES; ButtonRects rects = [self buttonRects]; UIImage* img = self.fullImage; self.fullImageWithoutArrows = img; //save for animations UIGraphicsBeginImageContext(img.size); UIColor* color = [UIColor colorWithRed:.4 green:.4 blue:.4 alpha:.6]; //CGSize arrowSize = CGSizeMake(24,4); CGSize arrowSize = CGSizeMake(48,8); CGFloat edgeOffset = 26; CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextSetLineWidth(ctx,6); CGContextSetLineJoin(ctx,kCGLineJoinRound); CGContextSetLineCap(ctx,kCGLineCapRound); CGContextSetStrokeColorWithColor(ctx,color.CGColor); [img drawAtPoint:CGPointMake(0,0)]; //Left arrow CGPoint leftCenter = CGPointMake(rects.left.origin.x + edgeOffset,rects.left.origin.y + rects.left.size.height/2); CGContextBeginPath(ctx); CGContextMoveToPoint(ctx,leftCenter.x + arrowSize.height,leftCenter.y - arrowSize.width/2); CGContextAddLineToPoint(ctx,leftCenter.x,leftCenter.y); CGContextAddLineToPoint(ctx,leftCenter.y + arrowSize.width/2); CGContextStrokePath(ctx); CGPoint rightCenter = CGPointMake(rects.right.origin.x + rects.right.size.width - edgeOffset,rects.right.origin.y + rects.right.size.height/2); CGContextBeginPath(ctx); CGContextMoveToPoint(ctx,rightCenter.x,rightCenter.y - arrowSize.width/2); CGContextAddLineToPoint(ctx,rightCenter.x + arrowSize.height,rightCenter.y); CGContextAddLineToPoint(ctx,rightCenter.y + arrowSize.width/2); CGContextStrokePath(ctx); CGPoint topCenter = CGPointMake(rects.top.origin.x + rects.top.size.width/2,rects.top.origin.y + edgeOffset); CGContextBeginPath(ctx); CGContextMoveToPoint(ctx,topCenter.x - arrowSize.width/2,topCenter.y + arrowSize.height); CGContextAddLineToPoint(ctx,topCenter.x,topCenter.y); CGContextAddLineToPoint(ctx,topCenter.x + arrowSize.width/2,topCenter.y + arrowSize.height); CGContextStrokePath(ctx); CGPoint bottomCenter = CGPointMake(rects.bottom.origin.x + rects.bottom.size.width/2,rects.bottom.origin.y + rects.bottom.size.height - edgeOffset); CGContextBeginPath(ctx); CGContextMoveToPoint(ctx,bottomCenter.x - arrowSize.width/2,bottomCenter.y); CGContextAddLineToPoint(ctx,bottomCenter.x,bottomCenter.y + arrowSize.height); CGContextAddLineToPoint(ctx,bottomCenter.x + arrowSize.width/2,bottomCenter.y); CGContextStrokePath(ctx); UIImage* imgWithButtons = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); _fullImage = imgWithButtons; } -(UIImage*)subImageInRect:(CGRect)rect fromImage:(UIImage*)image { UIGraphicsBeginImageContext(rect.size); [image drawInRect:CGRectMake(-rect.origin.x,-rect.origin.y,image.size.width,image.size.height)]; UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } -(ButtonRects)buttonRects { UIImage* img = self.fullImage; CGSize size = self.watchSize; CGFloat topHeight = size.height * .25; CGFloat bottomHeight = size.height * .25; CGFloat middleHeight = size.height * .5; CGRect topRect = CGRectMake(0,size.width,topHeight); CGRect leftRect = CGRectMake(0,topHeight,img.size.width/2.0,middleHeight); CGRect rightRect = CGRectMake(img.size.width/2.0,middleHeight); CGRect bottomRect = CGRectMake(0,topHeight + middleHeight,bottomHeight); ButtonRects rects; rects.top = topRect; rects.bottom = bottomRect; rects.left = leftRect; rects.right = rightRect; return rects; } -(void)breakUpForButtons { UIImage* img = self.fullImage; ButtonRects rects = [self buttonRects]; _topImage = [self subImageInRect:rects.top fromImage:img]; _leftImage = [self subImageInRect:rects.left fromImage:img]; _rightImage = [self subImageInRect:rects.right fromImage:img]; _bottomImage = [self subImageInRect:rects.bottom fromImage:img]; } @end
接下来在我的WKInterfaceController类中,我做这个动画.
typedef NS_ENUM(NSInteger,GPWatchImageAnimation) { GPWatchImageAnimationNone,GPWatchImageAnimationSlideLeftToRight,GPWatchImageAnimationSlideRighToLeft,GPWatchImageAnimationSlideTopToBottom,GPWatchImageAnimationSlideBottomToTop,GPWatchImageAnimationZoomIn,GPWatchImageAnimationZoomOut }; #define kNumImagesInMapAnimations 6 #define kMapAnimatinonDuration 0.4 ... -(void)updateMapImageWithAnimation:(GPWatchImageAnimation)animation { GPWatchMapImage* prevIoUsImage = self.currentMapImage; //This gets the size of the full image that you want CGSize size = [self mapSize]; self.currentMapImage = [[GPWatchMapImage alloc] init]; self.currentMapImage.watchSize = size; //Check if we have a prevIoUs image to animate from if (prevIoUsImage != nil && animation != GPWatchImageAnimationNone) { NSDictionary* animatedImage = [self animateFromImage:prevIoUsImage toImage:self.currentMapImage withAnimation:animation]; [self.mapTopImage setImage:[animatedImage objectForKey:@"top"]]; [self.mapLeftImage setImage:[animatedImage objectForKey:@"left"]]; [self.mapRightImage setImage:[animatedImage objectForKey:@"right"]]; [self.mapBottomImage setImage:[animatedImage objectForKey:@"bottom"]]; [self.mapTopImage startAnimatingWithImagesInRange:NSMakeRange(0,kNumImagesInMapAnimations) duration:kMapAnimatinonDuration repeatCount:1]; [self.mapLeftImage startAnimatingWithImagesInRange:NSMakeRange(0,kNumImagesInMapAnimations) duration:kMapAnimatinonDuration repeatCount:1]; [self.mapRightImage startAnimatingWithImagesInRange:NSMakeRange(0,kNumImagesInMapAnimations) duration:kMapAnimatinonDuration repeatCount:1]; [self.mapBottomImage startAnimatingWithImagesInRange:NSMakeRange(0,kNumImagesInMapAnimations) duration:kMapAnimatinonDuration repeatCount:1]; } else { [self.mapTopImage setImage:self.currentMapImage.topImage]; [self.mapLeftImage setImage:self.currentMapImage.leftImage]; [self.mapRightImage setImage:self.currentMapImage.rightImage]; [self.mapBottomImage setImage:self.currentMapImage.bottomImage]; } } -(NSDictionary*)animateFromImage:(GPWatchMapImage*)fromImage toImage:(GPWatchMapImage*)toImage withAnimation:(GPWatchImageAnimation)animation { NSMutableArray* topAnimatedImages = [[NSMutableArray alloc] initWithCapacity:kNumImagesInMapAnimations]; NSMutableArray* bottomAnimatedImages = [[NSMutableArray alloc] initWithCapacity:kNumImagesInMapAnimations]; NSMutableArray* leftAnimatedImages = [[NSMutableArray alloc] initWithCapacity:kNumImagesInMapAnimations]; NSMutableArray* rightAnimatedImages = [[NSMutableArray alloc] initWithCapacity:kNumImagesInMapAnimations]; CGSize size = fromImage.fullImage.size; for (int step = 0; step < kNumImagesInMapAnimations; step++) { UIGraphicsBeginImageContext(size); //render this step if (animation == GPWatchImageAnimationSlideLeftToRight) { CGFloat stepSize = (size.width/2)/kNumImagesInMapAnimations; CGPoint fromPoint = CGPointMake(-(step+1)*stepSize,0); CGPoint toPoint = CGPointMake(size.width/2 - (step+1)*stepSize,0); [fromImage.fullImageWithoutArrows drawAtPoint:fromPoint]; [toImage.fullImageWithoutArrows drawAtPoint:toPoint]; } else if (animation == GPWatchImageAnimationSlideRighToLeft) { CGFloat stepSize = (size.width/2)/kNumImagesInMapAnimations; CGPoint fromPoint = CGPointMake((step+1)*stepSize,0); CGPoint toPoint = CGPointMake(-size.width/2 + (step+1)*stepSize,0); [fromImage.fullImageWithoutArrows drawAtPoint:fromPoint]; [toImage.fullImageWithoutArrows drawAtPoint:toPoint]; } else if (animation == GPWatchImageAnimationSlideTopToBottom) { CGFloat stepSize = (size.height/2)/kNumImagesInMapAnimations; CGPoint fromPoint = CGPointMake(0,(step+1)*stepSize); CGPoint toPoint = CGPointMake(0,-size.height/2 + (step+1)*stepSize); [fromImage.fullImageWithoutArrows drawAtPoint:fromPoint]; [toImage.fullImageWithoutArrows drawAtPoint:toPoint]; } else if (animation == GPWatchImageAnimationSlideBottomToTop) { CGFloat stepSize = (size.height/2)/kNumImagesInMapAnimations; CGPoint fromPoint = CGPointMake(0,-(step+1)*stepSize); CGPoint toPoint = CGPointMake(0,size.height/2 - (step+1)*stepSize); [fromImage.fullImageWithoutArrows drawAtPoint:fromPoint]; [toImage.fullImageWithoutArrows drawAtPoint:toPoint]; } else if (animation == GPWatchImageAnimationZoomOut) { CGFloat yStepSize = (size.height/2)/kNumImagesInMapAnimations; CGFloat xStepSize = (size.width/2)/kNumImagesInMapAnimations; //CGRect fromRect = CGRectMake((step + 1)*xStepSize,(step + 1)*yStepSize,size.width - 2*(step + 1)*xStepSize,size.height - 2*(step + 1)*yStepSize); CGRect toRect = CGRectMake(-size.width/2 + (step+1)*xStepSize,-size.height/2 + (step+1)*yStepSize,size.width + 2*(kNumImagesInMapAnimations - step - 1)*xStepSize,size.height + 2*(kNumImagesInMapAnimations - step - 1)*yStepSize); [toImage.fullImageWithoutArrows drawInRect:toRect]; //double alpha = (double)(kNumImagesInMapAnimations - step - 1)/(double)kNumImagesInMapAnimations; //CGContextSetAlpha(UIGraphicsGetCurrentContext(),alpha); //[fromImage.fullImageWithoutArrows drawInRect:fromRect]; //CGContextSetAlpha(UIGraphicsGetCurrentContext(),1.0); } else if (animation == GPWatchImageAnimationZoomIn) { if (step == kNumImagesInMapAnimations -1) { [toImage.fullImageWithoutArrows drawAtPoint:CGPointMake(0,0)]; } else { CGFloat yStepSize = (size.height/2)/kNumImagesInMapAnimations; CGFloat xStepSize = (size.width/2)/kNumImagesInMapAnimations; CGRect fromRect = CGRectMake(-(step + 1)*xStepSize,-(step + 1)*yStepSize,size.width + 2*(step + 1)*xStepSize,size.height + 2*(step + 1)*yStepSize); //CGRect toRect = CGRectMake(-size.width/2 + (step+1)*xStepSize,size.height + 2*(kNumImagesInMapAnimations - step - 1)*yStepSize); [fromImage.fullImageWithoutArrows drawInRect:fromRect]; //[toImage.fullImageWithoutArrows drawInRect:fromRect]; } } else { [toImage.fullImageWithoutArrows drawAtPoint:CGPointMake(0,0)]; } UIImage* stepImg = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //Get each of the pieces of the image GPWatchMapImage* mapImage = [[GPWatchMapImage alloc] init]; mapImage.showMapArrows = self.showMapArrows; mapImage.fullImage = stepImg; mapImage.watchSize = [self mapSize]; [topAnimatedImages addObject:mapImage.topImage]; [bottomAnimatedImages addObject:mapImage.bottomImage]; [leftAnimatedImages addObject:mapImage.leftImage]; [rightAnimatedImages addObject:mapImage.rightImage]; } UIImage* topAnimatedImage = [UIImage animatedImageWithImages:topAnimatedImages duration:kMapAnimatinonDuration]; UIImage* bottomAnimatedImage = [UIImage animatedImageWithImages:bottomAnimatedImages duration:kMapAnimatinonDuration]; UIImage* leftAnimatedImage = [UIImage animatedImageWithImages:leftAnimatedImages duration:kMapAnimatinonDuration]; UIImage* rightAnimatedImage = [UIImage animatedImageWithImages:rightAnimatedImages duration:kMapAnimatinonDuration]; return @{@"top": topAnimatedImage,@"bottom": bottomAnimatedImage,@"left": leftAnimatedImage,@"right": rightAnimatedImage}; }