如何以编程方式使用自动布局在滚动视图中水平放置N个视图? [英] How to place N number of views Horizontally in scrollview using auto layout programmatically?

查看:186
本文介绍了如何以编程方式使用自动布局在滚动视图中水平放置N个视图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 scrollview 中水平创建N个视图。所以我创建了一个临时视图,并为此分配了当前视图。然后我根据它放置了约束。只有一个视图显示其他人没有显示。
我想要两个视图之间的水平空间。
我正在使用 VFL 来设置自动布局。
这是我的尝试代码。

  func ect(){
let scrollHeight = self.scrollObj。 frame.size.height - 40
let scrollHeightString = String(describe:scrollHeight)
print(scrollHeightString)
var firstTextView = UIView()//这是临时视图
var columnIndex :CGFloat = 0
for _ in 0 ..< 5 {
let textViewSample = UITextView()
textViewSample.translatesAutoresizingMaskIntoConstraints = false
//textViewSample.attributedText = self.htmlString.utf8Data?.attributedString
textViewSample.isScrollEnabled = false
textViewSample.tag = Int(columnIndex)
textViewSample.backgroundColor = UIColor.green
self.scrollObj.addSubview(textViewSample)

if columnIndex == 0 {
//这里我将第一个视图设置为左边距。
self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:H:| [textViewSample],options:NSLayoutFormatOptions(rawValue:0),metrics:nil,views:[textViewSample:textViewSample]))

// textview的高度
self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:V:[textViewSample(200)],options:NSLayoutFormatOptions(rawValue:0),metrics: nil,views:[textViewSample:textViewSample]))

// text to textview
self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:H:[textViewSample(200) ],选项:NSLayoutFormatOptions(rawValue:0),metrics:nil,views:[textViewSample:textViewSample]))

} else {

//水平设置临时视图和当前视图的空格
self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:H:| - [firstTextV] iew] - (10) - [textViewSample],选项:NSLayoutFormatOptions(rawValue:0),metrics:nil,views:[textViewSample:textViewSample,firstTextView:firstTextView]))
//设置相等第二个textview的宽度和相等高度基于第一个
self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:H:[firstTextView] [textViewSample(== firstTextView)],options:NSLayoutFormatOptions(rawValue:0) ,metrics:nil,views:[textViewSample:textViewSample,firstTextView:firstTextView]))

}

// y位置到textview
self .scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:V:| - (20) - [textViewSample],options:NSLayoutFormatOptions(rawValue:0),metrics:nil,views:[textViewSample:textViewSample]))

firstTextView = textViewSample //将当前视图分配给临时视图。
//增加当前偏移量
columnIndex = columnIndex + 1
}
self.scrollObj.contentSize = CGSize(width:columnIndex * 200,height:columnIndex * 200)
self.scrollObj .setNeedsLayout()
self.scrollObj.layoutIfNeeded()
}

这就是我的设计: -





解决方案

如果你想使用约束,你可以做类似这样的事情:

  var previousAnchor = scrollView.leadingAnchor 

for _ in 0 ..< 5 {
let textView = UITextView()
textView.translatesAutoresizingMaskIntoConstraints = false
textView.backgroundColor = .green
textView.isScrollEnabled = false
scrollView.addSubview(textView)

NSLayoutConstraint.activate([
textView.leadingAnchor.constraint(equalTo:previousAnchor,constant:10),
textView.heightAnchor.constraint(equalToConstant:200),
textView.widthAnchor.constraint(equalToConstant:200),
textView.topAnchor.constraint(equalTo:scrollView.topAnchor,constant:10),
textView.bottomAnchor.constraint(equalTo:scrollView.bottomAnchor,constant :-10)
])

previousAnchor = textView.trailingAnchor
}

previousAnchor.constraint(equalTo:scrollView.trailingAnchor,constant:-10 ).isActive = true

从概念上讲,它与你拥有的相似:因此,对于每个文本视图,设置宽度为200,高度到第一个视图,从滚动视图的前沿开始是10,对于最后一个视图,从滚动视图的后缘开始是10。



无需调整内容大小。没有布局相关的电话。只需添加约束即可。






在评论中,您说您希望文本视图的宽度为滚动视图边界的三分之一。由于滚动视图的约束的微妙性(请参阅


I want to create N number of views in horizontally in scrollview. so I have created One Temporary View and i assigned current view to that.Then i place constraints based on that.Only one view showing others not showing. I want Horizontal space between two views. I am using VFL to set a auto layout. Here is my trying code.

func ect() {
        let scrollHeight = self.scrollObj.frame.size.height - 40
        let scrollHeightString = String(describing: scrollHeight)
        print(scrollHeightString)
        var firstTextView = UIView() // this is temporary view
        var columnIndex: CGFloat = 0
        for  _ in 0 ..< 5 {
            let textViewSample = UITextView()
            textViewSample.translatesAutoresizingMaskIntoConstraints = false
            //textViewSample.attributedText = self.htmlString.utf8Data?.attributedString
            textViewSample.isScrollEnabled = false
            textViewSample.tag = Int(columnIndex)
            textViewSample.backgroundColor = UIColor.green
            self.scrollObj.addSubview(textViewSample)

            if columnIndex == 0{
//here i am setting first view to left margin.
            self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[textViewSample]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["textViewSample":textViewSample]))

                //height to textview
                self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[textViewSample(200)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["textViewSample":textViewSample]))

                //width to textview
                self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[textViewSample(200)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["textViewSample":textViewSample]))

            }else{

             //setting horizontal space to Temp view and current view   
            self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[firstTextView]-(10)-[textViewSample]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["textViewSample":textViewSample,"firstTextView":firstTextView]))
                //setting equal width and equal height to second textview based on first
                self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[firstTextView][textViewSample(==firstTextView)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["textViewSample":textViewSample,"firstTextView":firstTextView]))

            }

            //y position to textview
            self.scrollObj.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(20)-[textViewSample]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["textViewSample":textViewSample]))

            firstTextView = textViewSample//assigning current view to temp view.
            // Increase the current offset
            columnIndex = columnIndex + 1
            }
        self.scrollObj.contentSize = CGSize(width: columnIndex*200, height: columnIndex*200)
        self.scrollObj .setNeedsLayout()
        self.scrollObj.layoutIfNeeded()
    }

This is what my design:-

解决方案

If you want to use constraints, you could do something like this:

var previousAnchor = scrollView.leadingAnchor

for _ in 0 ..< 5 {
    let textView = UITextView()
    textView.translatesAutoresizingMaskIntoConstraints = false
    textView.backgroundColor = .green
    textView.isScrollEnabled = false
    scrollView.addSubview(textView)

    NSLayoutConstraint.activate([
        textView.leadingAnchor.constraint(equalTo: previousAnchor, constant: 10),
        textView.heightAnchor.constraint(equalToConstant: 200),
        textView.widthAnchor.constraint(equalToConstant: 200),
        textView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 10),
        textView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -10)
    ])

    previousAnchor = textView.trailingAnchor
}

previousAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true

Conceptually it's similar to what you have: So, for every text view, set the width to 200, height to 200, space to the prior view to 10. For the first view, it's 10 from the leading edge of the scroll view and for the last view, it's 10 from the trailing edge of the scroll view.

No content size adjustment is needed. No layout related calls. Just add the constraints and you're done.


In comments, you say you want the width of the text view to be one third of the scroll view's bounds. Because of the subtleties of constraints with scroll views (see TN2154, where constraints between a scroll view and its subviews are really between the contentSize of the scroll view and the subview, not the frame of the scroll view), you can't say ⅓ of the scroll view. But you can say ⅓ of the view the scroll view is in, e.g. replace the 200pt width constraint above with:

textView.widthAnchor.constraint(equalTo: scrollViewContainer.widthAnchor, multiplier: 1.0 / 3.0, constant: -13),

Likewise, you said you wanted it to be the height of the scroll view bounds less 10 (presumably on both sides). So you could do something like, again replacing the 200pt fixed height constraint with:

textView.heightAnchor.constraint(equalTo: scrollViewContainer.heightAnchor, constant: -20)

Now, because you cannot refer to the bounds of the scrollview, what I did was I put the scroll view inside a container view (scrollViewContainer), so the bounds of this parent view are the same as that of the scroll view. Now the constraints can refer to this parent view and you'll set these subviews relative to the bounds of the scroll view rather than the contentSize of the scroll view.

But when you do that, you see the first three views within the scroll view (and I can scroll to the right to see the rest):

这篇关于如何以编程方式使用自动布局在滚动视图中水平放置N个视图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆