How to Resize a Custom View Programmatically

How to resize a custom view programmatically?


this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, theSizeIWant));

Problem solved!

NOTE: Be sure to use the parent Layout's LayoutParams. Mine is LinearLayout.LayoutParams!

Android set height and width of Custom view programmatically

If you know the exact size of the view, just use setLayoutParams():

graphView.setLayoutParams(new LayoutParams(width, height));

Or in Kotlin:

graphView.layoutParams = LayoutParams(width, height)

However, if you need a more flexible approach you can override onMeasure() to measure the view more precisely depending on the space available and layout constraints (wrap_content, match_parent, or a fixed size). You can find more details about onMeasure() in the android docs.

Programmatically resize custom UIView from XIB

I guess that the main issue is that you do not use auto layout when you add your xib into the content view.

After adding the subview in you init methods please call that method, passing the view of the xib:

- (void) stretchToSuperView:(UIView*) view {
view.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *bindings = NSDictionaryOfVariableBindings(view);
NSString *formatTemplate = @"%@:|[view]|";
for (NSString * axis in @[@"H",@"V"]) {
NSString * format = [NSString stringWithFormat:formatTemplate,axis];
NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:bindings];
[view.superview addConstraints:constraints];
}

}

[EDIT]

Your setup code should look like that:

- (void)setup {
if (self.subviews.count == 0) {
[[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
self.bounds = self.view.bounds;
[self addSubview:self.view];
[self stretchToSuperView:self.view];
}
}

Pay attention that inside stretch view I've added view.translatesAutoresizingMaskIntoConstraints = NO;


[EDIT 2]

I'll try to elaborate my answer as requested. Using autolayout, when you add a view without setting constraints autolayout automatically converts autoresizing masks into constraints the default property of them is UIViewAutoresizingNone that means to do not autoresize.

Your XIB view was added to its parent without constraints and without the possibility of autoresize thus keeping its original size. Since you want that your view to resize accordingly to your view you had two choices:

  • Change the autoresizing masks of your xib view to flexible width and height but they need to match the parent size or you will not have a full cover
  • Add some constraints that constraint the two view to change accordingly to the parent changes. And you achieve that saying between the XIB view and its parent view the space between trailing/leading and top/botton is 0. Is like you are putting some glue on their borders. To do that you need to set the autotranslate resizing mask into constraint to NO, or you can have some conflicts as you posted in the log.


What you are doing later is adding constraints to the view (that hosts the XIB view) to its superview, but there were no constraints between the XIB and its parent, thus autolayout doesn't know how to resize the XIB view.
Each views in a view hierarchy should have its own constraints.
Hope this helps to understand better.

AutoLayout resize custom UIView content

Here comes viewDidLayoutSubviewsto resolve our issue,

Description:

When the bounds change for a view controller's view, the view adjusts the positions of its subviews and then the system calls this method.

Instead of viewDidLoad use viewDidLayoutSubviewsas follows

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let imageTemplateView: ImageTemplateView = ImageTemplateView(frame: frame)
cardView.addSubview(imageTemplateView)
imageTemplateView.clipsToBounds = true
}

UPDATE:

  • Declare variable above viewdidload

    var imageTemplateView: ImageTemplateView = ImageTemplateView()
  • set frame and add it as sub view in viewdidload

    override func viewDidLoad() {
    imageTemplateView = ImageTemplateView(frame: frame)
    cardView.addSubview(imageTemplateView)
    imageTemplateView.clipsToBounds = true
    }
  • In viewDidLayoutSubviews just set the frame alone,so that whenever orientation changes ImageTemplateView's frame will be updated

    override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    imageTemplateView = ImageTemplateView(frame: frame)
    }

Resizing rotated child view in custom ViewGroup subclass


  • You're not recalculating viewRectRotated for your EditText when the
    ViewGroup's onLayout(...) method is called again.
  • Since angleChanged is set to false (and never changes) after your ViewGroups first layout, then the part that calculates the left, right, top and bottom values for your EditText
    is skipped any time after the first time when your ViewGroup
    requestsLayout (when you change its height or width).
  • As such, your EditText is still laid out with the same left,right,top
    and bottom values it was initially laid out with.

Do away with the angleChanged and it should work just fine. Like so:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final RectF layoutRect = tempRectF1;
final RectF layoutRectRotated = tempRectF2;
layoutRect.set(0, 0, right - left, bottom - top);
rotateMatrix.setRotate(angle, layoutRect.centerX(), layoutRect.centerY());
rotateMatrix.postScale(-1, 1);
rotateMatrix.mapRect(layoutRectRotated, layoutRect);
layoutRectRotated.round(viewRectRotated);
final View view = getView();
if (view != null) {
view.layout(viewRectRotated.left, viewRectRotated.top, viewRectRotated.right,
viewRectRotated.bottom);
}
}

I've tested this and it works just fine this way.

If you need angleChanged for any reason, then just make sure it's changed back to true inside your ViewGroup's onMeasure method so that viewRectRotated is recalculated again. However I wouldn't recommend that.



Related Topics



Leave a reply



Submit