【问题标题】:Adding a header view to a UIWebView similar to Safari and Articles向 UIWebView 添加标题视图,类似于 Safari 和文章
【发布时间】:2011-01-29 19:04:11
【问题描述】:

我想为UIWebView 添加一个标题视图,类似于 MobileSafari 中的地址/搜索栏和 Sophia Teutschler 的优秀 Articles.app。更准确地说,我想在 UIWebView 上方创建一个“拉动固定方向”视图,就像在文章中一样。文章确实使用了 UIWebView,所以这似乎是可能的。如this article 所述,有没有一种方法可以实现这一点,而不必将UIWebView 嵌入UIScrollView 并一直更新其大小?显然,我确实需要滚动事件以使“拉动以固定方向”行为相应。

【问题讨论】:

  • 你试过问苏菲吗?
  • 你试过给 UIWebView 添加子视图吗?

标签: iphone objective-c uiwebview uiscrollview mobile-safari


【解决方案1】:

我特别喜欢 AutoLayout,因为我可以使页眉的高度动态化。

这是我在控制器中使用 AutoLayout 的代码,其中引用“headerView”到标题视图和“webView”到 webView。

// Function called in ViewDidLoad:
func addHeaderToWebView(){
    // We load the headerView from a Nib
    headerView = NSBundle.mainBundle().loadNibNamed(WebViewHeader.nibName, owner: self, options: nil).first as! WebViewHeader

    headerView.translatesAutoresizingMaskIntoConstraints = false

    webView.scrollView.addSubview(headerView)

    // the constraints
    let topConstraint = NSLayoutConstraint(item: headerView, attribute: .Bottom, relatedBy: .Equal, toItem: webView.scrollView, attribute: .Top, multiplier: 1, constant: 0)
    let leftConstraint = NSLayoutConstraint(item: headerView, attribute: .Leading, relatedBy: .Equal, toItem: webView, attribute: .Leading, multiplier: 1, constant: 0)
    let rightConstraint = NSLayoutConstraint(item: headerView, attribute: .Trailing, relatedBy: .Equal, toItem: webView, attribute: .Trailing, multiplier: 1, constant: 0)

    // we add the constraints
    webView.scrollView.addConstraints([topConstraint])
    webView.addConstraints([leftConstraint, rightConstraint])
}

// Function called in viewWillLayoutSubviews: to update the scrollview of the webView content inset
func updateWebViewScrollViewContentInset(){
    webView.scrollView.contentInset = UIEdgeInsetsMake(headerView.frame.height, 0, 0, 0)
}

【讨论】:

    【解决方案2】:

    试试这个:

        UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, -100, WIN_WIDTH, 100)];
        redView.backgroundColor = [UIColor redColor];
        self.view.scrollView.contentInset = UIEdgeInsetsMake(100, 0, 0, 0);
        [self.view.scrollView addSubview:redView];
        NSURLRequest *request = [NSURLRequest requestWithURL: [NSURL URLWithString:@"http://www.baidu.com"]];
        [self.view loadRequest:request];
    

    【讨论】:

      【解决方案3】:

      经过几次尝试,我决定采用这个解决方案:

      基本上我刚刚将我的标题 UIView 添加为 webview.scrollview 子视图。

      为避免标题与浏览器视图重叠:

      • 循环浏览所有 [webview.scrollView 子视图]
      • 寻找最大的,应该包含浏览器(其他用于阴影和线条)
      • 改变它的起源.y

        代码如下:

        CGRect browserCanvas = web.bounds;
        for(int i=0; i< [[web.scrollView subviews] count]; i++)
        {
          UIView* subview = [[web.scrollView subviews] objectAtIndex:i];
          CGRect f = subview.frame;
          NSLog(@"sub %d -> x:%.0f, y:%.0f, w:%.0f, h:%.0f", i, f.origin.x, f.origin.y, f.size.width, f.size.height);
        
          if(f.origin.x == browserCanvas.origin.x && 
             f.origin.y == browserCanvas.origin.y && 
             f.size.width == browserCanvas.size.width && 
             f.size.height == browserCanvas.size.height)
             {
                 f.origin.y = header.frame.size.height;
                 subview.frame = f;
             }
        }
        
        if(![header superview])
        {
          [web.scrollView addSubview:header];
          [web.scrollView bringSubviewToFront:header];
        }
        

      【讨论】:

      • 如何使用 scrollView 的 contentInsets (并将你的框架 y 设置为负数)?
      • @kenji 效果很好,正如@Manesh 在另一个答案中的详细信息。除非您的 webView 有一个 css 位置设置为 fixed-top 的元素。如果您期待各种各样的网络内容,您会遇到一个带有固定顶部导航栏的页面,因此@sosergio 的建议效果最好。
      【解决方案4】:

      我认为最好的解决方案是将标题添加为 UIWebView 的 scrollView 的子视图,调整 UIEdgeInsets,并在 scrollViewDidScroll 委托函数中根据需要调整 scrollIndicatorInsets。

      我发现的所有其他解决方案都没有考虑滚动指示器。

      由于获得恰到好处的行为有点复杂,我决定编写一个类来处理所有这些:MMWebViewWithSmartHeader。它的边缘仍然有点粗糙,但应该会有所帮助。

      【讨论】:

      • +1,尽管我无法使用设置为 headerView 的UIImageView 来完成工作。我不得不将UIImageView 包裹在UIView 中。
      • 不错,但当 web 视图缩放或在 x 轴上平移时很难看。标题应锁定在 x 轴上,并且不受滚动视图缩放的影响。
      • 我的坏处:缩放行为很好,但 x 轴问题仍然存在。
      • - (void)scrollViewDidScroll:(UIScrollView *)scrollView末尾添加CGRect headerFrame = self.headerView.frame;headerFrame.origin.x = scrollView.contentOffset.x;self.headerView.frame = headerFrame;解决问题
      • 我遇到了一个问题,在将子视图添加到 webview 的滚动视图后,一半的网页将无法点击,我通过在位置 0 处插入子视图来修复它(因此它位于视图层次结构的后面),不知道为什么它有效,但确实有效。
      【解决方案5】:

      Enormego 发布了一些示例代码来实现拉动刷新:

      https://github.com/enormego/EGOTableViewPullRefresh

      其实没那么复杂。您只需创建标题栏并将其作为子视图添加到UITableView 即可在表格视图中获得 Safari/Articles 样式的标题栏。我正在使用的应用程序上正是这样做的:

      GBSpendingMeter *meterView = [[[GBSpendingMeter alloc] initWithFrame:CGRectMake(0,0,320,44)] autorelease];
      
      // The meterView will appear pinned to the top of the table, similar to a headerView
      [self.tableView addSubview:meterView];
      

      棘手的部分是观察表格上的滚动事件(仅供参考,UITableView 是 UIScrollView 的子类,因此所有相同的通知/回调都应该工作),但我链接到的示例代码有一个很好的例子来说明它是如何工作的。

      【讨论】:

      • 我在为任何类型的UITableView 实现这些东西时没有任何问题,但我需要为UIWebView 提供它。
      【解决方案6】:

      我不能肯定地说,但 Twitter 似乎使用 UITableView 来实现这一点。也许您可以尝试将您的视图放在表格视图的标题中,并将您的内容放在一个单元格中。

      这是一个有趣的例子,你可以考虑看看 - How to make a Pull-To-Reload TableView just like Tweetie 2

      【讨论】:

      • 我在为任何类型的UITableView 实现这些东西时没有任何问题,但我需要为UIWebView 提供它。
      • 我认为 Adam 建议使用单个自定义单元格制作一个 tableView,该单元格包含一个 UIWebView,其中加载了您的 Web 内容。
      【解决方案7】:

      文章可能没有使用 UIWebView 来显示主要文章文本。要完成您的任务,几乎可以肯定需要 UIScrollView。可能不需要调整其子视图的大小。查看 Apple 提供的 UIScrollView 代码示例。

      【讨论】:

      • 文章几乎肯定使用UIWebView
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多