Ich habe eine Frage zu UIScrollview
.
Die Geschichte ist, ich habe eine UIView
namens ChartsView, die ich selbst mit der Überschreibungsmethode drawRect()
neu zeichnet. Der Inhalt der Zeichnung wurde dynamisch generiert. Also weiß ich nicht bis zur Laufzeit. Die Frage ist, wie und wo kann ich die Inhaltsgröße der Superansicht (ScrollView) dynamisch einstellen?
- (void)viewDidLoad
{
[super viewDidLoad];
// not this way. it's fixed size.....
ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)];
self.scrollView.contentSize = chartsView.frame.size;
[self.scrollView addSubview:chartsView];
}
Ein einfacher Weg
- (void)viewDidLoad
{
float sizeOfContent = 0;
UIView *lLast = [scrollView.subviews lastObject];
NSInteger wd = lLast.frame.Origin.y;
NSInteger ht = lLast.frame.size.height;
sizeOfContent = wd+ht;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent);
}
Swift (2,0)
@IBOutlet weak var btnLatestButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let height = btnLatestButton.frame.size.height
let pos = btnLatestButton.frame.Origin.y
let sizeOfContent = height + pos + 10
scrollview.contentSize.height = sizeOfContent
}
Oben ist natürlich, wenn Sie nur eine festgelegte Anzahl von Ansichten in Ihrem Scrollview haben. Die IOS Rocks-Methode ist zwar verfügbar, aber für mich nicht gut, da mehr Platz geschaffen wurde, als ich brauchte.
let lastView : UIView! = scrollview.subviews.last
let height = lastView.frame.size.height
let pos = lastView.frame.Origin.y
let sizeOfContent = height + pos + 10
scrollview.contentSize.height = sizeOfContent
Es ist nicht 100% ig garantiert, dass das letzte Objekt im Array scrollView.subviews das höchste y-Origin-Objekt in Ihrer Bildlaufansicht zurückgibt. Das Subviews-Array ist nach Z-Index angeordnet (dh das letzte Objekt im Subviews-Array ist das Objekt, das am höchsten gestapelt ist und die oberste Subansicht in den Unteransichten der Bildlaufansicht ist.) Stattdessen ist die Verwendung einer einfachen Sortierfunktion genauer durchlaufen die Unteransichten und erhalten das Objekt mit dem höchsten y-Ursprung.
Hier ist eine grundlegende Funktion in Swift 3, die das kann:
func calculateContentSize(scrollView: UIScrollView) -> CGSize {
var topPoint = CGFloat()
var height = CGFloat()
for subview in scrollView.subviews {
if subview.frame.Origin.y > topPoint {
topPoint = subview.frame.Origin.y
height = subview.frame.size.height
}
}
return CGSize(width: scrollView.frame.size.width, height: height + topPoint)
}
Verwendung (in viewDidLayoutSubviews oder bei jeder Aktualisierung der Inhaltsgröße):
scrollView.contentSize = calculateContentSize(scrollView: scrollView)
UPDATE Swift 4
Hier ist eine etwas konsistentere Version in Swift 4
extension UIScrollView {
func updateContentView() {
contentSize.height = subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? contentSize.height
}
}
Verwendungszweck:
myScrollView.updateContentView()
Vielen Dank an IOS Rocks und CularBytes für die Leads. Ich habe zwei Probleme (für mich) mit den obigen Lösungen gefunden:
Außerdem verwende ich Autolayout, um die Seiten der UIScrollView zu fixieren, so dass ich mich nicht um die Breite kümmern muss (wie CularBytes).
Ich habe es mir ausgedacht und funktioniert (in Swift 3.0):
func setScrollViewContentSize() {
var height: CGFloat
let lastView = self.myScrollView.subviews[0].subviews.last!
print(lastView.debugDescription) // should be what you expect
let lastViewYPos = lastView.convert(lastView.frame.Origin, to: nil).y // this is absolute positioning, not relative
let lastViewHeight = lastView.frame.size.height
// sanity check on these
print(lastViewYPos)
print(lastViewHeight)
height = lastViewYPos + lastViewHeight
print("setting scroll height: \(height)")
myScrollView.contentSize.height = height
}
Ich nenne das in meiner viewDidAppear()
-Methode.
override func viewDidAppear(_ animated: Bool) {
var height: CGFloat
let lastView = self.scrollView.subviews[0].subviews.last!
let lastViewYPos = lastView.convert(lastView.frame.Origin, to: nil).y
let lastViewHeight = lastView.frame.size.height
height = lastViewYPos + lastViewHeight
scrollView.contentSize.height = height
}
Versuche dies -
- (void)viewDidLoad
{
[super viewDidLoad];
// not this way. it's fixed size.....
ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)];
//self.scrollView.contentSize = chartsView.frame.size;
[self.scrollView setContentSize:CGSizeMake(chartsView.frame.size.width, chartsView.frame.size.height)];
[self.scrollView addSubview:chartsView];
}
versuche dies
- (void)viewDidLoad
{
[super viewDidLoad];
// not this way. it's fixed size.....
ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)];
self.scrollView.contentSize = chartsView.frame.size;
[self.scrollView setNeedsDisplay];
[self.scrollView addSubview:chartsView];
}
Berechnen Sie UIScrollview contentSize dynamisch (abhängig vom Rahmen der Unteransichten)
Schnell:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
DispatchQueue.main.async {
var contentRect = CGRect.zero
for view in self.scrollView.subviews {
contentRect = contentRect.union(view.frame)
}
self.scrollView.contentSize = contentRect.size
}
}
Ziel c:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
dispatch_async(dispatch_get_main_queue(), ^ {
CGRect contentRect = CGRectZero;
for(UIView *view in scrollView.subviews)
contentRect = CGRectUnion(contentRect,view.frame);
scrollView.contentSize = contentRect.size;
});
}
Dies ist eine Erweiterung zu Swift 3
extension UIScrollView {
func updateContentViewSize() {
var newHeight: CGFloat = 0
for view in subviews {
let ref = view.frame.Origin.y + view.frame.height
if ref > newHeight {
newHeight = ref
}
}
let oldSize = contentSize
let newSize = CGSize(width: oldSize.width, height: newHeight + 100)
contentSize = newSize
}
}
Bei der Verwendung von Bildlaufansichten im Storyboard ist es besser, die Inhaltsgröße anhand der Anzahl der in der Bildlaufansicht vorhandenen Ansichten zu berechnen, als die Inhaltsgröße programmgesteuert mit einem statischen Wert anzugeben. Hier sind die Schritte zum dynamischen Abrufen der Inhaltsgröße.
Schritt 1: Fügen Sie eine Bildlaufansicht hinzu, um sie im Storyboard anzuzeigen, und fügen Sie führende, nachfolgende, obere und untere Einschränkungen hinzu (alle Werte sind Null).
Schritt 2: Fügen Sie nicht direkt Ansichten hinzu, die Sie für die direkte Bildlaufansicht benötigen. Fügen Sie zunächst eine Ansicht zur Bildlaufansicht hinzu (dies ist unsere Inhaltsansicht für alle Benutzeroberflächen Elemente). Fügen Sie dieser Ansicht die folgenden Einschränkungen hinzu. Führende, nachfolgende, obere und untere Randbedingungen (Alle Werte sind Null). Fügen Sie der Hauptansicht die gleiche Höhe und Breite hinzu (d. H. Die Bildlaufansicht enthält). Bei gleicher Höhe Priorität auf niedrig setzen. (Dies ist der wichtige Schritt zum Festlegen der Inhaltsgröße.) Die Höhe dieser Inhaltsansicht richtet sich nach der Anzahl der der Ansicht hinzugefügten Ansichten. Angenommen, Sie haben als letzte Ansicht eine Beschriftung hinzugefügt, und seine Y-Position ist 420, und die Höhe ist 20. Dann ist Ihre Inhaltsansicht 440.
Schritt 3: Fügen Sie Einschränkungen zu allen Ansichten hinzu, die Sie gemäß Ihren Anforderungen in der Inhaltsansicht hinzugefügt haben.