跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 最近刚刚开始 IOS 开发,使用的是 Swift (非 swiftUI)开发,发现了一个问题,困扰了我,希望有大佬可以解答
未分類
6 2 月 2021

最近刚刚开始 IOS 开发,使用的是 Swift (非 swiftUI)开发,发现了一个问题,困扰了我,希望有大佬可以解答

最近刚刚开始 IOS 开发,使用的是 Swift (非 swiftUI)开发,发现了一个问题,困扰了我,希望有大佬可以解答

資深大佬 : Xcution 10

我发现很多地方都要固定写死控件的高度,宽度?难道没有自适应的方式嘛?

我在网上搜了用 SnapKit 的方式可以不设置控件的高宽来使用,这个算是一种方式,但是用了这个方式之后,获取控件的高宽有时候为 0,好像是因为 snapKit 是异步的原因,太痛苦了,有时候就是需要高宽但是获取不到

然后还有个问题就是控件的高宽根据内容自适应,我感觉这个是最头痛的,上面的 snapkit 是和父布局的高宽拉伸,但是有时候我想根据子控件内容自动适应高宽怎么弄呀

这段时间一直在弄控件宽度高度的问题,太痛苦了,因为以前是安卓开发,安卓确实没这么麻烦,如果真的只能这样的话安卓其他不说至少在这方面还是要方便点的,我想我应该是哪里没弄对,是否有大佬解答一下,或者有相关的资料也行,我感觉我这样开发的,问题太多了

大佬有話說 (34)

  • 資深大佬 : gdtdpt

    不是专业 App 开发,只是搞过一阵子,我记得 iOS 的默认布局方式就是安卓里的约束布局,只要设置元素自身的约束、元素与元素之间的约束、元素与父元素的约束就能自适应了。

  • 資深大佬 : linKnowEasy

    搜一下 SnapKit 自适应 + 你要自适应的控件.

  • 資深大佬 : timelessg

    本质还是 autolayout 的问题,首先子 view 需要有 contentsize,也就是子 view 要先把自己撑起来,其次各个子 view 之间的约束要设对,这样才会撑起来父 view

  • 主 資深大佬 : Xcution

    @gdtdpt 但是我用的代码进行布局的,不知道怎么弄,网上搜了也没搜到相关的资料
    @linKnowEasy 我去搜搜看

  • 主 資深大佬 : Xcution

    @timelessg 有相关的资料可以看嘛

  • 資深大佬 : finab

    布局应该不需要确切的 高度,可以把你要的布局说一说

  • 資深大佬 : linKnowEasy

    搜下 SnapKit 教程 https://www.jianshu.com/p/332b816cd3e4

    这个概念其实就是 View 没有固定大小. 都是相对 superview 或者同级的 View

  • 資深大佬 : cincout

    给你打了一堆字,然后发现我并不擅长给别人讲解。。。还是给你个思路吧,其实很简单,想要自适应内容的高度,你得让内容的上下约束都固定在 contentView 上,且保证内容自身有高度,如果是多行 UIlabel,得保证 UIlabel 有固定宽度。

  • 資深大佬 : imkerberos

    FlexBox, 你值得拥有。

  • 資深大佬 : everhere

    snapkit 可以设置宽高,比如
    make.width.equalTo
    make.height.equalTo

  • 資深大佬 : Building

    你就没有想过 Android 虽然不用写高度,那高度怎么来的?肯定还是要算的啊,子视图没有高度,那么肯定有一个高度确定的父容器,然后通过约束计算得出子视图的高度。

  • 資深大佬 : ooops

    把个 AutoLayout 的教程系统的看一下吧,现在这么问没法回答。

  • 資深大佬 : yikuo

    这其实跟 snapkit 没关系,iOS 的 autolayout 布局方式就是这样的。有的地方可以使用 UIStackView 来简化约束。至于获取不到宽高,是因为你获取的时候 UI 还没计算出真正的大小,这里有两个选择:只用约束不要手动设置宽高,或者在 layoutsubview 之后再获取宽高。我个人觉得 Android 的布局比 iOS 简单很多,Android 有多种布局方式组合使用,可以专心布局,而 iOS 就只有 frame 和 autolayout 以及 UIStackView 了,需要耗费很多精力在调整位置和大小上面。

  • 資深大佬 : StyxS

    优先级和抗伸缩性

  • 資深大佬 : ydatong

    可以看看 uistackview,一般的布局能省不少事

  • 資深大佬 : Baymaxbowen

    equal to superview offset

  • 資深大佬 : coloz

    为什么不选择跨平台的开发方式呢,搞两套 app 太累了

  • 資深大佬 : vincentxue

    不是你没弄对,而是 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 我给你解答,移动端是我的老本行,搞了十来年了,大家互相学习。

  • 資深大佬 : oko

    自动布局老心酸了,早已放弃,改用手动布局了,虽然烦了一点,但是手动控制每一个像素的感觉还是很美妙的

  • 資深大佬 : Sixi

    主的意思我懂,以前也是从这些坑里慢慢爬出来的。
    假如使用 SnapKit 为一个 View 添加约束之后,想要获取这个 View 的 宽高(实际上也就是 frame 值),但总是是 0 。这是因为你获取宽高的代码在你的 SnapKit 代码前执行,此时 View 并没有布局,默认的 frame 值均是 0,所以获取不到的。

  • 資深大佬 : vincentxue

    我来补充一下上的回复。准确地说,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,没有任何问题,非常的稳定。

  • 資深大佬 : Roccc

    百分比+SnapKit

  • 資深大佬 : magic3584

    1. 自适应可以
    ““ objective-c
    view1.snp_makeConstraints { make in
    make.height.equalTo(view2).dividedBy(2)
    }
    ““

    2. 获取 frame 之前先调用
    superView.setNeedLayout()
    superView.layoutIfNeeded()

  • 資深大佬 : magic3584

    上 code block 标记 OC 但实际写的 swift…

  • 資深大佬 : expkzb

    “我在网上搜了用 SnapKit 的方式可以不设置控件的高宽来使用,这个算是一种方式,但是用了这个方式之后,获取控件的高宽有时候为 0,好像是因为 snapKit 是异步的原因,太痛苦了,有时候就是需要高宽但是获取不到”

    — 如果确实需要获取宽高,执行一下 layoutIfNeeded,在后面应该就可以获取到宽高了。可能也有些细节我没提,好久没搞了。

    “然后还有个问题就是控件的高宽根据内容自适应,我感觉这个是最头痛的,上面的 snapkit 是和父布局的高宽拉伸,但是有时候我想根据子控件内容自动适应高宽怎么弄呀”

    — 你不指定父视图的宽高约束就行,自然会被子视图的约束撑起来。

    自动布局很好用,一定要多练习,掌握它的思维方式。唯一值得诟病的是改起来比较头疼。

  • 資深大佬 : loarland

    控件自身约束要完整,互相之间的优先级也要调整

  • 資深大佬 : 365473321

    其实 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)

  • 資深大佬 : Freeego

    一般来说某个控件用了 AutoLayout 就不需要再获取 frame 了,这也是 AutoLayout 的目的,如果一定要获取的话就在约束之后调用父控件的 layoutIfNeeded()

    父控件根据子控件自适应宽高,一句话就是通过子控件的约束计算出父控件的大小,父控件本身不设置宽高限制。多练习几次以后就会熟练了,只要你在写完子控件的约束以后,能够从中推算出父控件的 contentSize 就行,就像解方程一样。

  • 資深大佬 : Jackiehu

    因为是异步绘制,需要在你获取最终 frame 前 layoutifneeded

  • 資深大佬 : Jackiehu

    autolayout 就是等 layoutsubviews 后才有的 frame,layoutifneeded 会让 view 立即绘制,所以在之后可以拿到大小宽高

  • 資深大佬 : 365473321

    @365473321 子视图调用这两个方法可以确定子视图的 size,父视图调用这两个方法可以确定子视图的 frame

  • 資深大佬 : xhpan10

    通过约束条件还有自定义 View 的 content size 来做适配啊

  • 主 資深大佬 : Xcution

    @Freeego @expkzb 我就是遇到这种问题,比如说我用 UICollectionView,显示的网格状的,有时候有 5 排数据,有时候有 6 排数据,如果我不设置 UICollectionView 的高度内容就显示不出来,但是设置我又不知道该设置多少,还有种就是知道每个 cell 的高度来算高度进行设置,这种也行,但是万一我 cell 的高度也是动态的啦,要计算 cell 的高度就要显示出来才能计算,不设置 UICollectionView 的高度有显示不出来,所以就必须要设置 UICollectionView 的高度,但是因为是动态的我又不知道该设置多少

  • 資深大佬 : Freeego

    @Xcution 你说的应该是 UICollectionView 的 contentSize 吧,frame 在初始化的时候就写死了,里面的内容多了少了影响的都是 contentSize 。而且 UICollectionView 的 contentSize 都是自动的,它就是个 UIScrollView 的子类,比如数据多了 contentSize 就会变大,如果范围超过 collectionView 的 frame.size 了就可以滑动,不需要自己去改 contentSize 。

    如果又要网格布局 cell 高度又要动态变化,那就是瀑布流了,要重写一个 layout 才可以实现。

    不知道你说的不设置 UICollectionView 的高度内容就不显示是什么意思,是不是 layout 的 itemSize 没有写对?不应该有”设置 UICollectionView 的高度”这种做法,frame 和内容无关,contentSize 是自动的。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具