- Если я нарисую свою диаграмму внутри
- (void)drawRect:(CGRect)rect
, достаточно установить [_chartView setContentMode:UIViewContentModeRedraw]
, и этот метод будет вызываться, когда устройство изменит свою ориентацию, и можно будет вычислить, например. новая центральная точка моей карты. - Если я создам представление, подобное подпредставлению, с помощью
- (id)initWithFrame:(CGRect)frame
, а затем добавлю его в контроллер представления, например[self.view addSubview:chartView];
. Как в этом случае я могу обработать вращение, чтобы перерисовать мою диаграмму?
перерисовывать пользовательский интерфейс при изменении ориентации устройства
Ответы (8)
Чтобы ваша диаграмма отображалась правильно при изменении ориентации устройства, вам необходимо обновить макет диаграммы, вот код, который вы должны добавить в свой контроллер представления:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_chartView.frame = self.view.bounds;
[_chartView strokeChart];
}
Хотя для предпочтительного решения требуется ноль строк кода, если вы должны запустить перерисовку, сделайте это. в setNeedsDisplay
, который, в свою очередь, вызывает drawRect
.
Нет необходимости слушать уведомления или реорганизовывать код.
Swift
override func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
}
Цель-C
- (void)layoutSubviews {
[super layoutSubviews];
[self setNeedsDisplay];
}
Примечание. layoutSubviews
- это метод UIView
, не метод UIViewController
.
layoutSubviews
- это UIView
метод, а не UIViewController
метод. Вам необходимо создать подкласс UITableView
, а не UITableViewController
, что можно сделать в IB. Вы можете узнать больше о layoutSubviews на stackoverflow.com/a/5330162/218152.
- person SwiftArchitect; 30.12.2015
Ноль строк кода
Используйте .redraw
Программного вызова myView.contentMode = .redraw
при создании настраиваемого представления должно быть достаточно. Это единственный флаг в IB, поэтому предпочтительнее использовать 0 строк кода. См. Раздел «Переполнение стека» Как запустить drawRect в подклассе UIView.
Перейдите сюда, чтобы узнать, как получать уведомления. когда меняется ориентация устройства. Когда ориентация действительно изменится, просто вызовите [chartView setNeedsDisplay];
, чтобы вызвать drawRect:
, чтобы вы могли обновить свое представление. Надеюсь это поможет!
Код, который вы добавите в контроллер представления:
- (void)updateViewConstraints
{
[super updateViewConstraints];
[_chartView setNeedsDisplay];
}
К сожалению, в некоторых ответах предлагается переопределить методы контроллера, но у меня есть несколько пользовательских UITableViewCells
с тенью вокруг, и вращение устройства растягивает ячейки, но не перерисовывает тень. Поэтому я не хочу помещать свой код в контроллер, чтобы (пере) рисовать подпредставление. Решение для меня - прослушать UIDeviceOrientationDidChange
уведомление в моем пользовательском UITableViewCell
, а затем вызвать setNeedsDisplay()
, как было предложено.
Пример кода Swift 4.0 в одном из моих пользовательских UITableViewCells
override func awakeFromNib() {
super.awakeFromNib()
NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChangeNotification), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
@objc func deviceOrientationDidChangeNotification(_ notification: Any) {
Logger.info("Orientation changed: \(notification)")
setNeedsLayout()
}
Кстати: Logger
- это от typealias
до SwiftyBeaver
. Спасибо @Aderis, указывающему мне правильное направление.
Спасибо Кинл за вышеупомянутое решение ObjC. Я все утро возился с созданием запрограммированных ограничений, убивая свой мозг, не понимая, почему они не перекомпилировали / перестроили представление. Я думаю, потому что я создал UIView программно с помощью CGRect ... это имело приоритет.
Однако вот мое быстрое решение:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
myUIView.center = CGPoint(x: (UIScreen.mainScreen().bounds.width / 2), y: (UIScreen.mainScreen().bounds.height / 2))
}
Так приятно! :)
Я пробовал "setNeedsDisplay" дюжиной способов, и это не помогло настроить тень вида, который я анимирую, в новое положение.
Однако я решил свою проблему с этим. Если ваша тень не хочет сотрудничать / обновляться, вы можете попробовать просто установить для тени значение nil, а затем установить ее снова:
UIView.animateKeyframes(withDuration: 0.2 /*Total*/, delay: 0.0, options: UIViewKeyframeAnimationOptions(), animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 10/10, animations:{
// Other things to animate
//Set shadow to nil
self.viewWithShadow.layer.shadowPath = nil
})
}, completion: { finished in
if (!finished) { return }
// When the view is moved, set the shadow again
self.viewWithShadow.layer.shadowPath = UIBezierPath(rect: self.descTextView.bounds).cgPath
})
Если у вас еще нет тени и вам нужен этот код, вот что:
func addShadowTo (view: UIView) {
view.layer.masksToBounds = false
view.layer.shadowColor = UIColor.gray.cgColor
view.layer.shadowOffset = CGSize( width: 1.0, height: 1.0)
view.layer.shadowOpacity = 0.5
view.layer.shadowRadius = 6.0
view.layer.shadowPath = UIBezierPath(rect: view.bounds).cgPath
view.layer.shouldRasterize = true
}