是否可以将视图置于彼此之上?
我正在构build一个Watch应用程序,我想用一堆WKInterfaceLabel对象将WKInterfaceImage与一个组进行叠加。 似乎无法在StoryBoard编辑器中做到这一点。
有没有人能够实现观看应用程序的彼此顶部的意见?
PS。 我知道WKInterfaceGroup setBackgroundImage方法。 因为我想在WKInterfaceImage中做一些animation,setBackgroundImage不会为我而悲伤
您不能将WKInterfaceObjects排列在彼此之上。 您可以将标签渲染到图像上,然后进行设置。 您将必须为animation的每个框架呈现标签。 我在我的手表应用程序button做这个。 我生成的图像是我的UI的一大块,然后生成每帧的animation并覆盖每帧的button文本。 然后剪切每帧的图像,以便我可以在每个button上的animation。 当你使用应用程序,它看起来像图像是button下的animation,实际上它是4个不同的button中的4个不同的animation。
编辑
我想我会添加更多的细节。 这是我的应用程序的屏幕截图。 我猜你想要做类似的事情。
首先在我的故事板中,您需要确保您的组的间距为零。
为了创build这个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, 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.x + arrowSize.height, 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.x, 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, 0, size.width, topHeight); CGRect leftRect = CGRectMake(0, topHeight, img.size.width/2.0, middleHeight); CGRect rightRect = CGRectMake(img.size.width/2.0, topHeight, img.size.width/2.0, middleHeight); CGRect bottomRect = CGRectMake(0, topHeight + middleHeight, size.width, 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类,我做这个animation。
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 + (step+1)*yStepSize, size.width + 2*(kNumImagesInMapAnimations - 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}; }
在InterfaceBuilder中:您可以使用一个组,并从您的资产中设置Backgroundimage。 当你添加一个WKInterfaceImage到这个组中时,你可以使用两个图层(如果两个图层对你来说足够了)。