nicklockwood / layout

A declarative UI framework for iOS
MIT License
2.23k stars 97 forks source link

View structure changes from code #149

Open algrid opened 5 years ago

algrid commented 5 years ago

Suppose I have a view controller conforming to LayoutLoading and its view structure is created using Layout framework.

Later I want to change its view structure by changing some view frames, adding or removing some views. Am I allowed to do this? Or maybe the only thing I can do is to set the state of my layout node?

I'm asking because I'm getting some weird behavior when I try to change my view structure. Sometimes even when I just change the isHidden property of a view. When I use layoutNode?.setState however everything is fine.

Probably this https://github.com/schibsted/layout/issues/105 is also related to my question.

nicklockwood commented 5 years ago

@algrid this isn't really recommended. Layout wants to control the frames of all views that it creates, so if you change them there's a good chance it will override your changes.

Other properties should be OK to change directly, but note that if you set isHidden then Layout won't automatically move the neighboring views to fill the gap, which it would do if you used Layout to hide the view.

In general, if you are trying to do this, it's probably a sign that you are not using Layout as intended. To set properties in a Layout-controlled view you should normally just call setState() on the Layout node and then specify the values of those properties using expressions in your XML.

If that's not possible for some reason, I'd be interested in understanding your use case, as it may be that Layout can be improved to better support it.

algrid commented 5 years ago

@nicklockwood Thank you for your reply. Actually I'm not having big problems with this and setState() is usually enough.

Mostly my concern is about some custom views that may change its intrinsic size during their lifetime (when I'm using "auto" sizes in my layout). No problems for UILabel or UIImage if we set some text or image via setState. But recently I used this view: https://github.com/evermeer/AttributedTextView and I couldn't figure out how to change its contents in runtime and update my layout. For now I just set a fixed size for it in my layout and set the text from code.

Regarding isHidden - I was changing it from code and after that some view positions were changing but I couldn't figure out the logic (I'm not 100% sure here - have to investigate more).

And one small question about isHidden property - if I set it to true in my XML would that view be added to my view structure? Because I remember some strange issue where I couldn't see such views in "view debugging" mode.

nicklockwood commented 5 years ago

@algrid auto size is based mainly on the intrinsic size of a view, so changing the intrinsic size and calling update should work. In some cases it may update automatically, but that isn't always reliable. I'll have a look at AttributedTextView and see there's a bug in how Layout interacts with it.

Setting isHidden to true in Layout doesn't remove the view from the hierarchy, but it may set its size to zero, which would explain why you couldn't find it in the view debugger.

algrid commented 5 years ago

@nicklockwood When you're talking about "calling update" do you mean self.layoutNode?.update()? I have to try it :)

algrid commented 5 years ago

@nicklockwood just tried update() and with UILabel at least (after its contents change) it works well, thanks!

But with UITextView I found a problem: if I set

        isScrollEnabled="false"
        isEditable="false"

then it seems to have well defined intrinsicContentSize. But Layout seems to ignore it.

nicklockwood commented 5 years ago

@algrid thanks for reporting it, I'll investigate.