【问题标题】:Swift - self.bounds.size.width doesn't return the correct widthSwift - self.bounds.size.width 不返回正确的宽度
【发布时间】:2018-03-15 14:03:38
【问题描述】:

在另一个thread 中,我找到了分段控件 的下划线解决方案。

我的问题的重要行似乎是这一行:

let underlineWidth: CGFloat = self.bounds.size.width / CGFloat(self.numberOfSegments)

事实证明,宽度的计算并不完全正确。因为我总是有 3 个段,所以我希望这个值是屏幕宽度的三分之一(无论设备如何)。

在此屏幕截图中,您可以看到该应用程序在两个不同的设备上运行:

Screenshot

如您所见,在 iPhone 6S 上,下划线的宽度稍大,而在 iPhone 8Plus 上则太小了。

这只能意味着 self.bounds.size.width 没有返回正确的宽度。


分段控件的整个类:

import UIKit
import Foundation

extension UISegmentedControl{
    func removeBorder(){
        let backgroundImage = UIImage.getColoredRectImageWith(color: UIColor.clear.cgColor, andSize: self.bounds.size)
        let backgroundImageTest = UIImage.getColoredRectImageWith(color: UIColor.red.cgColor, andSize: self.bounds.size)

        self.setBackgroundImage(backgroundImage, for: .normal, barMetrics: .default)
        self.setBackgroundImage(backgroundImageTest, for: .selected, barMetrics: .default)
        self.setBackgroundImage(backgroundImage, for: .highlighted, barMetrics: .default)

        let deviderImage = UIImage.getColoredRectImageWith(color: UIColor.clear.cgColor, andSize: CGSize(width: 1.0, height: self.bounds.size.height))
        self.setDividerImage(deviderImage, forLeftSegmentState: .selected, rightSegmentState: .normal, barMetrics: .default)
        self.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.gray], for: .normal)
        self.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor(red: 67/255, green: 129/255, blue: 244/255, alpha: 1.0)], for: .selected)
    }

    func addUnderlineForSelectedSegment(){
        removeBorder()
        let underlineWidth: CGFloat = self.bounds.size.width / CGFloat(self.numberOfSegments)
        let underlineHeight: CGFloat = 2.0
        let underlineXPosition = CGFloat(selectedSegmentIndex * Int(underlineWidth))
        let underLineYPosition = self.bounds.size.height - 1.0
        let underlineFrame = CGRect(x: underlineXPosition, y: underLineYPosition, width: underlineWidth, height: underlineHeight)
        let underline = UIView(frame: underlineFrame)
        underline.backgroundColor = UIColor(red: 67/255, green: 129/255, blue: 244/255, alpha: 1.0)
        underline.tag = 1
        self.addSubview(underline)
    }

    func changeUnderlinePosition(){
        guard let underline = self.viewWithTag(1) else {return}
        let underlineFinalXPosition = (self.bounds.width / CGFloat(self.numberOfSegments)) * CGFloat(selectedSegmentIndex)
        UIView.animate(withDuration: 0.1, animations: {
            underline.frame.origin.x = underlineFinalXPosition
        })
    }
}

extension UIImage{

    class func getColoredRectImageWith(color: CGColor, andSize size: CGSize) -> UIImage{
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        let graphicsContext = UIGraphicsGetCurrentContext()
        graphicsContext?.setFillColor(color)
        let rectangle = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)
        graphicsContext?.fill(rectangle)
        let rectangleImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return rectangleImage!
    }
}

【问题讨论】:

  • 你必须做更多的计算。段之间的段垂直分隔线具有宽度 - 因此必须考虑到这一点。此外,线段宽度设置为整数磅值,因此它们可能不完全相等。例如,如果控件宽度为333,则段宽度最终为110, 110, 111(即331 加上两个分隔符)。而且....如果段控制宽度发生变化,您需要处理宽度的变化 - 例如设备旋转。
  • 您也应该从layoutSubviews 更新边界。实际上最好的解决方案是从UIControl 创建您自己的控件。

标签: ios swift


【解决方案1】:

您可能正试图在方法func viewDidLoad() 中获取尺寸。 尝试在方法func viewDidLayoutSubviews() 中获取确切的尺寸。

See also this answer

【讨论】:

  • 是的,我实际上是在func viewDidLoad() 中调用segmentedControl.addUnderlineForSelectedSegment(),我现在将此行放入func viewDidLayoutSubviews(),这会导致白屏。我将尝试找出导致此问题的原因,然后查看是否解决了问题。谢谢
【解决方案2】:

视图的确切大小只有在视图渲染后才是正确的。在此之前,视图具有默认大小(例如,在 xib 或情节提要中)。 在viewDidLayoutSubviews()viewDidAppear()/viewWillAppear() 中,大小肯定会计算正确。

【讨论】:

  • 这不是控制器。
  • 然后在方法draw(inRect:)中试试
  • 如果你不做任何自定义绘图,绝对不要覆盖draw(inRect:)
猜你喜欢
  • 2015-04-24
  • 1970-01-01
  • 2016-05-31
  • 1970-01-01
  • 2012-08-18
  • 2015-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多