【问题标题】:Offsetting UIRefreshControl偏移 UIRefreshControl
【发布时间】:2013-06-22 22:54:35
【问题描述】:

我目前正在为我的应用程序使用 JASidePanel,并且我有一个带有 UIRefreshControl 的 UITableViewcontroller 作为它的 ViewControllers 之一。我的 tableview 的宽度仍然为 320 像素,因此 UIRefreshControl 在视图中间居中。我试图弄清楚是否有办法偏移 UIRefreshControl(将 x 向左移动 20 像素),以便在我的侧面板可见时它看起来居中。

谢谢!

【问题讨论】:

  • 是否有不能更改表格视图框架的原因?
  • 因为我有交替的彩色行,所以如果有人试图查看侧面板下方,它看起来不完整:(
  • 您可以尝试将平移变换添加到刷新控件,并使用等于侧面板宽度的“x”移动。
  • 这是一个有趣的想法。不确定它是否会起作用,但我会尝试。
  • 你好@user754905你试过下面的答案吗

标签: ios ios6 uirefreshcontrol


【解决方案1】:

斯威夫特 5:

有几种方法可以改变 UIRefreshControl 的位置。刷新控件的设置是用最方便的方式完成的。

刷新控件是滚动视图一部分的示例:

let refresher = UIRefreshControl()
refresher.addTarget... // Add a proper target.
scrollView.refreshControl = refresher

请注意,您可以使用 tableView 代替 scrollView。

选项 1: 您可以使用视图的框架/边界。

scrollView.refreshControl?.refreshControl.bounds.origin.x = 50

选项 2: 或者您可以使用自动布局来实现。


scrollView.refreshControl?.translatesAutoresizingMaskIntoConstraints = false

scrollView.refreshControl?.topAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
scrollView.refreshControl?.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: -50).isActive = true

【讨论】:

    【解决方案2】:

    您需要继承 UIScrollView,下面的代码将根据 contentInset 调整 UIRefreshControl 位置(仅适用于垂直滚动,但易于采用水平滚动)

    override public func layoutSubviews() {
        super.layoutSubviews()
        guard let refreshControl = self.refreshControl else { return }
    
        var newFrame = refreshControl.frame
    
        if contentInset.top > .zero {
            let yOffset = abs(contentInset.top + contentOffset.y)
    
            newFrame.origin.y = -contentInset.top - yOffset
            newFrame.size.height = yOffset
        }
    
        guard newFrame != refreshControl.frame else { return }
        refreshControl.frame = newFrame
    }
    

    【讨论】:

      【解决方案3】:

      您需要设置UIRefreshControl 的框架。使用此代码

      UIRefreshControl *refContr=[[UIRefreshControl alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
      [refContr setTintColor:[UIColor blueColor]];
      [refContr setBackgroundColor:[UIColor greenColor]];
      
      [stocktable addSubview:refContr];
      [refContr setAutoresizingMask:(UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleLeftMargin)];
      
      [[refContr.subviews objectAtIndex:0] setFrame:CGRectMake(30, 0, 20, 30)];
      
      
      NSLog(@"subViews %@",refContr.subviews); 
      

      输出:

      【讨论】:

      • 很棒的提示。虽然 iOS 7 的仅供参考,但它少了 10 个点(即向左)。所以:[[refContr.subviews objectAtIndex:0] setFrame:CGRectMake(20, 0, 20, 30)];
      • UIRefreshControl 并不是要添加为子视图...根据我的经验,这样做确实会在未删除目标时导致崩溃... UIRefreshControl 添加为子视图时也可能会导致其他问题子视图
      • 改变第一个 UIRefreshControl 子视图的框架就可以了。我正在使用 SWRevealViewController 并且有效:- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; CGFloat rearPanelWidth = self.revealViewController.rearViewRevealWidth; UIView *refreshView = self.refreshControl.subviews[0]; CGRect refreshFrame = refreshView.frame; refreshFrame.size.width = rearPanelWidth; refreshView.frame = refreshFrame; }
      【解决方案4】:
      - (UIRefreshControl *)refreshControl
      {
          if (!_refreshControl)
          {
              _refreshControl = [UIRefreshControl new];
              _refreshControl.tintColor = [UIColor lightGrayColor];
      

      _refreshControl.bounds = CGRectInset(_refreshControl.bounds, 0.0, 10.0); // 用 inset 10.0 让它失望

              [_refreshControl addTarget:self
                                  action:@selector(pullToRefresh)
                        forControlEvents:UIControlEventValueChanged];
          }
          return _refreshControl;
      }
      

      【讨论】:

      • [self.refreshControl beginRefreshing];把它放在 viewWillAppear 开始动画
      【解决方案5】:

      对于 Swift 2.2 的解决方案是

      let offset = -50
      
      let refreshControl = UIRefreshControl()
      refreshControl.bounds = CGRect(x: refreshControl.bounds.origin.x, y: offset,
                                     width: refreshControl.bounds.size.width,
                                     height: refreshControl.bounds.size.height)
      refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
      refreshControl.addTarget(self, action: #selector(networking), forControlEvents: UIControlEvents.ValueChanged)
      self.profileTable.addSubview(refreshControl)
      

      就是这样。

      【讨论】:

        【解决方案6】:

        这是一个类似于 Werewolf 建议的解决方法的 Swift 版本。我正在使用我自己的自定义活动视图类 (MyCustomActivityIndicatorView),它也是刷新控件的子视图,所以我确保我不会弄乱它的框架,只是默认子视图的框架。在 super 上调用 layoutSubviews 后,我调整了自定义活动视图的框架以匹配。这都包含在自定义的UIRefreshControl 子类中。

        override func layoutSubviews() {
        
            for view in subviews {
                if view is MyCustomActivityIndicatorView {
                    continue
                } else {
                    // UIRefreshControl sizes itself based on the size of it's subviews. Since you can't remove the default refresh indicator, we modify it's frame to match our activity indicator before calling layoutSubviews on super
                    var subFrame = view.frame
                    subFrame.size = activityView.intrinsicContentSize()
        
                    // add some margins
                    subFrame.offsetInPlace(dx: -layoutMargins.left, dy: -layoutMargins.top)
                    subFrame.insetInPlace(dx: -(layoutMargins.left+layoutMargins.right), dy: -(layoutMargins.top+layoutMargins.bottom))
        
                    view.frame = subFrame.integral
                }
            }
        
            super.layoutSubviews()
        
            activityView.frame = bounds
        }
        

        注意:我添加了 UIView 的布局边距,这不是绝对必要的,但给我的活动指示器一些呼吸空间。

        【讨论】:

          【解决方案7】:

          我需要这样做才能将 UIRefreshControl 向下移动。我的解决方案是继承 UIRefreshControl,并覆盖 layoutSubviews 方法以在每个子视图上设置 CAAffineTransform 转换。不幸的是,您不能只在 UIRefreshControl 上设置转换。

          根据需要更改 xOffset 和 yOffset。

          @interface MyUIRefreshControl : UIRefreshControl
          @end
          
          @implementation MyUIRefreshControl
          
          - (void)layoutSubviews {
              [super layoutSubviews];
              for (UIView *view in self.subviews) {
                  view.transform = CGAffineTransformMakeTranslation(xOffset, yOffset);
              }
          }
          
          @end
          

          【讨论】:

            【解决方案8】:

            尝试编辑bounds。例如,将控件向下移动 +50px:

            refreshControl.bounds = CGRectMake(refreshControl.bounds.origin.x,
                                               -50,
                                               refreshControl.bounds.size.width,
                                               refreshControl.bounds.size.height);
            [refreshControl beginRefreshing];
            [refreshControl endRefreshing];
            

            【讨论】:

            • 这是一个比接受的答案更快、更简单的解决方案,但如果我希望我的UIRefreshControl 更加个性化,我会接受接受的答案。我个人正在使用这个解决方案。
            • 有人能解释一下为什么将 -50 设置为 y 原点会降低 50 个点吗?
            • 卢克:原点0,0在左下角..数字越小,位置越低。
            • 你也可以使用refreshControl.bounds = CGRectOffset(refreshControl.bounds, 0, 50)
            • 对我来说,是 50 而不是 -50。
            【解决方案9】:

            UIRefreshControl 的框架是自动管理的,因此尝试更改它的位置可能会产生意想不到的结果(尤其是在 iOS SDK 版本之间)。正如您所指出的,控件始终在其父视图的框架中水平居中。知道了这一点,您就可以通过抵消您的 superview 来“利用”这种情况。

            在您的情况下,将表格视图的框架设置为CGRect(-40, 0, 360, superViewHight)。这将使您的表格视图位于窗口左侧 40 点处。因此,您将需要相应地调整表格视图的内容,使其位于右侧 40 点或仅扩展额外的 40 点,但在屏幕外渲染的内容应该是填充。

            完成此操作后,您的UIRefreshControl 将位于您想要的左侧 20 点,因为它位于中心位置。

            【讨论】:

            • 感谢 Chris,很遗憾我无法移动表格,因为我有交替的彩色行,当用户查看侧面板下方时,这看起来很丑。
            • 不知道为什么水平移动会影响垂直排列的交替行?
            • 对不起,我没有正确阅读答案。这可能有效,但要正确处理子视图会很痛苦。
            • 克里斯,创建一个不可见的子视图(当前包含刷新控件的超级视图),然后添加刷新控件是否有意义?这将提供一个可以操作的视图,而不会使现有内容的布局复杂化。 [我偶然发现了这个答案,实际上并没有这种情况,所以不确定我是否考虑过。]
            猜你喜欢
            • 2015-05-19
            • 1970-01-01
            • 2013-10-14
            • 2013-10-07
            • 1970-01-01
            • 2021-08-17
            • 1970-01-01
            • 2021-04-07
            相关资源
            最近更新 更多