1
gdtdpt 2021-01-15 18:25:18 +08:00
不是专业 App 开发,只是搞过一阵子,我记得 iOS 的默认布局方式就是安卓里的约束布局,只要设置元素自身的约束、元素与元素之间的约束、元素与父元素的约束就能自适应了。
|
2
linKnowEasy 2021-01-15 18:25:48 +08:00
搜一下 SnapKit 自适应 + 你要自适应的控件.
|
3
timelessg 2021-01-15 18:30:30 +08:00 via Android
本质还是 autolayout 的问题,首先子 view 需要有 contentsize,也就是子 view 要先把自己撑起来,其次各个子 view 之间的约束要设对,这样才会撑起来父 view
|
4
Xcution OP |
6
finab 2021-01-15 18:33:33 +08:00
布局应该不需要确切的 高度,可以把你要的布局说一说
|
7
linKnowEasy 2021-01-15 18:37:16 +08:00
|
8
cincout 2021-01-15 18:47:23 +08:00
给你打了一堆字,然后发现我并不擅长给别人讲解。。。还是给你个思路吧,其实很简单,想要自适应内容的高度,你得让内容的上下约束都固定在 contentView 上,且保证内容自身有高度,如果是多行 UIlabel,得保证 UIlabel 有固定宽度。
|
9
imkerberos 2021-01-15 18:48:38 +08:00
FlexBox, 你值得拥有。
|
10
everhere 2021-01-15 19:08:30 +08:00
snapkit 可以设置宽高,比如
make.width.equalTo make.height.equalTo |
11
Building 2021-01-15 19:15:10 +08:00
你就没有想过 Android 虽然不用写高度,那高度怎么来的?肯定还是要算的啊,子视图没有高度,那么肯定有一个高度确定的父容器,然后通过约束计算得出子视图的高度。
|
12
ooops 2021-01-15 20:13:07 +08:00
把个 AutoLayout 的教程系统的看一下吧,现在这么问没法回答。
|
13
yikuo 2021-01-15 21:19:56 +08:00 via Android
这其实跟 snapkit 没关系,iOS 的 autolayout 布局方式就是这样的。有的地方可以使用 UIStackView 来简化约束。至于获取不到宽高,是因为你获取的时候 UI 还没计算出真正的大小,这里有两个选择:只用约束不要手动设置宽高,或者在 layoutsubview 之后再获取宽高。我个人觉得 Android 的布局比 iOS 简单很多,Android 有多种布局方式组合使用,可以专心布局,而 iOS 就只有 frame 和 autolayout 以及 UIStackView 了,需要耗费很多精力在调整位置和大小上面。
|
14
StyxS 2021-01-15 21:35:30 +08:00
优先级和抗伸缩性
|
15
ydatong 2021-01-15 22:08:05 +08:00
可以看看 uistackview,一般的布局能省不少事
|
16
Baymaxbowen 2021-01-15 23:15:49 +08:00 via iPhone
equal to superview offset
|
17
coloz 2021-01-15 23:17:45 +08:00
为什么不选择跨平台的开发方式呢,搞两套 app 太累了
|
18
vincentxue 2021-01-15 23:20:21 +08:00 1
不是你没弄对,而是 iOS 的布局系统以及它的命令式 UI 开发体验跟 Android 比简直就是一坨屎,更别提和 Web 比了。
iOS 的 Auto Layout 基本上等同于 Android 中的 ConstraintLayout,都是基于约束的布局系统。最大的不同点在于 iOS 中控件的尺寸基本上除了 UILabel / UITextView (相当于 Android 中的 TextView )、UIButton (相当于 Android 中的 *Button )、UIImageView (相当于 Android 中的 ImageView )之类有内容的控件还有一些系统固定尺寸的控件(如 UISegmentedControl 、UISearchBar 等)外,都是没有默认尺寸的。它们的尺寸是基于约束计算出来的。 如果你在 Android 中用过 Google 的 FlexboxLayout,在 iOS 上推荐你用 https://github.com/layoutBox/FlexLayout 这个库。 它是基于 Facebook 开源的 Flexbox 布局引擎 Yoga 实现的,非常好用。百分百找回 Android 上的感觉。iOS 中有个叫 UIStackView 的控件实现了一些类似于 Flexbox 的控件组织方式,但是和真正的 Flexbox 还是差的太远了。 但是说到底,iOS 最好还是要用 Auto Layout 来布局,因为这个才是最 Native 的布局方式。你用其他的布局方式之前,至少要搞投 Auto Layout 。 你有兴趣的话可以加我的 tg 我给你解答,移动端是我的老本行,搞了十来年了,大家互相学习。 |
19
oko 2021-01-15 23:28:17 +08:00
自动布局老心酸了,早已放弃,改用手动布局了,虽然烦了一点,但是手动控制每一个像素的感觉还是很美妙的
|
20
Sixi 2021-01-16 00:20:54 +08:00 via iPhone
楼主的意思我懂,以前也是从这些坑里慢慢爬出来的。
假如使用 SnapKit 为一个 View 添加约束之后,想要获取这个 View 的 宽高(实际上也就是 frame 值),但总是是 0 。这是因为你获取宽高的代码在你的 SnapKit 代码前执行,此时 View 并没有布局,默认的 frame 值均是 0,所以获取不到的。 |
21
vincentxue 2021-01-16 03:44:06 +08:00 2
我来补充一下楼上的回复。准确地说,SnapKit ( Auto Layout ) 的代码只是描述了约束。Auto Layout 相比传统的手动布局多了一步更新约束的操作,对应的是 updateConstraints 方法,约束代码通常要放在这里面,约束是从下到上的,所以 super 是放在最后的。这个方法被系统调用之后,View 还没有完成布局,也没有 frame 。直到 layoutSubviews 被调用,这个时候约束才会被转换成具体的 frame,布局是从上到下的,所以要先调用 super 。Auto Layout 推出之前,都是覆盖这个方法来写 frame 的。Auto Layout 推出之后,这个方法主要是用来在布局完成之后做一些操作的。
如果你想要在布局完成之前拿到一个 View 的 size,系统给你提供了三个方法,intrinsicContentSize 、sizeThatFits: 和 systemLayoutSizeFittingSize:。这三个方法具体的区别你可以去网上查,但是通常你都不会用到它们。 Auto Layout 的原理在 WWDC 2015 的时候有几节视频专门讲了,楼主有兴趣可以去找找看一下。 我帮你找好了。https://developer.apple.com/videos/all-videos/?q=auto%20layout 如果你觉得 Auto Layout 实在是太麻烦了,你也可以用我刚才说的那个开源了 FlexLayout 的 layoutBox 的另一个叫 PinLayout 的库。它是一个用 Auto Layout 的语法去直接操作 frame 的库,没有任何约束,和直接操作 frame 没有区别。这些布局库都是可以混用的,你可以一个 View 用 Auto Layout,另一个 View 用 FlexLayout,再一个 View 用 PinLayout 。layoutBox 下的两个库我都是一直在用的,写了好几个十万行以上代码的商业 App,没有任何问题,非常的稳定。 |
22
Roccc 2021-01-16 10:04:36 +08:00
百分比+SnapKit
|
23
magic3584 2021-01-16 10:13:16 +08:00
1. 自适应可以
```` objective-c view1.snp_makeConstraints { make in make.height.equalTo(view2).dividedBy(2) } ```` 2. 获取 frame 之前先调用 superView.setNeedLayout() superView.layoutIfNeeded() |
24
magic3584 2021-01-16 10:15:57 +08:00
楼上 code block 标记 OC 但实际写的 swift...
|
25
expkzb 2021-01-16 10:52:49 +08:00
“我在网上搜了用 SnapKit 的方式可以不设置控件的高宽来使用,这个算是一种方式,但是用了这个方式之后,获取控件的高宽有时候为 0,好像是因为 snapKit 是异步的原因,太痛苦了,有时候就是需要高宽但是获取不到”
-- 如果确实需要获取宽高,执行一下 layoutIfNeeded,在后面应该就可以获取到宽高了。可能也有些细节我没提,好久没搞了。 "然后还有个问题就是控件的高宽根据内容自适应,我感觉这个是最头痛的,上面的 snapkit 是和父布局的高宽拉伸,但是有时候我想根据子控件内容自动适应高宽怎么弄呀" -- 你不指定父视图的宽高约束就行,自然会被子视图的约束撑起来。 自动布局很好用,一定要多练习,掌握它的思维方式。唯一值得诟病的是改起来比较头疼。 |
26
loarland 2021-01-16 18:30:19 +08:00
控件自身约束要完整,互相之间的优先级也要调整
|
27
365473321 2021-01-16 18:32:05 +08:00
其实 AutoLayout 的初衷就是要你忘掉 Frame 布局,设置好约束,剩下的工作就交给 AutoLayout Engine 就好啦
如果你想要立刻获取到 frame,你需要调用两个方法 setNeedsLayout() layoutIfNeeded() let subView = UIView(frame: .zero) view.addSubview(subView) subView.snp.makeConstraints { make in make.top.left.equalToSuperview() make.size.equalTo(300) } subView.setNeedsLayout() subView.layoutIfNeeded() print(subView.frame) |
28
Freeego 2021-01-16 19:10:59 +08:00
一般来说某个控件用了 AutoLayout 就不需要再获取 frame 了,这也是 AutoLayout 的目的,如果一定要获取的话就在约束之后调用父控件的 layoutIfNeeded()
父控件根据子控件自适应宽高,一句话就是通过子控件的约束计算出父控件的大小,父控件本身不设置宽高限制。多练习几次以后就会熟练了,只要你在写完子控件的约束以后,能够从中推算出父控件的 contentSize 就行,就像解方程一样。 |
29
Jackiehu 2021-01-16 19:42:50 +08:00 via iPhone
因为是异步绘制,需要在你获取最终 frame 前 layoutifneeded
|
30
Jackiehu 2021-01-16 19:54:42 +08:00 via iPhone
autolayout 就是等 layoutsubviews 后才有的 frame,layoutifneeded 会让 view 立即绘制,所以在之后可以拿到大小宽高
|
32
xhpan10 2021-01-16 21:57:34 +08:00
通过约束条件还有自定义 View 的 content size 来做适配啊
|
33
Xcution OP |
34
Freeego 2021-01-18 19:16:10 +08:00
@Xcution 你说的应该是 UICollectionView 的 contentSize 吧,frame 在初始化的时候就写死了,里面的内容多了少了影响的都是 contentSize 。而且 UICollectionView 的 contentSize 都是自动的,它就是个 UIScrollView 的子类,比如数据多了 contentSize 就会变大,如果范围超过 collectionView 的 frame.size 了就可以滑动,不需要自己去改 contentSize 。
如果又要网格布局 cell 高度又要动态变化,那就是瀑布流了,要重写一个 layout 才可以实现。 不知道你说的不设置 UICollectionView 的高度内容就不显示是什么意思,是不是 layout 的 itemSize 没有写对?不应该有"设置 UICollectionView 的高度"这种做法,frame 和内容无关,contentSize 是自动的。 |
35
kfchyc 2021-01-29 14:29:24 +08:00
在一个 controller 的不同生命周期函数中,view 的一些视觉属性可能错误或为 0,具体情况取决于你写在哪和你的需要如何
|
36
CodingIran 2021-02-01 13:09:19 +08:00
@vincentxue 害 何必折腾呢 frame 布局不香么 用上面某层的回复“手动精准控制每一个像素的位置”不香么
|
37
vincentxue 2021-02-02 02:44:25 +08:00
@CodingIran frame 布局香在哪里...
|
38
CodingIran 2021-02-02 08:55:09 +08:00
@vincentxue
1.性能好,iOS 12 之前的 AutoLayout 性能一言难尽,用 frame 尽可能的确保流畅性还是很重要的,当然一些简单的静态页面用 AutoLayout 也无妨 2.易于封装组件,道理同市面上的三方 UI 库,几乎清一色的 frame 布局,这对于自定义控件的复用和组件化有很大帮助 3.如你自己所说,“ iOS 的布局系统以及它的命令式 UI 开发体验跟 Android 比简直就是一坨屎”,所以 AutoLayout 也没有多好用,只是比以前的 frame 布局稍微“方便”一丢丢而已。等 SwiftUI 真正成熟了,最低支持版本追上来了,我立马把 frame 布局换掉,而如今我还是老老实实玩好 layoutSubviews 和 sizeThatFits: 吧 ┓( ´∀` )┏ |
39
iXInbo 2021-02-07 00:47:28 +08:00
snapKit 基于苹果的 AutoLayout,会根据屏幕自适应
使用 frame 就是先给定宽度和高度的。 如果你需要 frame 和 AutoLayout 混用,可以试试 layoutIfNeeded 先于 frame 调用。 |
40
jiahy 2021-03-25 11:14:07 +08:00
自适应布局的话可以试试 UIStackView 嵌套布局,Autolayout 自适应大小适用控件重写了 IntrinsicContentSize,自动布局的时候会根据这个来自动设置约束,本质上还是要自己计算。不过一些常用的系统控件都实现了自动计算内容大小,关键约束设置正确就不用管了,其实设置一个完美自适应的约束还是比较烦的
|