是否可以将视图置于彼此之上 [英] Is it possible to position views on top of each other

查看:93
本文介绍了是否可以将视图置于彼此之上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个Watch应用程序,我希望将WKInterfaceImage与一组带有一堆WKInterfaceLabel对象的组重叠。似乎无法在StoryBoard编辑器中执行此操作。

I am building an Watch app where I want to overlay WKInterfaceImage with a group with a bunch of WKInterfaceLabel objects. Can't seem to be able to do this in StoryBoard editor.

有没有人能够在Watch App上实现彼此之间的视图?

Has anyone ever been able to achieve laying out views on top of each other for Watch App?

PS。我知道WKInterfaceGroup的setBackgroundImage方法。因为我想在WKInterfaceImage中做一些动画,所以setBackgroundImage不会让我感到悲哀

PS. I am aware of WKInterfaceGroup setBackgroundImage method. Since I want to do some animation inside WKInterfaceImage, setBackgroundImage is not going to woe for me

推荐答案

你不能在WKInterfaceObjects上布局彼此顶部。您可以在图像上渲染标签,然后进行设置。您必须为动画的每个帧渲染标签。我在我的手表应用程序中为按钮执行此操作。我生成的图像是我的UI的一大部分,然后生成动画的每个帧并覆盖每个帧的按钮文本。然后剪切每帧的图像,以便我可以在每个按钮上设置动画。当您使用该应用程序时,它看起来像是按钮下的动画,实际上它是4个不同按钮中的4种不同的动画。

You can't layout WKInterfaceObjects on top of each other. You can render the labels over your image and then set it. You will have to render the labels for each frame of the animation. I do this in my watch app for buttons. I generate an image that is a large piece of my UI, I then generate each frame of the animations and overlay the button text for each frame. Then a cut up the image for each frame so that I can the animations on each of the buttons. When you use the app it looks like the image is animating under the buttons, when in actuality it is 4 different animations in 4 different buttons.

编辑

我想我会添加更多细节。这是我的应用程序的屏幕截图。我猜你想要做类似的事情。

I figured I would add some more detail. Here is a screen capture of my app. I am guessing that you want to do something similar.

首先,在我的故事板中,您需要确保您的群组的间距为零。

First in my storyboard you need to make sure that the spacing for your groups in zero.

< img src =https://i.stack.imgur.com/atfSZ.pngalt =在此处输入图像说明>

要创建此UI我使用这个助手类。我已经编辑了这个课程,专注于所需的部分。

To create this UI I use this helper class. I have edited this class to focus on just the needed parts.

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类中这样做是为了制作动画。

Next in my WKInterfaceController class I do this to make the animations.

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};
}

这篇关于是否可以将视图置于彼此之上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆