Why is ScrollView's automated layout a difficult point?
To ScrollView do automatic layout, nothing but want to scrollview inside the subviews to do automation layout. But ScrollView inside of the Subviews automation layout is not determined by the aspect of ScrollView, but by the scrollview of Contentsize together to decide, so there is a problem, Even if the scrollview aspect is changed, but as long as the contentsize unchanged, then the scrollview inside of the subviews of the high is actually no impact. The nslayoutconstraint of automatic layout can not realize the automatic layout of the Contentsize property of ScrollView. The pure way to use Nslayoutconstraint to automate the layout of ScrollView is not feasible.
Here we will change a method, in fact, we usually use scrollview more scenes are used to do up and down scrolling or left and right scrolling, there are very few scroll and left and right scrolling at the same time there is a situation. Now assume that the ScrollView of our automation layout is to scroll up and down, in the horizontal direction, the width of the subviews is always consistent with the width of ScrollView, such a scenario can not be achieved? For such a scene we can immediately think of, as long as the width of the subviews with the Nslayoutconstraint implementation with the width of the scrollview binding on it.
Uiscrollview *scroll=[[Uiscrollview alloc] init]; Scroll.backgroundcolor=[Uicolor Bluecolor]; Scroll.isbindsizetosuperview=YES; [Self.view Addsubview:scroll]; [Scroll Setcontentsize:cgsizemake ( -, +)]; UILabel*label = [[UILabel alloc] Initwithsize:cgsizemake ( -, -)]; Label.backgroundcolor=[Uicolor Blackcolor]; Label.textcolor=[Uicolor Whitecolor]; Label.font=[uifont systemfontofsize: A]; Label.text=@"Label1"; Label.translatesautoresizingmaskintoconstraints=NO; Label.textalignment=Nstextalignmentcenter; [Scroll Addsubview:label]; [Scroll Addconstraint:[nslayoutconstraint Constraintwithitem:label A Ttribute:nslayoutattributewidth relatedby:nslayoutrelationequal Toitem:scroll Attribute:NSLayoutAttributeWidth Multiplier:1.0fconstant0]];
We found it possible to do so! Don't worry, you try to add another subview look? You will find that using this method, although the width of the subviews is consistent with the width of the scrollview, it is not possible to lay out the order vertically. What is this for?
The problem is that translatesautoresizingmaskintoconstraints this property we set no, why set no? As long as we use automatic layout, or more generally, as long as we use nslayoutconstraint, we have to set this property to No. When no is set, the position and size of the view can only be achieved by Nslayoutconstraint. Said here, read my first three blog students can think, not have a uistackpanel just can achieve such a function? That's right. We can use it directly, add Uistackpanel Subview to ScrollView, and add subviews to StackPanel that would have been added to Scrollvew. This will enable the above scenario to be achieved. However, there is still a problem, that is, the width of stackpanel we can be bound to the width of scrollview, but the height of it? Height must be tied to Contentsize's height. To achieve such a requirement, we have to use iOS KVO technology to get the ScrollView Contentsize property Change event and bind again. In this way, the above requirements can be fully realized.
In order to carry out the above implementation process in a package, we added a Bindtoscrollview method inside the UIPanel.
NSString *ConstKvcuipanelstring_contentsize =@"scrollview_contentsize";-(void) Bindtoscrollview: (Uiscrollview *) scrollview{_scrollview=ScrollView; Self.translatesautoresizingmaskintoconstraints=NO; [ScrollView addconstraint:[nslayoutconstraint Constraintwithitem:self Attribute:nslayoutattributeleft relatedby:nslayoutrelationequal Toitem:scrollview Attribute:NSLayoutAttributeLeft Multiplier:1.0fconstant0]]; [ScrollView addconstraint:[nslayoutconstraint Constraintwithitem:self Attribute:nslayoutattributewidth relatedby:nslayoutrelationequal Toitem:scrollview attribute: Nslayoutattributewidth Multiplier:1.0fconstant0]]; [ScrollView addconstraint:[nslayoutconstraint Constraintwithitem:self Attribute:nslayoutattributetop relatedby:nslayoutrelationequal Toitem:scrollview Attribute:NSLayoutAttributeTop Multiplier:1.0fconstant0]]; [ScrollView addobserver:self forkeypath:kvcuipanelstring_contentsize options:nskeyvalueobservingoptionnew Context: NIL]; [Self addconstraint:[nslayoutconstraint constraintwithitem:self attrib Ute:nslayoutattributeheight relatedby:nslayoutrelationequal Toitem:nil Attribute:nslayoutattributenotanattribute Multiplier:1.0fConstant:[scrollview Contentsize].height]];//The first time you bind the ScrollView contentsize.height as a panel height}-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID)ObjectChange: (nsdictionary *) Change context: (void*) context{if([KeyPath isequaltostring:kvcuipanelstring_contentsize]) {[Self removeConstraints:self.constraints]; [Self Addconstraint:[nslayoutconstraint constraintwithitem:self at Tribute:nslayoutattributeheight relatedby:nslayoutrelationequal Toitem:nil attribute: Nslayoutattributenotanattribute Multiplier:1.0fconstant:[(Uiscrollview *)ObjectContentsize].height]]; }}
Always remember to release when using KVO.
-(void) removefromsuperview{ [Super Removefromsuperview]; if (_scrollview) { [_scrollview removeobserver:self forkeypath:kvcuipanelstring_contentsize Context:nil]; _scrollview=nil; }}
The method is already encapsulated, so the latter is how to use it. The code is as follows:
//Initialize UiscrollviewUiscrollview *scroll=[[Uiscrollview alloc] init]; Scroll.backgroundcolor=[Uicolor Bluecolor]; Scroll.isbindsizetosuperview=yes;//bind the Uiscrollview high-wide to the parent view[Self.view Addsubview:scroll]; [Scroll Setcontentsize:cgsizemake ( -, +)];//set the contentsize of UiscrollviewUistackpanel*_panel=[[Uistackpanel alloc] init]; [Scroll Addsubview:_panel]; _panel.backgroundcolor=[Uicolor Yellowcolor]; [_panel Bindtoscrollview:scroll];//bind Uistackpanel to UiscrollviewUILabel*label = [[UILabel alloc] Initwithsize:cgsizemake ( -, -)]; Label.backgroundcolor=[Uicolor Blackcolor]; Label.textcolor=[Uicolor Whitecolor]; Label.font=[uifont systemfontofsize: A]; Label.text=@"Label1"; Label.textalignment=Nstextalignmentcenter; [_panel Addsubview:label]; Label= [[UILabel alloc] Initwithsize:cgsizemake ( -, -)]; Label.backgroundcolor=[Uicolor Blackcolor]; Label.textcolor=[Uicolor Whitecolor]; Label.font=[uifont systemfontofsize: A]; Label.text=@"Label2"; Label.margin=uiedgeinsetsmake (Ten,0,0,0); Label.textalignment=Nstextalignmentcenter; [_panel Addsubview:label];
At this point, Uiscrollview's automation solution has been completed.
The next time you introduce how UIView is docked in Superview, it does not change the docking position of UIView regardless of how the aspect of Superview is changed.
The source code for this article will be given in the next article.
IOS Auto Layout-uistackpanel and Uigridpanel (iv)