ios – 可以将视图放在彼此之上

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

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...