当下主流 APP , Hybrid app 中需要熟练掌握的交互知识(二)

如果感觉略有用处,点赞支持下作者。上一篇将关于 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 框架来实现一个总体的处理流程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容