UIScrollView масштабирование с автоматической компоновкой
Я пытаюсь реализовать UIScrollView
Новый способ с помощью автоматической компоновки. Я установил ограничения из внутреннего представления в представление прокрутки, чтобы он мог автоматически вычислить свой собственный contentSize
, и это работает как шарм, за исключением того, что весь ад разрывается, когда я пытаюсь увеличить или уменьшить масштаб. Я не могу даже правильно описать, что происходит, кроме того, что внутреннее представление "перепуталось".
Здесь вы можете увидеть пример этого (а не мой проект, вам нужно установить прокрутку maximumZoomScale
и реализовать -viewForZoomingInScrollView:
до того, как масштабирование будет работать).
Кто-нибудь еще сталкивается с этим поведением? Есть ли какой-либо способ получить масштабирование в UIScrollView
для работы с автоматической компоновкой без существенного повторного выполнения поведения масштабирования?
Ответы
Ответ 1
Лучший ответ, который я видел, - Mark (https://stackoverflow.com/users/1051919/mark-kryzhanouski), размещенный здесь: UIScrollView Zoom не работает С автоопределением.
Суть его в том, что вы должны привязать вид изображения, который вложен в представление прокрутки, родительскому представлению прокрутки. Несмотря на руководство в примечаниях к выпуску iOS 6, мне неинтересно, какая точка зрения "плавает" над чем. В этом случае просмотр прокрутки представляет собой только один вид изображения.
Я очень много экспериментировал с этим, надеясь найти подход, основанный на IB, и не нашел его. Вы все равно можете генерировать иерархию представлений в IB, но вам все равно придется программно добавлять ограничения. Вы можете удалить некоторые или все ограничения по умолчанию (в основном, чтобы успокоить предупреждения ограничения конфликтов), но вам всегда нужен код Mark, чтобы привязать изображение к родительскому элементу прокрутки, родоначальнику изображения.
Кажется, что это должно быть проще, чем это - он должен "просто работать", но:
NSDictionary *viewsDictionary = @{ @"scrollView": self.scrollView, @"imageView": self.imageView };
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|[imageView(width)]"
options:0
metrics:@{@"width": @(self.imageView.image.size.width)}
views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|[imageView(height)]"
options:0
metrics:@{@"height": @(self.imageView.image.size.height)}
views:viewsDictionary]];
Ответ 2
Без добавления imageView в раскадровке я отлично нашел следующие работы:
-(UIImageView *)imageView
{
if (!_imageView) _imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
return _imageView;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.scrollView addSubview:self.imageView];
// Set the min and max:
self.scrollView.minimumZoomScale = 0.2;
self.scrollView.maximumZoomScale = 5.0;
self.scrollView.delegate = self;
// Set the content:
self.scrollView.zoomScale = 1.0; // reset zoomScale for new image
self.scrollView.contentSize = CGSizeMake(image.size.width/2, image.size.height/2);
self.imageView.frame = CGRectMake(0, 0, image.size.width/2, image.size.height/2);
self.imageView.image = image;
}
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
Ответ 3
Полный пример игровой площадки Swift
Простейшим примером, о котором я могу думать, является добавление UIImageView
к UIScrollView
. Это 100% кода, вам просто нужно добавить PNG к игровой площадке. Я назвал мой Image.png
. На игровой площадке вы увидите все, что отображается в "Live View". Pinch-zoom работает с помощью Ctrl-клика, чтобы поместить один палец на экран, а затем перетащить его. Пока контент не будет увеличен, экранное панорамирование не будет работать. Дважды нажмите изображение, чтобы переключиться между шкалой 1x и 3x.
На основе Apple Техническая нота TN2154: UIScrollView и Autolayout
Гоча
Вы найдете все, что очень расстраивает, если ваш контент не больше размера экрана. Если ваш контент полностью соответствует экрану, ничего не произойдет. Это значит, что вы тоже должны масштабироваться. Если вы хотите доказать, что это работает, протестируйте с действительно большим изображением (больше, чем окно).
import UIKit
import PlaygroundSupport
enum TapToggle {
case Regular, Large
}
class ScrollingViewController : UIViewController
{
var tapToggle: TapToggle = .Large
var scrollView: UIScrollView?
var imageView: UIImageView?
override func viewDidLoad()
{
let image = UIImage(named: "Image")
let imageView = UIImageView(image: image)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.backgroundColor = .white
imageView.isUserInteractionEnabled = true
let scrollView = UIScrollView()
scrollView.minimumZoomScale = 0.5
scrollView.maximumZoomScale = 10.0
scrollView.delegate = self
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(imageView)
let imageViewKey = "imageView"
let imageViews = [imageViewKey: imageView]
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[\(imageViewKey)]|", options: [], metrics: nil, views: imageViews))
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[\(imageViewKey)]|", options: [], metrics: nil, views: imageViews))
self.imageView = imageView
scrollView.backgroundColor = .white
self.view.addSubview(scrollView)
let scrollViewKey = "scrollView"
let scrollViews = [scrollViewKey: scrollView]
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[\(scrollViewKey)]|", options: [], metrics: nil, views: scrollViews))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[\(scrollViewKey)]|", options: [], metrics: nil, views: scrollViews))
self.scrollView = scrollView
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap(sender:)))
tapGesture.numberOfTapsRequired = 2
self.imageView?.addGestureRecognizer(tapGesture)
}
@objc
public func didDoubleTap(sender: AnyObject)
{
switch self.tapToggle {
case .Regular:
self.scrollView?.zoomScale = 1.0
self.tapToggle = .Large
case .Large:
self.scrollView?.zoomScale = 3.0
self.tapToggle = .Regular
}
}
}
extension ScrollingViewController: UIScrollViewDelegate
{
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.imageView
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat)
{
print("\(scale)")
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = ScrollingViewController()