我有大量的文本,希望在Text()
视图中显示。如果将视图包装在ScrollView
中,则可以向.horizontal
或.vertical
方向滚动。
但是,如果我想双向滚动,则布局是完全错误的。几乎好像有一个负偏移。
import SwiftUI
struct ContentView: View {
let text = """
<?xml version="1.0"?>
<PrettyXML>
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:dlna="urn:schemas-dlna-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<device>
<deviceType>urn:schemas-upnp-org:device:MediaRenderer:2</deviceType>
<friendlyName>Sample Renderer</friendlyName>
<manufacturer></manufacturer>
<manufacturerURL></manufacturerURL>
<modelDescription/>
<modelName>Test device</modelName>
<modelNumber/>
<modelURL></modelURL>
<serialNumber>12354-12312789-123987129873</serialNumber>
<UDN>uuid:12312311-1234-1234-1234-123456789011</UDN>
<iconList>
<icon>
<mimetype>image/png</mimetype>
<width>120</width>
<height>120</height>
<depth>24</depth>
<url>/image-120x120x24.png</url>
</icon>
<icon>
<mimetype>image/png</mimetype>
<width>48</width>
<height>48</height>
<depth>24</depth>
<url>/image-48x48x24.png</url>
</icon>
<icon>
<mimetype>image/jpeg</mimetype>
<width>120</width>
<height>120</height>
<depth>24</depth>
<url>/image-120x120x24.jpg</url>
</icon>
<icon>
<mimetype>image/jpeg</mimetype>
<width>48</width>
<height>48</height>
<depth>24</depth>
<url>/image-48x48x24.jpg</url>
</icon>
</iconList>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:ConnectionManager:2</serviceType>
<serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>
<SCPDURL>/xml/ConnectionManager.xml</SCPDURL>
<controlURL>/Control/ConnectionManager</controlURL>
<eventSubURL>/Event/ConnectionManager</eventSubURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:AVTransport:2</serviceType>
<serviceId>urn:upnp-org:serviceId:AVTransport</serviceId>
<SCPDURL>/xml/AVTransport2.xml</SCPDURL>
<controlURL>/Control/AVTransport</controlURL>
<eventSubURL>/Event/AVTransport</eventSubURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:RenderingControl:2</serviceType>
<serviceId>urn:upnp-org:serviceId:RenderingControl</serviceId>
<SCPDURL>/xml/RenderingControl2.xml</SCPDURL>
<controlURL>/Control/Renderer/RygelRenderingControl</controlURL>
<eventSubURL>/Event/Renderer/RygelRenderingControl</eventSubURL>
</service>
</serviceList>
<presentationURL>http://10.0.0.1:80/</presentationURL>
<dlna:X_DLNADOC>DMR-1.51</dlna:X_DLNADOC>
</device>
</root>
"""
var body: some View {
// ScrollView(.horizontal) {
// ScrollView(.vertical) {
ScrollView([.horizontal, .vertical]) {
Text(text)
}
}
}
是否有更好的方法来解决这个问题,还是仅仅是目前没有解决方法的bug?我唯一的其他想法是使用包装的UITextView
,该包装仅允许垂直滚动,但是如果有一种方法可以手动将帧宽度设置为必要的大小,则允许ScrollView
只能水平滚动。
解决这个问题的方法非常丑陋:
ScrollView(.horizontal, showsIndicators: false) {
ScrollView(.vertical, showsIndicators: false) {
Text(text)
}
}
但是,这只能允许一次感觉不自然的方向滚动。
似乎这种行为也与更新视图有关。考虑以下模拟重绘的示例:
struct ContentView: View {
@State var labelText = "Loading"
let text = """
<?xml version="1.0"?>
<PrettyXML>
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:dlna="urn:schemas-dlna-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<device>
<deviceType>urn:schemas-upnp-org:device:MediaRenderer:2</deviceType>
<friendlyName>Sample Renderer</friendlyName>
<manufacturer></manufacturer>
<manufacturerURL></manufacturerURL>
<modelDescription/>
<modelName>Test device</modelName>
<modelNumber/>
<modelURL></modelURL>
<serialNumber>12354-12312789-123987129873</serialNumber>
<UDN>uuid:12312311-1234-1234-1234-123456789011</UDN>
<iconList>
<icon>
<mimetype>image/png</mimetype>
<width>120</width>
<height>120</height>
<depth>24</depth>
<url>/image-120x120x24.png</url>
</icon>
<icon>
<mimetype>image/png</mimetype>
<width>48</width>
<height>48</height>
<depth>24</depth>
<url>/image-48x48x24.png</url>
</icon>
<icon>
<mimetype>image/jpeg</mimetype>
<width>120</width>
<height>120</height>
<depth>24</depth>
<url>/image-120x120x24.jpg</url>
</icon>
<icon>
<mimetype>image/jpeg</mimetype>
<width>48</width>
<height>48</height>
<depth>24</depth>
<url>/image-48x48x24.jpg</url>
</icon>
</iconList>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:ConnectionManager:2</serviceType>
<serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>
<SCPDURL>/xml/ConnectionManager.xml</SCPDURL>
<controlURL>/Control/ConnectionManager</controlURL>
<eventSubURL>/Event/ConnectionManager</eventSubURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:AVTransport:2</serviceType>
<serviceId>urn:upnp-org:serviceId:AVTransport</serviceId>
<SCPDURL>/xml/AVTransport2.xml</SCPDURL>
<controlURL>/Control/AVTransport</controlURL>
<eventSubURL>/Event/AVTransport</eventSubURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:RenderingControl:2</serviceType>
<serviceId>urn:upnp-org:serviceId:RenderingControl</serviceId>
<SCPDURL>/xml/RenderingControl2.xml</SCPDURL>
<controlURL>/Control/Renderer/RygelRenderingControl</controlURL>
<eventSubURL>/Event/Renderer/RygelRenderingControl</eventSubURL>
</service>
</serviceList>
<presentationURL>http://10.0.0.1:80/</presentationURL>
<dlna:X_DLNADOC>DMR-1.51</dlna:X_DLNADOC>
</device>
</root>
"""
var body: some View {
ScrollView([.horizontal, .vertical]) {
Text(self.labelText)
}
.onAppear() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
self.labelText = self.text
}
}
}
}
答案 0 :(得分:1)
如果您没有聪明的方法,这是一个愚蠢的方法。您可以添加条件以适应不同的尺寸等级。
struct ContentView: View {
let text = "" /// Your long multiline text
var body: some View {
GeometryReader { (geometry: GeometryProxy) in
ScrollView([.horizontal, .vertical]) {
VStack {
Spacer(minLength: geometry.size.height)
HStack {
Spacer(minLength: geometry.size.width)
Text(self.text)
}
}
}
}
}
}
一种更好的方法是添加一个viewModifier,它使事情自动进行。
struct ContentView: View {
let text = "" // Your multiline text
var body: some View {
GeometryReader { p in
ScrollView([.horizontal, .vertical]) {
Text(self.text)
.modifier(SimpleOffset(frameSize: p.size))
}
}
}
}
struct SimpleOffset: GeometryEffect {
var frameSize: CGSize
func effectValue(size: CGSize) -> ProjectionTransform {
ProjectionTransform(CGAffineTransform(translationX: (size.width - frameSize.width) / 2, y: (size.height - frameSize.height) / 2))
}
}
这里是纯对齐方式的解决方案。
var body: some View {
ScrollView([.horizontal, .vertical]) {
Text(self.text).alignmentGuide(HorizontalAlignment.center) { (v) -> CGFloat in
return (v[HorizontalAlignment.center] + v[.leading]) / 2
}.alignmentGuide(VerticalAlignment.center) { (v) -> CGFloat in
return (v[VerticalAlignment.center] + v[.top]) / 2
}.frame(alignment: .center )
}
}
align方法的完整代码如下:
struct ContentView: View {
let text = """
<?xml version="1.0"?>
<PrettyXML>
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:dlna="urn:schemas-dlna-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<device>
<deviceType>urn:schemas-upnp-org:device:MediaRenderer:2</deviceType>
<friendlyName>Sample Renderer</friendlyName>
<manufacturer></manufacturer>
<manufacturerURL></manufacturerURL>
<modelDescription/>
<modelName>Test device</modelName>
<modelNumber/>
<modelURL></modelURL>
<serialNumber>12354-12312789-123987129873</serialNumber>
<UDN>uuid:12312311-1234-1234-1234-123456789011</UDN>
<iconList>
<icon>
<mimetype>image/png</mimetype>
<width>120</width>
<height>120</height>
<depth>24</depth>
<url>/image-120x120x24.png</url>
</icon>
<icon>
<mimetype>image/png</mimetype>
<width>48</width>
<height>48</height>
<depth>24</depth>
<url>/image-48x48x24.png</url>
</icon>
<icon>
<mimetype>image/jpeg</mimetype>
<width>120</width>
<height>120</height>
<depth>24</depth>
<url>/image-120x120x24.jpg</url>
</icon>
<icon>
<mimetype>image/jpeg</mimetype>
<width>48</width>
<height>48</height>
<depth>24</depth>
<url>/image-48x48x24.jpg</url>
</icon>
</iconList>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:ConnectionManager:2</serviceType>
<serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>
<SCPDURL>/xml/ConnectionManager.xml</SCPDURL>
<controlURL>/Control/ConnectionManager</controlURL>
<eventSubURL>/Event/ConnectionManager</eventSubURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:AVTransport:2</serviceType>
<serviceId>urn:upnp-org:serviceId:AVTransport</serviceId>
<SCPDURL>/xml/AVTransport2.xml</SCPDURL>
<controlURL>/Control/AVTransport</controlURL>
<eventSubURL>/Event/AVTransport</eventSubURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:RenderingControl:2</serviceType>
<serviceId>urn:upnp-org:serviceId:RenderingControl</serviceId>
<SCPDURL>/xml/RenderingControl2.xml</SCPDURL>
<controlURL>/Control/Renderer/RygelRenderingControl</controlURL>
<eventSubURL>/Event/Renderer/RygelRenderingControl</eventSubURL>
</service>
</serviceList>
<presentationURL>http://10.0.0.1:80/</presentationURL>
<dlna:X_DLNADOC>DMR-1.51</dlna:X_DLNADOC>
</device>
</root>
"""
var body: some View {
ScrollView([.horizontal, .vertical]) {
Text(self.text).alignmentGuide(HorizontalAlignment.center) { (v) -> CGFloat in
return (v[HorizontalAlignment.center] + v[.leading]) / 2
}.alignmentGuide(VerticalAlignment.center) { (v) -> CGFloat in
return (v[VerticalAlignment.center] + v[.top]) / 2
}.frame(alignment: .center )
}
}
}