Skip to content Skip to sidebar Skip to footer

Relativelayout Or Linearlayout In Ios Iphone Development?

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. It is ver

Solution 1:

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

Solution 2:

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 inself.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.

Solution 3:

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];
  }
  elseif ([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];
  }
}

Solution 4:

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.

Solution 5:

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.

Post a Comment for "Relativelayout Or Linearlayout In Ios Iphone Development?"