美文网首页移动互联网Android技术知识Android知识
当下主流 APP , Hybrid app 中需要熟练掌握的交互

当下主流 APP , Hybrid app 中需要熟练掌握的交互

作者: smartbeng | 来源:发表于2017-05-20 23:26 被阅读913次

    如果感觉略有用处,点赞支持下作者。上一篇将关于 WebView 的设置仔细的捋了一遍,我们通过 WebViewController 这个类完成了所有 WebView 的设置,并且在布局的时候,只需在布局文件中引入这个类的完整包名,前提是这个类要继承于 WebView,就可以完成所有 WebView 的设置,具体可参考上一篇 当下主流 APP,Hybrid app 中需要熟练掌握的交互知识(一) 其实有人就说到了,现在有现成的框架可,那我的出发点是从自己动手开始,再去接触框架,这个系列我们一步步来!

    那么本篇将就以下几点展开:

    • 页面布局相同情况下Activity 的 共用问题。

    • 在原生与网页混合的开发状态下,如何确定页面跳转以及参数传递。

    • 根据服务端发送的 Js 接口名去做具体实现

    Activity 共用

    这是当下很多 WebApp 都在使用的一个套路,除了避免了创建多个 Activity 后影响性能之外,还可以保持项目「友好」的结构!这样的处理大多适应于这样的场景:

    • 页面布局上方只有一个 ToolBar 或者 ActionBar 等等的标题栏

    • 下方则是一个 WebView 用于呈现网页内容

    • 如此则可以将共同的属性提取出来,WebView 则不用管,都是一致的东西。ToolBar 上无论是标题还是按钮的设置,当点击了某处后我们会进入我们在本地实现的网页接口,具体的原理请看下面的详细解释!

    一 、建立共用的 Activity:

    我们将之命名为 NewWebViewActivity

    //获取到消息处理类传过来的 url 网址
    String url = getIntent().getStringExtra("url");
    //获取到消息处理类传过来的动画操作
    int anim = getIntent().getIntExtra("animation", 0);
    if (url == null) {
       finish();
    }else if (url.equals(Constants.urlHostBase + Constants.urlLogIn)){
       baseWebView.loadUrl(url);
       topToolbar.setVisibility(View.GONE);
    } else {
       baseWebView.loadUrl(url);
       //用动画文件判断新开页面
       if (anim == R.anim.slide_right_out) {  //当所有的新开页面 是从右往左打开时(表示新开页面)
            //添加返回按钮
            backImageView.setImageResource(R.drawable.returns);
            //变为显示状态
            backImageView.setVisibility(View.VISIBLE);
            //返回键点击事件
            backImageView.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   finish(); //关闭页面
                   //设置页面退出动画为从左往右退出
                   overridePendingTransition(R.anim.none, R.anim.slide_right_out);
               }
             });
        }
    }
    

    可以看到,并没有多少逻辑。我们这样就可以所有新开的页面添加一个返回键了,前提是有一个消息处理的类来完成打开页面的 url 参数设置,以及动画参数设置,其实实现起来也是很简单!往下看

    二 、建立共用的 Activity 的布局:

    我们紧接着需要将我们这个 Activity 布局:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_new_web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:theme="@android:style/Animation.Toast"
        android:background="@android:color/white"
        tools:context="com.lansum.eip.activity.NewWebViewActivity">
        <!-- 标题栏 -->
        <android.support.v7.widget.Toolbar
            android:id="@+id/web_top_toolbar"
            android:layout_width="match_parent"
            android:layout_height="70dp"
            android:layout_alignParentTop="true"
            android:background="#00a6ff"/>
        <!-- WebView -->
        <com.lansum.eip.webview.WebViewController
            android:id="@+id/base_web_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/web_top_toolbar" />
        <!-- 标题栏右上角图片点击按钮 默认隐藏状态 下同 -->
        <ImageView
            android:id="@+id/right_Button"
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:layout_alignRight="@id/web_top_toolbar"
            android:layout_alignTop="@id/web_top_toolbar"
            android:layout_marginRight="16dp"
            android:layout_marginTop="30dp"
            android:visibility="gone" />
        <!-- 标题栏正中显示的标题 根据点击区域切换标题内容 -->
        <TextView
            android:id="@+id/toolbar_text_top"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@id/web_top_toolbar"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="32dp"
            android:textColor="@android:color/white"
            android:textSize="18sp" />
        <!-- 标题栏左上角用于关闭打来页面的图片按钮 -->
        <ImageView
            android:id="@+id/back_web"
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:layout_alignLeft="@id/web_top_toolbar"
            android:layout_alignTop="@id/web_top_toolbar"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="30dp"
            android:visibility="gone" />
        <!-- 右上角文字点击按钮 -->
        <TextView
            android:id="@+id/right_Button_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignRight="@id/web_top_toolbar"
            android:layout_alignTop="@id/web_top_toolbar"
            android:layout_marginRight="16dp"
            android:layout_marginTop="32dp"
            android:textColor="@android:color/white"
            android:textSize="18sp"
            android:visibility="gone" />
    </RelativeLayout>
    

    布局文件很简单,我们将标题栏上正中标题,左上角关闭页面的图片点击按钮,右上角的文字提交按钮以及图片点击按钮都放在了布局中,那接下来就是如何去控制他们的显示时机,以及按下后的反馈了!

    建立好了这个用于展示我们所有网页的共用 Activity 后,就是我们本篇的核心类了,敲黑板!!

    核心类 HtmlMessageForLocal

    在开始之前我们先将思路捋清楚

    • 处理所有网页的接口实现,以及跳转操作和添加标题栏上的按钮添加。

    • 此类用于接收我们点击或打开 WebView 服务端暴漏给我们的接口,我们负责具体实现!

    • 将我们实现的方法上加上 @JavascriptInterface 注解

    • 此注解表明所有服务端 Js 接口,都会进入我们自定义的这个方法里找同名方法,直接执行里面的逻辑!

    好了,通过以上说明相信明眼的你可以发现,这是一个网页与我们本地的交互的核心类,所有的交互逻辑实现都需要在这里进行!

    接下来我们分层进行,一层层,一个个方法的具体实现步骤,来剖析整个过程。

    一 、判断接口名执行具体的方法:

    @JavascriptInterface
    public void callHandler(final String methodName, final String data, final String callbackName) {
        Log.e(TAG, "Method:" + methodName);
        if (methodName.equals("openAttendanceFromJS")) {
           openAttendanceFromJS(data);      // 打开新窗口
        }
    }
    

    这里只是起到了判断作用,特定的方法执行特定的操作,就比如上面这个方法,只负责用户点击了 WebView 去打开新的 WebView 的所有操作。

    如何判断

    /**
     * Js 与 Native(android 原生交互)
     * Native 调用 JS 方法
     * @param methodName Js 方法名
     * @param data 需要用到的数据 比如图片资源需要传递的数据 以下代码的实体类为 RightInfo
     我们需要声明一个实体类 用到什么数据资源就传给这个参数 
     * @param callbackName 回调的方法名 这里具体用不到
     */
    @JavascriptInterface
    public void callHandler(final String methodName, final String data, final String callbackName) {
        Log.e(TAG, "Method:" + methodName);
        if (methodName.equals("openAttendanceFromJS")) {
           openAttendanceFromJS(data);      // 打开新窗口
        } else if (methodName.equals("addRightBarButtonItemFromJS")) {
           addRightBarButtonItemFromJS(data);// 添加右上角按钮
        }
    
    /**
     * 打开新窗口
     * @param url
     */
    protected void openAttendanceFromJS(String url) {
        Log.i("js", url);
        // TODO Auto-generated method stub
        Intent intent = new Intent(ActivityCollector.getTopActivity(), NewWebViewActivity.class);
        intent.putExtra("url", url);
        intent.putExtra("animation", R.anim.slide_right_out);
        intent.putExtra("animation", R.anim.slide_right_in);
        ActivityCollector.getTopActivity().startActivity(intent);
    }
    
    /**
     * 设置右上角图片按钮
     * @param data
     */
    protected void addRightBarButtonItemFromJS(String data) {
        topRightImage.setBackgroundResource(imageId);  //找到图片按钮资源
        topRightImage.setVisibility(View.VISIBLE);     //设置为可见状态
        topRightImage.setOnClickListener(new View.OnClickListener() {  //此按钮点击事件
            @Override
            public void onClick(View v) {
                Activity activity = ActivityCollector.getTopActivity();//获取到栈顶 Activity
                activity.runOnUiThread(new Runnable() {  //强制运行到主线程
                    @Override
                    public void run() {
                        //找到共用打的 WebView                       
                        ActivityCollector.getTopActivity().findViewById(R.id.base_web_view);
                        activity.overridePendingTransition(R.anim.push_bottom_out, R.anim.push_bottom_in);
                        //找到对应 web url网址
                        baseWebView.loadUrl("javascript:" + rightInfo.funcName);
                    }
                });
            }
        });
    }
    

    在这里用两个方法举例,重要的步骤在这里都呈现了出来,根据我们服务端和 Android 端的需求做相应逻辑和方法的叠加就可以了!

    总结

    此次在这里将 Js 与 Native 的交互做了一个简单总结记录,整理了通用流程和思想,下个系列将使用当下比较流行的 Hybrid APP 框架来实现一个总体的处理流程。

    相关文章

      网友评论

      本文标题:当下主流 APP , Hybrid app 中需要熟练掌握的交互

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