“This paper has been involvedWeekend Study plan, click for details”
This is the sixth day of my participation in the Gwen Challenge.More article challenges
UI, the bane of iOS development
If you’ve only ever worked on iOS, you’ll find SnapKit (OC for navigation) handy, and even XIb dragging works fine.
It’s all part of the normal routine of iOS development.
But once you’ve learned how to write UI components with Flutter/Vue, iOS UI writing is truly untouchable and primitive.
Android’s UI next door isn’t particularly user-friendly either, but it’s still better than iOS.
Why? Because the rest of UI programming is basically what you see and what you get, and you make mistakes and you debug them as you go along
Only iOS needs to compile and debug… Compile debug… Compile debug…
The CSS in the front-end of the Flutter can be found in some components with the same name. Let’s take an example to illustrate the simplicity and assimilation of the building UI of the Flutter:
The following UI can be implemented with Flutter, H5 and iOS:
Flutter:
Wrap(children: model.children.map ((topic) => Padding(Padding: EdgeInsets. All (3.0), child: Chip( materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, key: ValueKey<String>(topic.name), backgroundColor: _getChipBgColor(topic.name), label: Text(topic.name, style: TextStyle(fontSize: 14.0),),),).tolist ();Copy the code
H5:
<view class="flex-wrap" v-for="(item, index) in list" :key="index">
<u-tag :text="item.name" :index="item.name" @click="click" />
</view>
<style scoped lang="scss">
.flex-wrap {
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
width: auto;
height: auto;
margin: 16rpx;
}
</style>
Copy the code
iOS:
I need too much code, so HERE I post T_T
Both Flutter and H5 use wrap as their layout idea. Flutter has a wrap component, while H5 uses flex-wrap CSS. IOS does not.
The situation is that even though the design draft and UI elements are similar to iOS, Flutter and H5 actually have very mature official components or third parties on their components, while iOS does not… Plus no thermal overload…
But while the iOS layout is not working, or even not working, SnapKit at least gives you a little bit of hope. Let’s take a look at the same layout, using the iOS native layout and SnapKit layout code amount.
IOS native layout VS SnapKit layout
Ios native Layout:
contentView.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
addConstraint(NSLayoutConstraint(item: imageView,
attribute: .leading,
relatedBy: .equal,
toItem: contentView,
attribute: .leading,
multiplier: 1,
constant: 0))
addConstraint(NSLayoutConstraint(item: imageView,
attribute: .top,
relatedBy: .equal,
toItem: contentView,
attribute: .top,
multiplier: 1,
constant: 0))
addConstraint(NSLayoutConstraint(item: imageView,
attribute: .trailing,
relatedBy: .equal,
toItem: contentView,
attribute: .trailing,
multiplier: 1,
constant: 0))
addConstraint(NSLayoutConstraint(item: imageView,
attribute: .bottom,
relatedBy: .equal,
toItem: contentView,
attribute: .bottom,
multiplier: 1,
constant: 0))
Copy the code
SnapKit layout:
contentView.addSubview(imageView)
imageView.snp.makeConstraints { make in
make.edges.equalTo(contentView)
}
Copy the code
Use native layout or SnapKit, I don’t need to say more.
SnapKit use, precautions and confusion
As for the projects I have done so far, even if it contains a large number of XIBs, SnapKit or navigation will be used. Although it is only a layer of packaging of the native Api, its chain call and functional programming ideas are worth learning and drawing lessons from. Here are some experiences about using SnapKit:
Before using SnapKit, you must first add child controls to the superview
parentView.addSubview(subview)
Always always always add child controls to the parent view before layout, otherwise it will crash!!
Leading and left, trailing and right
In China, the usage of leading and left, trailing and right are equivalent in normal cases, because the domestic reading habit is left to right, but if your App needs to be displayed in Arab countries, the layout of the App is right to left (for example, in Arabic).
My personal habit is to use leading and trailing, which may have something to do with my internationalization.
Add, update constraints, reference constraints, disable, enable controls
- Add new constraints
contentView.addSubview(imageView)
imageView.snp.makeConstraints { (make) in
}
Copy the code
- Delete all previous constraints of the control and add new constraints
Because the imageView is already added to the contentView, this spinner does not need to call the addSubview method
imageView.snp.remakeConstraints { (make) in
}
Copy the code
- Update constraints, update as you write, other constraints remain the same
When updating a constraint, however, it may crash. I have experienced this while doing an update in the cell and am trying to determine the cause of the crash. If this crashes, you may want to use the layout of the existing control in remakeConstraints, which may cost a bit of performance but is better than crashing.
imageView.snp.updateConstraints { (make) in
}
Copy the code
- A reference constraint that declares a local variable or class attribute to reference the constraint to be modified
It is important to note that topConstraint uses an optional type, which ensures that calls to deactivate() and activate() methods will not crash when null. Also set as a global variable, easy to call in a variety of situations.
var topConstraint: Constraint? = nil
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView()
view.addSubview(imageView)
imageView.snp.makeConstraints { (make) in
self.topConstraint = make.left.equalToSuperview().offset(100).constraint
make.right.equalToSuperview().offset(-100)
make.top.equalToSuperview().offset(100)
make.bottom.equalToSuperview().offset(-100)
}
}
Copy the code
disable
topConstraint? .deactivate()Copy the code
To enable the
topConstraint? .activate()Copy the code
Setting constraints
The constraint relations | instructions |
---|---|
equalTo() | Sets the property to be equal to a value |
greaterThanOrEqualTo() | Sets the property to be greater than or equal to a value |
lessThanOrEqualTo() | Sets the property to be less than or equal to a value |
multipliedBy() | Sets the value of a property multiplied by a factor |
multipliedBy() | Sets the value of a property divided by a factor |
Sets control layout properties
The constraint relations | instructions |
---|---|
size | Size CGSize |
Width, height, | The width and the height |
left | The left margin |
top | The top margin |
right | The right margin |
bottom | At the bottom of the margin |
Center, centerX, centerY | The center of the x and y axes, the center of the x axis, the center of the y axis |
leading | The margin at the beginning of a reading habit |
trailing | The margins at the end of reading habits |
Set constraint offset
methods | parameter | instructions |
---|---|---|
offset | CGFloat | How much a control property is offset from its reference |
insets(MASEdgeInsets insets) | UIEdgeInsets | How much the edges of the control are offset with respect to the reference |
Two examples:
imageView.snp.makeConstraints { (make) in
make.left.equalToSuperview().offset(20)
make.right.equalToSuperview().offset(-20)
make.top.equalToSuperview().offset(20)
make.bottom.equalToSuperview().offset(-20)
}
Copy the code
/ / / specific parent controls are surrounded by 20 spacing imageView. SNP. MakeConstraints {(make) in the make. Edges. EqualToSuperview () an inset (UIEdgeInsets (top: 20, left: 20, bottom: 20, right: 20)) }Copy the code
The second form has the same effect as the first form written by left, right, top and bottom, except that the form of organization language is different. SnapKit’s programming method is organized by Swift, but it is more encoded by its own DSL.
Set the constraint priority
- SnapKit provides three default methods, required, high, Medium, and Low, with a maximum priority of 1000
Public static var required: ConstraintPriority {return 1000.0} public static var high: ConstraintPriority {return 750.0} public static var medium: ConstraintPriority {#if OS (OSX) return 501.0 #else return 500.0 #endif} public static var low: ConstraintPriority {return 250.0}Copy the code
Set your own priority value, which can be set using the priority() method
imageView.snp.makeConstraints { (make) in
make.center.equalToSuperview()
make.width.equalTo(100).priority(ConstraintPriority.low)
make.height.equalTo(50).priority(800)
}
Copy the code
In fact, I seldom use this priority in the development process, and it still needs more learning and exploration.
SnapKit and UIScrollView
Many novices will often find the ScrollView stuck when placing child controls into UIScrollView for layout.
First, understand the core idea: UIScrollView depends on constraints with its subview to determine the size of its ContentSize. Why do you say that?
That’s because UIScrollView is a very special UIView, and for the subview of UIScrollView, Its leading/trailing/top/bottom of space is relative to the UIScrollView contentSize rather than bounds to determine, in other words: The constraint on the position of the UIScrollView relative to its subView is not applied directly to the calculation of the frame, but is translated into the calculation of the contentSize. When the UIScrollView knows where the upper, lower, left, and right constraints point to in the subview, once the subview position is fixed, the UIScrollView contentSize is determined.
But when we try to use UIScrollView and its subview of leading/trailing/top/bottom to decide the size of each other, Warning Has ambiguous scrollable Content width/height
As a rule of thumb, it is customary to add a contentView between the UIScrollView and its original subviews, relying on the contentView to determine the contentSize.
The code is shown below:
class ViewController: UIViewController { lazy let scrollView = UIScrollView() lazy let contentView = UIView() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white view.addSubview(scrollView) scrollView.snp.makeConstraints { (make) in Make. Edges. EqualTo (view)} / / / add container view scrollView. AddSubview (contentView) contentView. SNP. MakeConstraints {(make) in Make.top.bottom. EqualTo (scrollView) make.left. Right. EqualTo (view) } let label1 = UILabel() // Notice the component added to the contentView, Contentview.addsubview (label1) label1.numberoflines = 0 label1.backgroundColor =.yellow label1.snp.makeConstraints { (make) in make.left.right.equalTo(contentView).inset(20) Make.top.equalto (contentView).offset(20)} let label2 = UILabel() AddSubview (Label2) label2.numberoflines = 0 label2.backgroundColor =.red label2.snp.makeConstraints { (make) in make.left.right.equalTo(label1) make.top.equalTo(label1.snp.bottom).offset(20) /// The bottom constraint must be added to tell the contentView where it is, otherwise the contentSize cannot be determined. Make. Bottom. EqualToSuperview ()} label1. Text = "" "hi, dig the friends! Do you find out why some programmers have the same skill level, some get more promotions and raises, and some don't look for jobs, but there are always jobs for them? Under the same "hardware" condition, why the competitiveness is not the same? One of the main reasons is that people have different influences. Blog, share, open source... These are all ways to increase their influence. Many technologists even turn their side business into their main business by exporting their technical knowledge and experience. Of course, such influence is not a day to develop overnight, need to continue to output, accumulated momentum. Many people also set up a Flag to write something every day, but always can not adhere to two days, Flag fell, fell, has not been positive feedback, and finally they are discouraged. This time, we help you develop a good habit of long-term adherence and positive motivation, and help stabilize the Flag! """ label2.text = """ Wang will earn up to $3,000 worth of prizes, such as the Gopro Hero8, for his 28 days alone. If wang is hit by both the lucky jackpot, he will have to choose between the lucky jackpot and the first prize. Wang and li completed the 27-day challenge, wang and li each won 1500 yuan equivalent prizes, such as AirPos2 generation. In addition to the first prize, xiao Li will also receive the attendance award after 30 days. A total of 6 people, including Xiao Wang, completed the 27-day wen challenge, and each of them could choose an equivalent prize within 833 yuan. Xiao Wang has been practicing for 23 days and can choose one of the second or third prizes. "" "}}Copy the code
If the text is not enough to make the scrollView slide, write as many strings as you like in text in Label1 and label2.
Other options
With the evolution of mobile apps towards a large front-end, UI development tools for iOS and Android are now evolving towards declarative development. SwiftUI for iOS, ComposeUI for Android, and Flutter, which is cross-platform, are basically the same template, but with different languages.
There is also a FlexLib library in OC for iOS.
The layout framework is based on the Flexbox model, which is the web side layout standard. Based on the Flexbox model, FlexLib offers great layout capabilities and is easy to use.
A colleague has done it before, and those who have used it have said yes, and I’m going to explore it.
Tomorrow to continue
I have finally finished the weekend update. Recently, there are many interactions between iOS and H5 at work, so I think I will interrupt some questions on work next week for archiving. Please bear with me.