我正在构建一个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};
- }