一个好用的WebView控件窗口组件

作者: 天兵公园 | 来源:发表于2017-10-14 16:46 被阅读0次

在我们公司的一个项目中使用到了QQ微信微博等三方登陆,但是由于网站已经已成了这些登陆方式,为了简化app端的工作量以及最快的方式让app拥有三方登陆的功能,我们决定在app里使用web登陆的方式。

早在之前我写过一篇文章介绍了一些简单的WebView控件的使用,不过WebView确实是很复杂的一个控件,这里说的复杂并不是说它有多难用,而是很多的状态的不确定性,在不同的手机上可能渲染的效果不一样等等,不过如果api level>=19问题就会相对好得多,所以如果webview需要大量用的话,不妨将api level设置大于19,或者使用Crosswalk,不过比较坑的是,Crosswalk已经不再维护了...

不过眼下解决的问题是,app许多网页和本地代码交互的界面,如果保证不用放置太多的包含WebView的Activity才是关键,这里写了个简单的库 WebFrame,也许是重复造的轮子。

WebFrame https://github.com/yahch/WebFrame

用法:

allprojects {
        repositories {
            ...
            maven { url 'https://www.jitpack.io' }
        }
}
dependencies {
            compile 'com.github.yahch:WebFrame:2017.09.27.2'
}

如果有需要在网页上调用的本地代码,需要继承WebFrameScriptInterface 这个抽象类。

WebFrameSettings 是一个单例,用于对webview 的 activity 进行设置,它的成员如下:

private String url;
private HashMap<String, WebFrameScriptInterface> objs;
private boolean noActionBar;

第一个表示需要导航到的url,第二个表示这个页面和本地代码调用的对象类的集合,第三个设置是否需要ActionBar。

在我的项目中,我点击 QQ 登录的图标后,导航至我们网站的 QQ 登录授权链接,对应在 Android 中的操作如下:

Intent intentForQQLogin = new Intent(LoginActivity.this, WebFrameActivity.class);
WebFrameSettings.instance.reset();
WebFrameSettings.instance.setUrl("http://my.域名.com/oauth/qq?client=android");
WebFrameSettings.instance.addObject("app", new WebInterface());
WebFrameSettings.instance.setNoActionBar(true);
startActivity(intentForQQLogin);

可以看到所有交互传入的对象是 WebInterface 的实例,来看看 WebInterface 的内容。

class WebInterface extends WebFrameScriptInterface {
    @JavascriptInterface
    public void oauth(String uid) {
        if (getWebFrameActivity() != null) getWebFrameActivity().finish();
    }
}

因为在我们网站授权登录后的回调时 app.oauth(qqopenid),所以方法签名一定要对应好。
这里有个黑魔法是在调用方能关闭授权窗口的Activity,也就是能通过 getWebFrameActivity() 获取到打开的窗口的 “句柄”,然后进行操作。

WebFrameScriptInterface 的设计如下:

public abstract class WebFrameScriptInterface {
    private WebFrameActivity webFrameActivity;

    public WebFrameScriptInterface() {
    }

    public WebFrameActivity getWebFrameActivity() {
        return this.webFrameActivity;
    }

    public void setWebFrameActivity(WebFrameActivity webFrameActivity) {
        this.webFrameActivity = webFrameActivity;
    }
}

WebFrameScriptInterface 是一个抽象类,其实不写成抽象类也可以,因为也不需要子类重写或实现什么。它唯一作用就是保存着一个 WebFrame 对象实例,供 Java/JS 调用接口层使用。

在 WebFrameScriptInterface 的 onCreate 方法中,会将当前的实例传递给抽象类的实现者。

@SuppressLint("JavascriptInterface")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    ...
    
    HashMap<String, WebFrameScriptInterface> invokeObjects = WebFrameSettings.instance.getObjs();
    if (invokeObjects.size() > 0) {
        for (Map.Entry<String, WebFrameScriptInterface> entry : invokeObjects.entrySet()) {
            WebFrameScriptInterface ws = entry.getValue();
            ws.setWebFrameActivity(WebFrameActivity.this);
            webViewWebFrameModule.addJavascriptInterface(ws, entry.getKey());
        }
    }
    ...
}

到这里这个组件算是介绍完了,我是沿着我的思路是实现的,也可能网络上有更好的第三方库,写了多年的 C# 也可能还是保留有 C# 的某些语法习惯 😂

相关文章

  • 一个好用的WebView控件窗口组件

    在我们公司的一个项目中使用到了QQ微信微博等三方登陆,但是由于网站已经已成了这些登陆方式,为了简化app端的工作量...

  • WebView

    布局中创建 WebView 控件: 使用 WebView 控件: 调用 WebView 的** getSettin...

  • Android的WebView的API详解

    WebView WebView是谷歌提供的一个加载H5的控件,WebView这个控件又包含四大部分:WebSett...

  • Android的WebView的API详解

    WebView WebView是谷歌提供的一个加载H5的控件,WebView这个控件又包含四大部分:WebSett...

  • mui底部选项卡

    Webview模块管理应用窗口界面,实现多窗口的逻辑控制管理操作:webview API文档 创建webview ...

  • 控件总结

    一、WebView控件1.Android 解决WebView重定向问题 二,RecyclerView控件1.Rec...

  • 2019-02-04 3 pyQT5建立窗口控件

    3 建立窗口控件 建立窗口的控件,需要注意以下几点: 1)控件本身也是窗口,它的父窗口是主窗口,这里定义父窗口的原...

  • WebView组件属性方法

    WebView组件进行创建渲染一个原生的WebView,进行加载一个网页。 属性方法 继承可以使用View组件的所...

  • WebView

    一、WebView WebView就是一个内嵌浏览器控件,在iOS中主要有两种WebView:UIWebView和...

  • iOS学习笔记14-网络(三)WebView

    一、WebView WebView就是一个内嵌浏览器控件,在iOS中主要有两种WebView:UIWebView和...

网友评论

    本文标题:一个好用的WebView控件窗口组件

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