【问题标题】:Swift 3, iOS 10 - programmatically declared UIStackView not fitting screen widthSwift 3,iOS 10 - 以编程方式声明 UIStackView 不适合屏幕宽度
【发布时间】:2017-02-12 02:13:50
【问题描述】:

我是一名新的 Swift 开发人员,使用 WKWebView 实现 Safari 的主要部分(我需要在 Javascript 和 Swift 之间进行接口,因此 SFSafariViewController 不是一个选项)并尝试以编程方式声明所有元素。

为了模仿 Safari 的搜索栏和进度条,我想设置一个 UISearchBar,堆叠在 UIProgressView 的顶部,作为 UIViewController 的 titleView UINavigationItem。我可以只使用一个元素来管理它,但不能使用两个元素的堆栈。

这是我的项目现在的样子。 UISearchBarUIProgressView 太宽或太薄,无法正确填充 UINavigationBar,具体取决于旋转:

这是我的 ViewController.swift 代码:

import WebKit
import UIKit

class ViewController: UIViewController, WKNavigationDelegate, UISearchBarDelegate {
    var searchBar: UISearchBar = UISearchBar()
    var progressView: UIProgressView = UIProgressView(progressViewStyle: .bar)
    var stackView: UIStackView = UIStackView()
    var webView: WKWebView!

    override func loadView() {
        webView = WKWebView()
        webView.navigationDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        /** Watches for changes in the WKWebView.estimatedProgress variable, and  */
        webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)

        /** Initialise toolbar elements */
        let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let refresh = UIBarButtonItem(barButtonSystemItem: .refresh, target: webView, action: #selector(webView.reload))
        toolbarItems = [spacer, refresh]
        navigationController?.isToolbarHidden = false

        /** Initialise the UISearchBar */
        searchBar.delegate = self // not clear yet whether setting this is necessary.
        searchBar.searchBarStyle = UISearchBarStyle.minimal
        searchBar.showsCancelButton = true
        searchBar.widthAnchor.constraint(equalToConstant: (navigationController?.navigationBar.bounds.width)!).isActive = true
        // searchBar.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
        // searchBar.sizeToFit()

        /** Initialise the UIProgressView */
        progressView.widthAnchor.constraint(equalToConstant: (navigationController?.navigationBar.bounds.width)!).isActive = true
        // progressView.heightAnchor.constraint(equalToConstant: 4.0).isActive = true
        // progressView.sizeToFit()

        /** Add the UISearchBar & UIProgressView to the UIStackView, then initialise it and finally set it as the UINavigationItem's titleView.*/
        stackView.axis  = UILayoutConstraintAxis.vertical
        stackView.alignment = UIStackViewAlignment.center
        stackView.distribution = UIStackViewDistribution.fillProportionally
        stackView.addArrangedSubview(searchBar)
        stackView.addArrangedSubview(progressView)
        stackView.translatesAutoresizingMaskIntoConstraints = false;
        /* These two constraints are causing a crash, so disabling them for now. */
        // stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        // stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
        navigationItem.titleView = stackView

        navigationController?.hidesBarsOnSwipe = true

        let url = URL(string: "https://en.wikipedia.org")!
        webView.load(URLRequest(url: url))
        webView.allowsBackForwardNavigationGestures = true
    }

    /** Updates the UIProgressView. */
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        // keyPath "estimatedProgress" is equivalent to #keyPath(WKWebView.estimatedProgress)
        if keyPath == "estimatedProgress" {
            // progressView.isHidden = webView.estimatedProgress == 1 // if we want to hide upon 100%
            progressView.progress = Float(webView.estimatedProgress)
        }
    }

    /** Sets the webView's title upon navigation finishing. */
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        title = webView.title
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

注意:任何接受的解决方案都必须在回调后继续正确显示元素堆栈,以隐藏由navigationController?.hidesBarsOnSwipe 发起的UINavigationBar,即。当用户在 WKWebView 上执行滑动手势时。

【问题讨论】:

    标签: ios swift uiview swift3 wkwebview


    【解决方案1】:

    Hacking With Swift 的作者在 Reddit 上提供的 solution 的指导下,用我的最终代码进行报告:

    class ViewController: UIViewController, UISearchBarDelegate {
        var webView: WKWebView?
        var searchBar: UISearchBar?
        var progressView: UIProgressView?
    
        override func loadView() {
            super.loadView()
            setUpWebView()
            view = self.webView! // TODO: fix constraints error when video is run.
    
            setUpSearchbar()
            setUpProgressView()
    
            let url = URL(string: "http://www.bbc.com")!
            webView!.load(URLRequest(url: url))
        }
    
        func setUpWebView(){
            webView = WKWebView()
        }
    
        func setUpSearchbar(){
            searchBar = UISearchBar()
            searchBar!.delegate = self
        }
    
        func setUpProgressView() {
            webView!.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)
            guard let bar = navigationController?.navigationBar else { return; }
    
            progressView = UIProgressView(progressViewStyle: .bar)
            progressView!.translatesAutoresizingMaskIntoConstraints = false
            bar.addSubview(progressView!)
    
            progressView!.leadingAnchor.constraint(equalTo: bar.leadingAnchor).isActive = true
            progressView!.trailingAnchor.constraint(equalTo: bar.trailingAnchor).isActive = true
            progressView!.bottomAnchor.constraint(equalTo: bar.bottomAnchor).isActive = true
        }
    
        override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
            if keyPath == "estimatedProgress" {
                // progressView.isHidden = webView.estimatedProgress == 1 /* Optional. This hides progressView on 100% */
                progressView!.progress = Float((webView?.estimatedProgress)!)
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-12-04
      • 2011-02-04
      • 1970-01-01
      • 1970-01-01
      • 2013-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多