перерисовка пользовательского uiview при изменении ориентации устройства
- если я нарисую свою диаграмму внутри
- (void)drawRect:(CGRect)rect
достаточно просто установить [_chartView setContentMode:UIViewContentModeRedraw]
и этот метод будет вызван, когда устройство изменит ориентацию, и можно вычислить f.e. новая центральная точка для моей диаграммы. - если я создаю представление, подобное подвиду, используя
- (id)initWithFrame:(CGRect)frame
а затем добавьте его в контроллер вида, как[self.view addSubview:chartView];
. Как в этом случае я могу обрабатывать вращение, чтобы перерисовать мою диаграмму?
7 ответов
чтобы ваша диаграмма отображалась правильно при изменении ориентации устройства, вам необходимо обновить макет диаграммы, вот код, который вы должны добавить в контроллер вида:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_chartView.frame = self.view.bounds;
[_chartView strokeChart];
}
используя .Redraw
программный вызов myView.contentMode = .Redraw
при создании пользовательского представления должно хватить. Это один флаг в IB и, как таковой,0 строк кода предпочтительный способ. См. Раздел Переполнение Стека как вызвать drawRect в подклассе UIView.
используя setNeedsDisplay()
если вы должны вызвать перерисовку, делать так setNeedsDisplay
, который в свою очередь вызывает drawRect
.
Нет необходимости слушать уведомления или рефакторинг кода.
Свифт
override func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
}
С
- (void)layoutSubviews {
[super layoutSubviews];
[self setNeedsDisplay];
}
Примечание:layoutSubviews
это UIView
метод не a UIViewController
метод.
Go здесь чтобы узнать, как получать уведомления о том, когда меняется ориентация устройства. Когда ориентация изменится, просто вызовите [chartView setNeedsDisplay];
сделать drawRect:
получить вызов, чтобы вы могли обновить свой вид. Надеюсь, это поможет!
код, который вы добавите в контроллер вида:
- (void)updateViewConstraints
{
[super updateViewConstraints];
[_chartView setNeedsDisplay];
}
спасибо Keenle, за вышеуказанное решение ObjC. Я все утро возился с созданием запрограммированных ограничений, убивая свой мозг, не понимая, почему они не перекомпилируют/не перестроят вид. Я думаю, потому что я создал UIView программно, используя CGRect...это было важнее.
однако вот мое решение в swift:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
myUIView.center = CGPoint(x: (UIScreen.mainScreen().bounds.width / 2), y: (UIScreen.mainScreen().bounds.height / 2))
}
такое облегчение! :)
к сожалению, некоторые ответы предлагают переопределить методы контроллера, но у меня есть некоторые пользовательские UITableViewCells
с тенью вокруг и вращением устройства растягивает ячейки, но не перерисовывает тень. Поэтому я не хочу помещать свой код в контроллер для (re)рисования подвида.
Решение для меня-слушать a 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()
}
BTW:Logger
это typealias
to SwiftyBeaver
.
Благодаря @Aderis, указывающему мне в правильном направлении.
я попробовал "setNeedsDisplay" десятком способов, и это не сработало для настройки тени представления, которое я анимировал, на новую позицию.
Я решил свою проблему с этим, хотя. Если ваша тень, похоже, не хочет сотрудничать / обновлять, вы можете попробовать просто установить тень на ноль, а затем установить ее снова:
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
}