#ios #swift #xcode #uiview #uikit
Вопрос:
Я реализую код для применения диагонального градиента к различным видам. он отлично работал для всех небольших видов и всех видов на небольших экранах, но на симуляторе iPhone 13 Pro Max он не применяется к полному виду и оставляет некоторую часть справа. Я только заметил, что даже в некоторых других видах, которые шире, этот градиент применяется только примерно на 80% по ширине. Вот скриншот, как он отображается в одном представлении:
Это не относится к правой части представления, и радиус правого угла невидим. Вот код для градиента:
func applyGradientDiagonal(isVertical: Bool, colorArray: [UIColor]) { layer.sublayers?.filter({ $0 is CAGradientLayer }).forEach({ $0.removeFromSuperlayer() }) let gradientLayer = CAGradientLayer() gradientLayer.colors = colorArray.map({ $0.cgColor }) if isVertical { //top to bottom gradientLayer.locations = [0.0, 1.0] } else { //left to right gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0) gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0) } backgroundColor = .clear gradientLayer.frame = bounds layer.insertSublayer(gradientLayer, at: 0) }
И я звоню по этому viewDidLoad()
поводу вот так:
self.viewTAGradient.applyGradientDiagonal(isVertical: false, colorArray: [UIColor.init(named: "gradient1")!, UIColor.init(named: "gradient2")!, UIColor.init(named: "gradient3")!])
Я искал некоторые решения и даже пытался назвать это так, но это тоже не сработало:
override func viewDidLayoutSubviews() { self.viewTAGradient.applyGradientDiagonal(isVertical: false, colorArray: [UIColor.init(named: "gradient1")!, UIColor.init(named: "gradient2")!, UIColor.init(named: "gradient3")!]) }
Изменить: Новое обновление: проблема заключается во всех градиентах на iPhone 13 pro max. Я скопировал некоторые коды из Интернета для градиентов и создал новый контроллер вида с одним видом фиксированной высоты, прикрепленным сверху, и все они сдвинуты влево на 13 pro max. однако отлично работает на других устройствах. вот скриншоты:
Кто-нибудь может мне помочь, почему на одном конкретном устройстве оно так себя ведет?
Комментарии:
1. Правильно ли вы установили ограничения
viewTAGradient
?2. Это должно работать, когда вы вызываете applyGradientDiagonal(isVertical:colorArray:) внутри viewDidLayoutSubviews(). Хотя это работает на моей машине. Не могли бы вы показать больше примеров кода, например, как настроить «viewTAGradient»?
3. @kyaw.monkey Я добавил более подробную информацию.
4. @Sweeper Я просто вызываю их внутри горизонтальной стопки фиксированной высоты = 180. При заполнении поровну на расстоянии 20 они должны создаваться автоматически. См. Выше после редактирования цвет BG применяется правильно, но градиент не будет
5. Проверьте свои ограничения компоновки…. предполагая , что вы
viewTAGradient
являетесь стандартомUIView
, правильно ли он имеет размер, если вы зададите ему цвет фона вместо вызоваapplyGradientDiagonal()
?
Ответ №1:
Нет причин, по которым градиент будет вести себя по-другому на iPhone 13 Pro Max, поэтому я предполагаю (не видя вашего полного макета), что это будет связано с ограничениями или когда вы на самом деле звоните applyGradientDiagonal()
.
Возможно, вам будет намного проще получить надежные результаты, создав подклассы UIView
и поместив код градиента внутрь layoutSubview()
.
Вот простой пример:
class MyGradientView: UIView { var colorArray: [UIColor] = [] { didSet { setNeedsLayout() } } var vertical: Bool = true { didSet { setNeedsLayout() } } static override var layerClass: AnyClass { return CAGradientLayer.self } override func layoutSubviews() { super.layoutSubviews() guard let layer = layer as? CAGradientLayer else { return } layer.colors = colorArray.map({ $0.cgColor }) if vertical { // top-down gradient layer.startPoint = CGPoint(x: 0.5, y: 0.0) layer.endPoint = CGPoint(x: 0.5, y: 1.0) } else { // diagonal gradient layer.startPoint = CGPoint(x: 0.0, y: 0.0) layer.endPoint = CGPoint(x: 1.0, y: 1.0) } } }
и пример контроллера представления для демонстрации:
class GradientTestViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let stack = UIStackView() stack.axis = .vertical stack.spacing = 8 stack.distribution = .fillEqually let colorPairs: [[UIColor]] = [ [.blue, .cyan], [.red, .yellow], [.blue, .yellow, .red], ] // 3 pairs of gradient views colorPairs.forEach { colors in let hstack = UIStackView() hstack.spacing = 8 hstack.distribution = .fillEqually var v = MyGradientView() v.colorArray = colors v.vertical = true hstack.addArrangedSubview(v) v = MyGradientView() v.colorArray = colors v.vertical = false hstack.addArrangedSubview(v) stack.addArrangedSubview(hstack) } // a pair of plain, solid color views for comparison let hstack = UIStackView() hstack.spacing = 8 hstack.distribution = .fillEqually var v = UIView() v.backgroundColor = .systemRed hstack.addArrangedSubview(v) v = UIView() v.backgroundColor = .systemBlue hstack.addArrangedSubview(v) stack.addArrangedSubview(hstack) stack.translatesAutoresizingMaskIntoConstraints = false view.addSubview(stack) let g = view.safeAreaLayoutGuide NSLayoutConstraint.activate([ stack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0), stack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0), stack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0), stack.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0), ]) // outline the stack view // so we can see its frame let outlineView = UIView() outlineView.backgroundColor = .clear outlineView.layer.borderColor = UIColor.black.cgColor outlineView.layer.borderWidth = 3 outlineView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(outlineView) NSLayoutConstraint.activate([ outlineView.topAnchor.constraint(equalTo: stack.topAnchor, constant: -2.0), outlineView.leadingAnchor.constraint(equalTo: stack.leadingAnchor, constant: -2.0), outlineView.trailingAnchor.constraint(equalTo: stack.trailingAnchor, constant: 2.0), outlineView.bottomAnchor.constraint(equalTo: stack.bottomAnchor, constant: 2.0), ]) } }
Результат выполнения этого кода: