简体   繁体   中英

make subview descend from “behind” another subview

Within a UISrollView , I have several programmatically-added subviews representing nodes in a tree:

在此处输入图片说明

Each node's frame includes the node itself plus the line connecting it to its parent. (I did this to facilitate animation of the line with the node.) In the picture below, the frame is drawn for one of the nodes:

在此处输入图片说明

When the user taps on one of the nodes, two child nodes are "born". I'd like to animate this by having the child nodes descend down from behind the parent node. My basic animation code is:

- (void)descendFromParent
{
    // Do nothing if this is root node
    if (!self.parent)
        return;

    // Move node to parent location
    self.frame = CGRectMake(self.frame.origin.x + self.parent.nodeFrame.origin.x - self.nodeFrame.origin.x,
                            self.frame.origin.y + self.parent.nodeFrame.origin.y - self.nodeFrame.origin.y,
                             self.frame.size.width, self.frame.size.height);

    // Animate the move back to original location
    [UIView animateWithDuration:1.0
                          delay:0.0
                        options:0
                     animations:^{
                         self.frame = self.trueFrame;
                     }
                     completion:nil];
}

( nodeFrame is a frame containing just the circular part of the view.)

The problem of course is that as the child node is descending, it (especially the line) is visible on top of and above the parent node:

在此处输入图片说明

I've tried a lot of different ways to make this work -- using CGContextClip , etc. -- but none of them work, mainly because drawRect: isn't called during the animation.

How can I make this work?

You may want to look at the UIView methods

  • -insertSubview:belowSubview:
  • -insertSubview:atIndex:
  • -sendSubviewToBack:

In your case, you can either send the two subviews to the background with -sendSubviewToBack: after you have added them. Or you can just add them with -insertSubview:atIndex: and provide 0 as the index.

I think your problem is not how to arrange the views in the correct view hierarchy, but the following:

After you have arranged the child disks behind the parent disk, you want them to slide down, and while they are sliding, the edge that connects their centers should have first zero length (when all 3 disks are at the same place), and should then be extended until it reaches its final length in the end.

If this is the case, one possible solution would be:

Lets call the initial x,y center coordinate of one disk (0,0), and the final coordinate (X,Y). Using the usual animation code, it is easy to move the child center to (X,Y) in time t.
Now assume you have an additional image view that shows the edge along the diagonal. In the end position, the center of the "edge view" is at (X/2,Y/2), and its size is (X,Y). If this view is placed behind all others, it will connect the two disks at their final position.
The animation consists now of 1) changing the center property from the initial position (0,0) to (X/2,Y/2), and 2) changing the scale of the view (using its transform property ) from zero to the final size, also in time t.
This should do it.

您可以为子视图指定索引,尝试在索引0处插入要设置动画的节点,并使蓝色节点在较高的索引处。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM