Relativelayout or LinearLayout in ios iphone development?

前端 未结 6 653
再見小時候
再見小時候 2021-02-08 15:23

I want to add a subview in the top of my view, I have to recalculate the origin y value for all of other views and re-position them to leave space for the new added view.

<
相关标签:
6条回答
  • 2021-02-08 15:37

    You've got no luck here. iOS doesn't have provisions for positioning the views in different layouts like Android. You need to reposition all the other subviews to make the way for the new view.

    There are some view resizing methods like sizeToFit and autoResizingMask but they won't help you in your case here.

    0 讨论(0)
  • 2021-02-08 15:37

    iOS is much more focused on pixel accuracy than Android it is, which uses relative layouts as it has to deal with multiple screen sizes. However, in iOS, the Interface Builder is an incredibly good tool included in XCode, which you can use.

    Also, if you are just adding subviews in a repetitive manner, you could override the layoutSubviews method and use that to handle to manual labour for you. You mention having to "recalculate the origin y value for all of other views and re-position them to leave space for the new added view" ... You could code that into your layoutSubviews so you don't have to do it yourself each time.

    Unfortunately, though, the SDK doesn't have any of this included by default. autoresizingMask's are great but you can't use that for initial layout; it's for automatic really it when rotating only.

    0 讨论(0)
  • 2021-02-08 15:37

    As of iOS 9 you can use UIStackView, which works very similarly to LinearLayout: you add views and the stack view arranges them as needed based on your sizing preferences:

    • Fill will leave three of them their natural size, and make the fourth one take up the most space. It uses Auto Layout's content hugging priority to decide which one to stretch.

    • Fill Equally will make each subview the same size so they fill all the space available to the stack view.

    • Fill Proportionally uses the intrinsic content size of each subview to resize them by an equal amount. So view 1 was designed to have twice as much height as views 2, 3 and 4, that ratio will remain when they are resized – all the subviews get proportionally bigger or smaller.

    • Equal Spacing does not resize the subviews, and instead resizes the spacing between the subviews to fill the space.

    • Equal Centering is the most complicated, but for many people also the most aesthetically pleasing. It attempts to ensure the centers of each subview are equally spaced.

    You can also set spacing between views in the stack view, adding some padding.

    WARNING: When adding stack view child views in code you should always use addArrangedSubview() like this:

    stackView.addArrangedSubview(someView)
    

    If you try to use plain old addSubview() it won't work correctly, because the stack view won't know to arrange it.

    As for removing, you need to be careful to use stackView.removeArrangedSubview(someView) and someView.removeFromSuperview() otherwise the view won't be removed correctly.

    You might find my UIStackView tutorial useful.

    0 讨论(0)
  • 2021-02-08 15:38

    I've been trying to do a relative (linear) layout for a while and finally decided to just subclass UIScrollView to get it done.

    I started out just replacing layoutSubviews with a simple loop through the subviews that reset the origins while keeping a running Y. But, some unexpected things are added to the scrollview, including UIInlineAutoCorrect views from textfields/views, which means these things were being mangled by the layout. So I added a little bit of logic that uses the tag property of a UIView to determine if I should lay it out:

    -(void) layoutSubviews{
        CGFloat runningY = 0.0f;
        CGFloat widestWidth = 0.0f;
        for (UIView *view in self.subviews) {
            if (view.tag != 1999) {
                continue;
            }
    
            view.origin = CGPointMake(view.origin.x, runningY);
            runningY += view.height;
    
            if ([view autoresizingMask] == UIViewAutoresizingFlexibleWidth) {
                view.width = self.width;
            }
    
    
    
            if (view.width > widestWidth) {
                widestWidth = view.width;
            }
        }
        [self setContentSize:CGSizeMake(widestWidth, runningY)];
    
    }
    

    If you would still like to use unique tags for your views, you should just specify a range of tags that will be included in the layout instead of a single value.

    0 讨论(0)
  • 2021-02-08 15:38

    It's not much work to subclass UIView to make sense of methods like -(void)addView:toRightOfView: etc. You could do this as you go, porting only the methods you need. You could then call these in your override of layoutSubviews as Benjamin indicates.

    Views can be built using IB or they can be written programmatically; Android scores well here in making layouts readable and you can bring that benefit to iOS views created programmatically. That there are few iOS devices means beyond readability there are not (yet?) many practical benefits to this pattern.

    NB. A "XIB" file is an XML file. Open it up in your favourite text editor and take a look.

    ** EDIT.

    Here's a quick example I knocked up. It has not been tested but some thing like this will work in your subclass of UIView (call it UIRelativeView perhaps).

    - (void) addSubview:(UIView *) viewOne
       toRightOfSubview:(UIView *) viewTwo
    {
      if (viewTwo == nil ||
          [self.subviews contains:viewTwo] == NO)
      {
        [self addSubview:viewOne];
      }
      else
      {
        CGRect frameTwo = viewTwo.frame;
        CGPoint originOne = CGPointMake(frameTwo.origin.x + frameTwo.size.width,
                                        frameTwo.origin.y);
    
        CGRect frameOne = CGRectZero;
        frameOne.origin = originOne;
        frameOne.size = viewOne.frame.size;
    
        [viewOne setFrame:frameOne];
        [self addSubview:viewOne];
      }
    }
    
    - (void) moveSubview:(UIView *) viewOne
        toRightOfSubview:(UIView *) viewTwo
    {
      if (viewTwo == nil ||
          [self.subviews contains:viewTwo] == NO)
      {
        [self addSubview:viewOne];
      }
      else if ([self.subviews contains:viewOne] == NO)
      {
        [self addSubview:viewOne toRightOfSubview:viewTwo];
      }
      else
      {
        CGRect frameTwo = viewTwo.frame;
        CGPoint originOne = CGPointMake(frameTwo.origin.x + frameTwo.size.width,
                                        frameTwo.origin.y);
    
        CGRect frameOne = CGRectZero;
        frameOne.origin = originOne;
        frameOne.size = viewOne.frame.size;
    
        [viewOne setFrame:frameOne];
      }
    }
    
    0 讨论(0)
  • 2021-02-08 15:44

    I've created a library to solve just this problem: CSLinearLayoutView

    You use it like this:

    // create the linear layout view
    CSLinearLayoutView *linearLayoutView = [[[CSLinearLayoutView alloc] initWithFrame:self.view.bounds] autorelease];
    linearLayoutView.orientation = CSLinearLayoutViewOrientationVertical;
    [self.view addSubview:linearLayoutView];
    
    // create a layout item for the view you want to display and add it to the layout view
    CSLinearLayoutItem *item = [CSLinearLayoutItem layoutItemForView:someView];
    item.padding = CSLinearLayoutMakePadding(5.0, 10.0, 5.0, 10.0);
    item.horizontalAlignment = CSLinearLayoutItemHorizontalAlignmentCenter;
    item.fillMode = CSLinearLayoutItemFillModeNormal;
    [linearLayoutView addItem:item];
    
    // add more items
    
    0 讨论(0)
提交回复
热议问题