【问题标题】:How to center content in a UIScrollView with contentOffset如何使用 contentOffset 在 UIScrollView 中居中内容
【发布时间】:2013-03-13 02:05:34
【问题描述】:

这应该是一个非常简单的问题,但我无法获得想要的结果。我水平滚动 UIScrollView,宽度为 320。其内容的宽度为 5000。我试图将内容居中:

// 'self' is the UIScrollView
CGFloat newContentOffsetX = (self.width/2) + (self.contentSize.width/2);
self.contentOffset = CGPointMake(newContentOffsetX, 0);

我不明白为什么这不是使内容居中。你能看出计算有什么问题吗?

【问题讨论】:

    标签: ios objective-c uiscrollview


    【解决方案1】:

    我想你想要:

    CGFloat newContentOffsetX = (self.contentSize.width/2) - (self.bounds.size.width/2);
    

    图表:

    |------------------------self.contentSize.width------------------------|
                             |-----self.width-----|
    |-------- offset --------|
                                        ^ center
    

    【讨论】:

    • 对“self.width”的混淆感到抱歉。这是我使用 UIView 类别添加的快捷方式。你为什么使用 self.bounds 而不是 self.frame?
    • 我怀疑self.width 不是问题——实际上,你想从contentSize.width 中减去它——但我出于习惯使用了self.boundsself.bounds.sizeself.frame.size 应该相同;我倾向于使用self.bounds,除非我需要使用self.frame.origin 获得的origin-relative-to-superview。
    【解决方案2】:

    使用以下代码:

    CGFloat newContentOffsetX = (scrollView.contentSize.width - scrollView.frame.size.width) / 2;
    scrollView.contentOffset = CGPointMake(newContentOffsetX, 0);
    

    【讨论】:

      【解决方案3】:

      斯威夫特 4

      滚动到ScrollView的内容中心

      let centerOffsetX = (scrollView.contentSize.width - scrollView.frame.size.width) / 2
      let centerOffsetY = (scrollView.contentSize.height - scrollView.frame.size.height) / 2
      let centerPoint = CGPoint(x: centerOffsetX, y: centerOffsetY)
      scrollView.setContentOffset(centerPoint, animated: true)
      

      【讨论】:

        【解决方案4】:

        我创建了一个带有 IBInspectable 属性的简单 UIScrollView 扩展,以水平和/或垂直居中内容。仅当滚动视图内容大小小于滚动视图大小时才有效。

        这是 Swift 5.2 代码:

        import UIKit
        
        @IBDesignable class CenteredScrollView: UIScrollView {
            @IBInspectable var verticallyCentered: Bool = false
            @IBInspectable var horizontallyCentered: Bool = false
        
            override var contentSize: CGSize {
                didSet {
                    if contentSize.height <= bounds.height && verticallyCentered {
                        centerVertically()
                    }
        
                    if contentSize.width <= bounds.width && horizontallyCentered {
                        centerHorizontally()
                    }
                }
            }
        
            private func centerVertically() {
                let yContentOffset = (contentSize.height / 2) - (bounds.size.height / 2)
                contentOffset = CGPoint(x: contentOffset.x, y: yContentOffset)
            }
        
            private func centerHorizontally() {
                let xContentOffset = (contentSize.width / 2) - (bounds.size.width / 2)
                contentOffset = CGPoint(x: xContentOffset, y: contentOffset.y)
            }
        }
        

        【讨论】:

          【解决方案5】:

          不是最好的解决方案,但可能对你有用

          - (void)viewDidLayoutSubviews {
              [super viewDidLayoutSubviews];
              [self centerScrollViewAnimated:NO];
          }
          
          - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
              [self centerScrollViewAnimated:YES];
          }
          
          - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
              *targetContentOffset = [self suggestedCenteredContentOffset];
          }
          
          - (CGPoint)suggestedCenteredContentOffset {
              CGSize imageSize = self.pickedImage.size;
              CGSize containerSize = self.zoomingScrollView.bounds.size;
              CGPoint result = self.zoomingScrollView.contentOffset;
          
              if ( self.zoomingScrollView.zoomScale * imageSize.width < containerSize.width )
                  result.x = MIN((self.zoomingScrollView.zoomScale * imageSize.width - containerSize.width)/2, 0);
          
              if ( self.zoomingScrollView.zoomScale * imageSize.height < containerSize.height )
                  result.y = MIN((self.zoomingScrollView.zoomScale * imageSize.height - containerSize.height)/2, 0);
          
              return result;
          }
          
          - (void)centerScrollViewAnimated:(BOOL)animated {
              [self.zoomingScrollView setContentOffset:[self suggestedCenteredContentOffset] animated:animated];
          }
          

          【讨论】:

            【解决方案6】:

            斯威夫特 5+

            @IBDesignable class CenteredScrollView: UIScrollView {
                
                @IBInspectable var isVerticallyCentered: Bool = false
                @IBInspectable var isHorizontallyCentered: Bool = false
            
                public func center(vertically: Bool, horizontally:Bool, animated: Bool) {
                    
                    guard vertically || horizontally else {
                        return
                    }
                    
                    var offset = contentOffset
                    if vertically && contentSize.height <= bounds.height {
                        offset.y = (contentSize.height / 2) - (bounds.size.height / 2)
                    }
            
                    if horizontally && contentSize.width <= bounds.width {
                        offset.x = (contentSize.width / 2) - (bounds.size.width / 2)
                    }
                    setContentOffset(offset, animated: animated)
                    
                }
                
                override func layoutSubviews() {
                    super.layoutSubviews()
                    center(vertically: isVerticallyCentered, horizontally: isHorizontallyCentered, animated: false)
                }
                
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-08-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-08-03
              • 1970-01-01
              • 2018-11-30
              相关资源
              最近更新 更多