Swift开发迷你浏览器

作者: Color酸奶 | 来源:发表于2016-04-10 13:01 被阅读685次

前不久写了一篇[WKWebView解读和使用],基于WKWebView,我制作了一个简易的浏览器。当然里面有些功能还没实现,大家可以自己来定制。所以开始前我建议如果对WKWebView不熟悉的话去读读[WKWebView解读和使用]这篇文章。

测试环境:Xcode7.3.0

1.整体效果

1.gif

2.准备工作

首先让类继承WKNavigationDelegate,WKUIDelegate两个协议,然后在初始化各功能之前需要声明一些部件:

//获取设备宽高
    let screenWidth = UIScreen.mainScreen().bounds.width
    let screenHeight = UIScreen.mainScreen().bounds.height
    
    var webView = WKWebView()
    //下部菜单
    var downToolbar = UIToolbar()
    //网址输入框
    var textField = UITextField()
    //上部菜单
    var upBar = UIView()
    //wk配置
    let configuration = WKWebViewConfiguration()
    //全局点击按钮
    var button5 = UIButton()
    //进度条控件
    var progBar = UIProgressView()
    //设置弹出菜单的view
    var menuView = UIView()
    //创建后退按钮
    var btnBack = UIBarButtonItem()
    //创建前进按钮
    var btnForward = UIBarButtonItem()
    //设置判断旗帜
    var buttonFlag = 1

在Info.plist中加入:


2.jpg

3.创建WKWebView

 //设置webView
    func setWebView()
    {
        webView = WKWebView(frame: CGRectMake(0, 64, screenWidth, screenHeight-108))
        self.webView.navigationDelegate = self
        self.webView.UIDelegate = self
        self.view.addSubview(webView)
        self.webView.addObserver(self, forKeyPath: "estimatedProgress", options: NSKeyValueObservingOptions.New, context: nil)
    }

4.配置WKWebView

//js提示框
    func webView(webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: () -> Void) {
        let alert = UIAlertController(title: nil, message: message, preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "好", style: .Default, handler: { (_) -> Void in
            completionHandler()
        }))
        
        self.presentViewController(alert, animated: true, completion: nil)
    }
    
    //js确认框
    func webView(webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: (Bool) -> Void) {
        let alert = UIAlertController(title: nil, message: message, preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "确认", style: .Default, handler: { (_) -> Void in
            completionHandler(true)
        }))
        alert.addAction(UIAlertAction(title: "取消", style: .Cancel, handler: { (_) -> Void in
            completionHandler(false)
        }))
        
        self.presentViewController(alert, animated: true, completion: nil)
    }
    
    //js文本输入框
    func webView(webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: (String?) -> Void) {
        let alert = UIAlertController(title: prompt, message: defaultText, preferredStyle: .Alert)
        
        alert.addTextFieldWithConfigurationHandler { (textField: UITextField) -> Void in
            textField.textColor = UIColor.redColor()
        }
        alert.addAction(UIAlertAction(title: "好", style: .Default, handler: { (_) -> Void in
            completionHandler(alert.textFields![0].text!)
        }))
        
        self.presentViewController(alert, animated: true, completion: nil)
    }

//允许点击
    func webView(webView: WKWebView, createWebViewWithConfiguration configuration: WKWebViewConfiguration, forNavigationAction navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        if !(navigationAction.targetFrame?.mainFrame != nil) {
            self.webView.loadRequest(navigationAction.request)
        }
        return nil
    }

func webView(webView: WKWebView, didCommitNavigation navigation: WKNavigation!) {
        //收起键盘
        textField.resignFirstResponder()
    }

5.创建进度条

 //设置进度条
    func setProgressView()
    {
        //创建进度工具条
        progBar = UIProgressView(progressViewStyle:UIProgressViewStyle.Bar)
        // 设置UIProgressView的大小
        progBar.frame = CGRectMake(0 , 0 , screenWidth, 30)
        progBar.progressTintColor = UIColor.greenColor()
        // 设置该进度条的初始进度为0
        progBar.progress = 0
        self.webView.addSubview(progBar)
    }

6.监听进度条

//监听
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if keyPath == "estimatedProgress" {
            self.progBar.alpha = 1.0
            progBar.setProgress(Float(webView.estimatedProgress), animated: true)
            
            if(self.webView.estimatedProgress >= 1.0) {
                UIView.animateWithDuration(0.3, delay: 0.1, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
                    self.progBar.alpha = 0.0
                    }, completion: { (finished:Bool) -> Void in
                        self.progBar.progress = 0
                })
            }
        }
    }

7.创建下方工具条

 //设置下方工具条
    func setDownToolbar()
    {
        //创建Toolbar
        downToolbar =  UIToolbar(frame:CGRectMake(0, screenHeight-44, screenWidth, 44))
        downToolbar.barTintColor = UIColor.blackColor()
        downToolbar.tintColor = UIColor.whiteColor()
        //创建后退按钮
        btnBack = UIBarButtonItem(image:UIImage(named:"back.png"),
            style:UIBarButtonItemStyle.Plain, target:self, action:#selector(ViewController.back(_:)))
        btnBack.enabled = false
        //创建分隔符1
        let btnGap1 =  UIBarButtonItem(barButtonSystemItem:.FlexibleSpace,
            target:nil,
            action:nil)
        //创建前进按钮
        btnForward = UIBarButtonItem(image:UIImage(named:"forward.png"),
            style:.Plain, target:self, action:#selector(ViewController.forward(_:)))
        btnForward.enabled = false
        //创建分隔符2
        let btnGap2 =  UIBarButtonItem(barButtonSystemItem:.FlexibleSpace,
            target:nil,
            action:nil)
        //创建菜单按钮
        let btnMenu = UIBarButtonItem(image:UIImage(named:"menu.png"),
            style:.Plain, target:self, action:#selector(ViewController.showMenu))
        //创建分隔符3
        let btnGap3 =  UIBarButtonItem(barButtonSystemItem:.FlexibleSpace,
            target:nil,
            action:nil)
        //创建主页
        let btnHome = UIBarButtonItem(image:UIImage(named:"home.png"),
            style:.Plain, target:self, action:#selector(ViewController.toHome))
        //创建分隔符4
        let btnGap4 =  UIBarButtonItem(barButtonSystemItem:.FlexibleSpace,
            target:nil,
            action:nil)
        //创建刷新按钮
        let btnRefresh = UIBarButtonItem(image:UIImage(named:"refresh.png"),
            style:.Plain, target:self, action:#selector(ViewController.Refresh))
        //添加按钮
        downToolbar.setItems( [btnBack,btnGap1, btnForward,btnGap2,btnMenu,btnGap3,btnHome,btnGap4,btnRefresh], animated:true)
        self.view.addSubview(downToolbar)
    }

8.封装创建按钮方法

由于项目中需要大量用到创建按钮的方法,所以可以把它封装起来使代码简洁。

//封装添加按钮方法
    func addButton(title:String?,x:CGFloat,y:CGFloat,width:CGFloat,height:CGFloat) -> UIButton
    {
        let button = UIButton(frame: CGRectMake(x, y, width, height))
        button.setTitle(title, forState: UIControlState.Normal)
        button.titleLabel?.textAlignment = NSTextAlignment.Center
        return button
    }

9.创建弹出菜单

//初始化弹出菜单
    func menuInit()
    {
        //创建按钮
        let button1 = addButton("添加书签", x: 0,y: 0,width: screenWidth/4,height: 75)
        let button2 = addButton("书签", x: screenWidth/4, y: 0, width: screenWidth/4, height: 75)
        let button3 = addButton("下载", x: screenWidth/2, y: 0, width: screenWidth/4, height: 75)
        let button4 = addButton("文件管理", x: 3*screenWidth/4, y: 0, width: screenWidth/4, height: 75)
        button5 = addButton("隐身模式", x: 0, y: 75, width: screenWidth/4, height: 75)
        let button6 = addButton("分享", x: screenWidth/4, y: 75, width: screenWidth/4, height: 75)
        let button7 = addButton("设置", x: screenWidth/2, y: 75, width: screenWidth/4, height: 75)
        let button8 = addButton("关于", x: 3*screenWidth/4, y: 75, width: screenWidth/4, height: 75)

        //添加视图,以webview为参照系,加载谁上面就以谁为参照系
        menuView = UIView(frame: CGRectMake(0,screenHeight-108, screenWidth, 150))
        menuView.backgroundColor = UIColor.grayColor()
        menuView.addSubview(button1)
        menuView.addSubview(button2)
        menuView.addSubview(button3)
        menuView.addSubview(button4)
        menuView.addSubview(button5)
        menuView.addSubview(button6)
        menuView.addSubview(button7)
        menuView.addSubview(button8)
        //注意添加到webView上
        self.webView.addSubview(menuView)
        //添加事件,其他按钮类似
        button5.addTarget(self, action: #selector(ViewController.privateMode), forControlEvents: UIControlEvents.TouchUpInside)
    }

10.显示和隐藏弹出菜单

从Demo中看到,当我们点击下方工具条中间的图标时从底下弹出一个菜单。要实现这个功能,我的思路是创建一个UIView(第6步中已创建),使用动画改变坐标让它从下面移到指定位置:

//显示弹出菜单
    func showMenu()
    {
        if buttonFlag == 1
        {
            UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
            self.menuView.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(1, 1), CGAffineTransformMakeTranslation(0, -150))
            }, completion: nil)
            buttonFlag = 0
        }
        else
        {
            hideMenu()
        }
    }
    
    //隐藏按钮
    func hideMenu()
    {
        buttonFlag = 1
        UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
            self.menuView.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(1, 1), CGAffineTransformMakeTranslation(0, 150))
            }, completion: nil)
    }

11.创建上部菜单

//设置上方区域
    func setUpBar()
    {
        //创建顶部区域
        upBar = UIView(frame:CGRectMake(0, 0, screenWidth, 64))
        upBar.backgroundColor = UIColor.blackColor()
        //创建输入框
        textField = UITextField(frame:CGRectMake(20, 20, (screenWidth*3)/4, 30))
        textField.backgroundColor = UIColor.whiteColor()
        //自动清除
        textField.clearsOnBeginEditing = true
        //创建Go按钮
        let btnGo = UIButton(frame:CGRectMake(30+(screenWidth*3)/4, 15, 30, 40))
        btnGo.setImage(UIImage(named:"go.png"), forState: UIControlState.Normal)
        btnGo.addTarget(self, action: #selector(ViewController.goToWeb), forControlEvents: UIControlEvents.TouchUpInside)
        //添加视图
        upBar.addSubview(textField)
        upBar.addSubview(btnGo)
        self.view.addSubview(upBar)
    }

12.加载网址

首先把加载网址封装成方法,然后直接调用。

//加载指定网址
    func loadUrl(url:String?)
    {
        let nsurl = NSURL(string: url!)
        let request = NSURLRequest(URL: nsurl!)
        self.webView.loadRequest(request)
    }

  //跳转指定网页
    func goToWeb()
    {
        let url = textField.text
        //判断网址是否合法
        if (url?.rangeOfString("http://")?.isEmpty != nil) ||
            (url?.rangeOfString("https://")?.isEmpty != nil) {
            loadUrl(url!)
        }
        else {
            //显示错误页面
            let url = NSBundle.mainBundle().URLForResource("404", withExtension: "html")
            self.webView.loadRequest(NSURLRequest(URL: url!))
        }
    }

这里简单的判断了网页是否合法,如果错误将会跳转至自定义的错误页。

13.按钮事件

网页前进和网页后退

//网页返回
    func back(sender:UIBarButtonItem)
    {
        if self.webView.canGoBack {
            webView.goBack()
        }
    }

    //网页前进
    func forward(sender:UIBarButtonItem)
    {
        if self.webView.canGoForward {
            webView.goForward()
        }
    }

主页按钮事件

//主页按钮事件
    func toHome() {
        let url = NSBundle.mainBundle().URLForResource("MyHome", withExtension: "html")
        self.webView.loadRequest(NSURLRequest(URL: url!))
    }

重新加载网页

 //重新加载网页
    func Refresh() {
        self.webView.reload()
    }

隐身模式

 //隐身模式
    func privateMode() {
        if configuration.websiteDataStore.persistent {
            configuration.websiteDataStore = WKWebsiteDataStore.nonPersistentDataStore()
            button5.setTitleColor(UIColor(red: 0, green: 255, blue: 255, alpha: 1.0), forState: UIControlState.Normal)
        }
        else {
            configuration.websiteDataStore = WKWebsiteDataStore.defaultDataStore()
            button5.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
        }
        showMenu()
    }

14.前进和后退按钮动画

当刚打开时只有一个页面,所以前进和后退没效果,需要将这两个按钮变灰;而当只有后退页面没有前进页面时需要将前进按钮变灰。我把这些放到加载网页完成后来执行。

//处理网页完成事件
    func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
        //判断是否可以前进和后退
        if self.webView.canGoForward {
            btnForward.enabled = true
        }
        else {
            btnForward.enabled = false
        }
        
        if self.webView.canGoBack {
            btnBack.enabled = true
        }
        else {
            btnBack.enabled = false
        }
        textField.text = self.webView.title
    
}

15.销毁监听

KVO模式有add一定要有remove

 //KVO一定要销毁!
    override func viewWillDisappear(animated: Bool) {
        webView.removeObserver(self, forKeyPath: "estimatedProgress")
    }

16.调用各方法

override func viewDidLoad() {
        super.viewDidLoad()
        setWebView()
        setDownToolbar()
        setUpBar()
        setProgressView()
        loadUrl("http://www.baidu.com")
        menuInit()
    }

17. 自定义主页和错误页

这个会做网页的朋友可以自己实现,不一定和我的一样。我的只是为了演示一下页面。
创建1个html文件,名为MyHome.html,然后敲入

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Language" content="zh-cn">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <title>迷你浏览器</title>
 
</head>

<body bgcolor="#DCDCDC">
  
<div style="margin-top: 200px">
 <h1 align="center" style="font-size:60px">这是浏览器的主页</h1><br/>
</div>

<div style="margin-top: 200px" align="center">
    <a style="font-size:60px" href="http://www.jianshu.com/users/040395b7230c/latest_articles">我的简书</a>
</div>

</body>
</html>

再创建1个html文件,名为404.html,然后敲入

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Language" content="zh-cn">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <title>出错了!</title>
 
</head>

<body bgcolor="#DCDCDC">
  
<div style="margin-top: 300px">
 <h1 align="center" style="font-size:60px">请输入正确的网址!</h1><br/>
</div>
<div style="margin-top: 100px">
    <h1 align="center" style="font-size:60px">请检查是否加上http://或https://</h1><br/>
</div>

</body>
</html>

把这两个文件拖入项目中即可。

伸伸小手Star一下吧
源码下载

相关文章

网友评论

本文标题:Swift开发迷你浏览器

本文链接:https://www.haomeiwen.com/subject/ykdllttx.html