UIScrollView 子视图在按比例缩小时错位,而子视图在四舍五入时不显示

Posted

技术标签:

【中文标题】UIScrollView 子视图在按比例缩小时错位,而子视图在四舍五入时不显示【英文标题】:UIScrollView Subviews being misplaced when scaled down and Subviews not showing up when rounded 【发布时间】:2020-04-01 04:50:06 【问题描述】:

所以我正在制作我的第一个 Swift ios 应用程序。我有两个问题需要帮助。

第一个问题:我遇到了一些问题,我以编程方式创建的子视图在小屏幕上显示时没有正确对齐。

第一张图片显示了我希望滚动视图的外观。 (iPhone 11 Pro Max)

但是,这就是它在较小屏幕上时的样子。 (iPhone 8)

我认为问题在于我以编程方式创建子视图,因为滚动视图的大小是我想要的。

这是我在 viewDidLoad() 中使用的 swift 代码:

var districtNewsSize = 10;
var districtNewsFrame = CGRect(x:0,y:0,width:0,height:0);
// District News -----
        districtNewsPageControl.numberOfPages = districtNewsSize;
        for aIndex in 0..<districtNewsSize
            districtNewsFrame.origin.x = districtNewsScrollView.frame.size.width * CGFloat(aIndex);
            districtNewsFrame.size = districtNewsScrollView.frame.size;


            // create content in scrollview
            let contentView = UIButton(frame: districtNewsFrame);
            contentView.backgroundColor = makeColor(r: 147, g: 66, b: 78);
            contentView.setTitle("titletext", for: .normal);
            contentView.layer.cornerRadius = 20; // just to show how displaced the views are


            // add contentview to scrollview
            self.districtNewsScrollView.addSubview(contentView);
        
        // change horizontal size of scrollview
        districtNewsScrollView.contentSize = CGSize(width: districtNewsScrollView.frame.size.width * CGFloat(districtNewsSize), height: districtNewsScrollView.frame.size.height);
        districtNewsScrollView.delegate = self;

第二个问题:当尝试将滚动视图的顶部两个角转圆时,滚动视图内的内容似乎消失了。

这是第一个子视图的图片。

这是第二个子视图的图片。

我也怀疑这是由我用来圆顶边缘的函数引起的。

这是我为 UIScrollView 做的扩展函数:

extension UIScrollView
    func setRoundedEdge(corners:UIRectCorner, radius: CGFloat) // label.setRoundedEdge([.TopLeft, . TopRight], radius: 10)
        let maskPath1 = UIBezierPath(roundedRect: bounds,
            byRoundingCorners: corners,
            cornerRadii: CGSize(width: radius, height: radius))
        let maskLayer1 = CAShapeLayer()
        maskLayer1.frame = bounds
        maskLayer1.path = maskPath1.cgPath
        layer.mask = maskLayer1
    

这就是我在viewDidLoad() 中调用函数的方式:

districtNewsScrollView.setRoundedEdge(corners: [.topRight,.topLeft], radius: 30);

我们将不胜感激。我一直被这两个问题困住,在网上找不到任何东西(可能是因为我的措辞不对,但我不知道如何描述这些问题)。谢谢!

【问题讨论】:

【参考方案1】:

我假设您正在使用故事板进行滚动视图并以编程方式在 viewDidLoad 中添加子视图,

districtNewsFrame.origin.x = districtNewsScrollView.frame.size.width * CGFloat(aIndex);
districtNewsFrame.size = districtNewsScrollView.frame.size;

应该改为

districtNewsFrame.origin.x = UIScreen.main.bounds.size.width * CGFloat(aIndex);
districtNewsFrame.size = UIScreen.main.bounds.frame.size;

在 viewDidLoad 上使用屏幕大小,因为情节提要中的视图已加载,但尚未应用自动布局中的约束。

第二个问题,

将扩展名改为

extension UIScrollView
    func setRoundedEdge(corners:UIRectCorner, radius: CGFloat) // label.setRoundedEdge([.TopLeft, . TopRight], radius: 10)
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        layer.mask = mask
    

和视图控制器

override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews();
    districtNewsScrollView.setRoundedEdge(corners: [.topRight,.topLeft], radius: 30);

【讨论】:

这两件事都没用。 第一个问题:您的代码:districtNewsFrame.size = UIScreen.main.bounds.frame.size;,但 bounds.frame 不存在。我试过districtNewsFrame.origin.x = (UIScreen.main.bounds.size.width) * CGFloat(aIndex); districtNewsFrame.size = UIScreen.main.bounds.size;,但也没有用。 第二个问题:即使在使用您的代码后,同样的问题仍然存在。谢谢【参考方案2】:

这是我解决这两个问题的方法:

// District News -----
        districtNewsFrame.size = districtNewsScrollView.frame.size;
        districtNewsFrame.size.width = UIScreen.main.bounds.size.width - 34;
        for aIndex in 0..<districtNewsSize
            //districtNewsFrame.origin.x = (UIScreen.main.bounds.size.width-52) * CGFloat(aIndex);
            //districtNewsFrame.size = UIScreen.main.bounds.size;
            districtNewsFrame.origin.x = (districtNewsFrame.size.width * CGFloat(aIndex));

            // create content in scrollview
            let contentView = UIButton(frame: districtNewsFrame); // wrapper for article
            //testButton.setImage(UIImage(named: "ahsldpi.png"), for: .normal);
            contentView.backgroundColor = makeColor(r: 147, g: 66, b: 78);

            // content inside contentView -------
            let articleContentFrame = CGRect(x:0,y:0,width:districtNewsFrame.width,height:districtNewsFrame.height-60);
            let articleContent = UIView(frame: articleContentFrame); // may be image?
            articleContent.backgroundColor = makeColor(r: 138, g: 138, b: 138);

            let articleLabelFrame = CGRect(x:0,y:districtNewsFrame.height-60,width:districtNewsFrame.width,height:60);
            let articleLabel = UILabel(frame: articleLabelFrame);
            articleLabel.text = "    " + "Title";
            articleLabel.backgroundColor = UIColor.white;
            articleLabel.font = UIFont(name: "DINCondensed-Bold", size: 30);



            // add content inside contentView to contentview
            contentView.addSubview(articleContent);
            contentView.addSubview(articleLabel);
            // add contentview to scrollview
            contentView.setRoundedEdge(corners: [.topRight,.topLeft,.bottomLeft,.bottomRight], radius: 30);
            self.districtNewsScrollView.addSubview(contentView);
        
        // change horizontal size of scrollview
        districtNewsScrollView.contentSize = CGSize(width: (districtNewsFrame.size.width * CGFloat(districtNewsSize)), height: districtNewsScrollView.frame.size.height);
        districtNewsScrollView.delegate = self;
    ```

【讨论】:

以上是关于UIScrollView 子视图在按比例缩小时错位,而子视图在四舍五入时不显示的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 最小比例问题

UIScrollview,当完全缩小时是不是可以在屏幕上移动视图?

如果涉及superview,则不会排除子视图点击的UIScrollView

如何处理 Xcode 故事板中的错位视图警告?

如何使用 UIScrollView 捕捉缩放?

UIScrollView 不缩放