gpt4 book ai didi

Push up view problem when focus textField in SwfitUI(在SwfitUI中聚焦文本字段时的上推查看问题)

转载 作者:bug小助手 更新时间:2023-10-24 19:27:25 31 4
gpt4 key购买 nike



struct TextFieldTest: View {

@State var textfieldText: String = ""
@FocusState var isTextFieldFocus: Bool

var body: some View {
ScrollViewReader { proxy in
ScrollView {
VStack {
ForEach(0 ..< 5) { num in
RoundedRectangle(cornerRadius: 25)
.frame(height: 100)
.frame(maxWidth: .infinity)
}
TextField("something here ...", text: $textfieldText, axis: .vertical)
.padding()
.frame(minHeight: 120, maxHeight: .infinity, alignment: .top)
.background(Color.gray.opacity(0.3).cornerRadius(10))
.padding(.bottom)
.focused($isTextFieldFocus)
.onTapGesture {
isTextFieldFocus = true
}
.id("textField")
}
.padding()
.onChange(of: textfieldText) { newValue in
proxy.scrollTo("textField", anchor: .bottom)
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidShowNotification)) { notification in
withAnimation() {
proxy.scrollTo("textField", anchor: .bottom)
}
}
}
}
}
}

When I touch the text field and the keyboard appears, it scrolls to the bottom anchor of the text field, but when the text changes and the frame of the text field goes below the keyboard, it does not scroll to the bottom anchor of the text field. However, if I do not specify a minimum height for the background of the text field, it scrolls to the bottom anchor of the text field whenever the content of the text field changes.

当我触摸文本字段时,键盘出现时,它会滚动到文本字段的底部锚点,但当文本更改并且文本字段的框架位于键盘下方时,它不会滚动到文本字段的底部锚点。但是,如果我没有为文本字段的背景指定最小高度,则每当文本字段的内容发生更改时,它都会滚动到文本字段的底部锚点。


Also, if you specify a minimum height and it automatically scrolls to the bottom of the TextField when the keyboard is raised, and then the text in the TextField gets longer and goes over the minimum height, it should scroll to the bottom because of the .onChange, but it doesn't work. However, if you scroll to the bottom by hand after it goes over the frame, you can see that it moves to the bottom whenever the text changes.

此外,如果您指定了最小高度,当键盘升起时,它会自动滚动到Textfield的底部,然后Textfield中的文本变长并超过最小高度,则由于.onChange,它应该会滚动到底部,但它不起作用。但是,如果在它经过框架后手动滚动到底部,您可以看到每当文本更改时,它都会移动到底部。


Do you know why this is happening and how to specify a minimum height and have the TextField automatically scroll when the frame goes over the keyboard?

您知道为什么会发生这种情况吗?知道如何指定最小高度并在框架经过键盘时让Textfield自动滚动吗?


I wanted the textField to continue scrolling to the bottom as the keyboard rises and the textField adds text, but no.

我希望随着键盘的上升和文本字段的添加,文本字段继续滚动到底部,但没有。


更多回答
优秀答案推荐

From trial and error, I found that scrolling the scroll view for a little bit before inserting a new line produces the correct behaviour.

通过反复试验,我发现在插入新行之前稍微滚动一下滚动视图会产生正确的行为。


So I tried doing that programmatically, and it does work.

所以我试着通过编程来实现这一点,它确实奏效了。


First, make a view for the scroll view to temporarily scroll to. You can do this by simply surrounding the TextField with a VStack or similar.

首先,为滚动视图创建一个临时滚动到的视图。只需用VStack或类似的方法将Textfield括起来,就可以做到这一点。


VStack {
TextField("something here ...", text: $textfieldText, axis: .vertical)
.padding()
.frame(minHeight: 120, maxHeight: .infinity, alignment: .top)
.background(Color.gray.opacity(0.3).cornerRadius(10))
.padding(.bottom)
.focused($isTextFieldFocus)
.onTapGesture {
isTextFieldFocus = true
}
.id("textField")
}.id("placeholder")

In onChange, scroll to placeholder first, then to textField. You need to put either or both of these scrollTos in a DispatchQueue.main.async block (found by trial and error) for this to work. I assume this is to allow the text field to re-layout, and only start scrolling after that is done.

在onChange中,首先滚动到占位符,然后滚动到文本字段。您需要将这两个scroll Tos中的一个或两个放入DispatchQueue.main.async块中(通过反复试验找到),这样才能正常工作。我假设这是为了允许文本字段重新布局,并仅在完成后才开始滚动。


.onChange(of: textfieldText) { _ in
DispatchQueue.main.async {
proxy.scrollTo("placeholder", anchor: .bottom)
proxy.scrollTo("textField", anchor: .bottom)
}
}

I doubt this is the best solution for this though, unless the weird scrolling behaviour is a bug.

不过,我怀疑这是解决这一问题的最佳解决方案,除非这种奇怪的滚动行为是一个错误。



You can have another element at the bottom of the page which you use as the target for scrolling. The id of this element needs to change for scrolling to work, so this can be done in your .onChange callback. The element itself can be in the background and have such low opacity that it is effectively invisible - a Divider works nicely. In fact, applying .hidden() also worked sometimes, but I think it works more reliably using low opacity. See also the note about reliability that follows the code.

您可以在页面底部使用另一个元素作为滚动目标。需要更改此元素的id才能使滚动生效,因此这可以在.onChange回调中完成。元素本身可以在背景中,并且具有如此低的不透明度,以至于它实际上是不可见的--Divider工作得很好。事实上,应用.den()有时也会起作用,但我认为使用低不透明度会更可靠。另请参阅代码后面有关可靠性的说明。


struct TextFieldTest: View {

@State var textfieldText: String = ""
@FocusState var isTextFieldFocus: Bool
@State private var dividerId = UUID()

var body: some View {
ScrollViewReader { proxy in
ScrollView {
VStack {
// contents as before
}
.background(alignment: .bottom) {
Divider()
.opacity(0.001)
.id(dividerId)
}
.padding()
.onChange(of: textfieldText) { newValue in
dividerId = UUID()
proxy.scrollTo(dividerId, anchor: .bottom)
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidShowNotification)) { notification in
withAnimation() {
proxy.scrollTo(dividerId, anchor: .bottom)
}
}
}
}
}
}

In my tests on a real iPhone 8 running iOS 16.6, this worked sometimes, but not always. I tried a few different ideas (such as, scrolling asynchronously), but wasn't able to find a way to get it working reliably every time. I don't know if the issue is related to spelling suggestions - I was just entering junk into the text field for the purpose of a quick test.

在我对一部运行iOS 16.6的真正的iPhone 8进行的测试中,这有时会奏效,但并不总是有效。我尝试了几种不同的想法(例如,异步滚动),但无法找到一种方法让它每次都可靠地工作。我不知道这个问题是否与拼写建议有关-我只是在文本栏中输入垃圾信息,以便快速测试。


更多回答

Thanks! it's working the way I want it to.

谢谢!它正在按照我想要的方式工作。

@hentick If you think an answer answers your question, please consider accepting it by clicking on that checkmark!

@Hentik如果您认为答案回答了您的问题,请考虑通过单击该复选标记来接受!

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com