首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SwuiftUI折叠多行文字

SwuiftUI折叠多行文字
EN

Stack Overflow用户
提问于 2021-09-27 16:47:46
回答 1查看 74关注 0票数 5

我试图在一个有多行的Text上添加一个扩展/收缩动画,但是我有一个奇怪的行为。

下面是这个问题的gif。我已经设置了缓慢的动画,以使其清晰。

https://www.dropbox.com/s/sx41g9tfx4hd378/expand-collapse-stack_overflow.gif

我正在对视图的height属性进行动画处理,似乎无论动画周期如何,Text都会立即转换为一行。下面是一些代码:

代码语言:javascript
运行
复制
struct ContentView: View {

    @State var expanded = false

    var body: some View {
        VStack(spacing: 20) {
            HStack {
                Button(expanded ? "Colapse" : "Expand") {
                    withAnimation {
                        self.expanded.toggle()
                    }
                }
            }
            VStack(spacing: 10) {
                Text(bigText)
                Text(bigText)
            }
            .frame(height: expanded ? .none : 0)
            .clipped()
            .background(Color.red)
            Text("Thist is another text underneath the huge one. ")
                .font(.system(.headline))
                .foregroundColor(.red)
            Spacer()
        }
    }
}

我已经尝试了很多其他方法,这是目前最接近所需输出的方法,这与在UIKit中为UIStackView中的标签设置动画效果相同。

有没有办法正确地做到这一点呢?这是一个bug吗?通常情况下,问题来自开发人员,但我注意到,如果我使用DisclosureGroup,当它展开时,动画可以工作,但当它折叠时,它根本没有动画。所以这实际上可能是多行Text的一个限制

非常感谢。

EN

回答 1

Stack Overflow用户

发布于 2021-09-27 18:16:33

嗯,问题是我们在nil0之间设置了帧动画,但对于内部文本项,只有边缘值被传输。

要解决这个问题,需要完成两个步骤:

  1. 使高度成为可动画的数据,因此每次对高度值的更改都会传递给content
  2. calculate文本内容的实际最大高度,因为我们需要可动画范围的具体值。

所以这里是一个方法的演示。用Xcode13/ iOS 15编写

注意:在模拟器中激活慢速动画,以获得更好的可见性

代码语言:javascript
运行
复制
let bigText = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
"""

struct ContentView: View {

    // we need `true` on construction (not visible) to calculate
    // max content height
    @State var expanded = true    // << required initial true !!

    @State private var maxHeight: CGFloat?

    var body: some View {
        VStack(spacing: 20) {
            HStack {
                Button(expanded ? "Colapse" : "Expand") {
                    withAnimation {
                        self.expanded.toggle()
                    }
                }
            }
            VStack(spacing: 10) {
                Text(bigText)
                Text(bigText)
            }
            .background(GeometryReader { // read content height
                Color.clear.preference(key: ViewHeightKey.self,
                                              value: $0.frame(in: .local).size.height)
            })
            .onPreferenceChange(ViewHeightKey.self) {
                if nil == self.maxHeight {
                    self.maxHeight = $0     // << needed once !!
                }
            }
            .modifier(AnimatingFrameHeight(height: expanded ? maxHeight ?? .infinity : 0))
            .clipped()
            .background(Color.red)
            Text("Thist is another text underneath the huge one. ")
                .font(.system(.headline))
                .foregroundColor(.red)
            Spacer()
        }
        .onAppear {
            // this cases instance redraw on first render
            // so initial state will be invisible for user
            expanded = false    // << set if needed here !!
        }
    }
}

struct AnimatingFrameHeight: AnimatableModifier {
    var height: CGFloat = 0

    var animatableData: CGFloat {
        get { height }
        set { height = newValue }
    }

    func body(content: Content) -> some View {
        content.frame(height: height)
    }
}

struct ViewHeightKey: PreferenceKey {
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value = value + nextValue()
    }
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69350410

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档