公司有个项目,是需要有呈现大量的图表及统计的饼状图,因为考虑到要有ios,Android及web端。所以为了统一就ios和Android都是做一个外壳,也就是打开原生的APP,但是其实里面就是个webview,直接浏览固定网址,然后所有的登录,查看等操作就是直接在网页上面操作,这样需求改了图表等,就可以直接web前段做完,我们Android和ios就都更新好了。但是这样就带来一个问题,比如在手机上浏览这个网页,像一些下拉框,点击按钮,横向滑动菜单等,操作起来很不方便。体验效果很差。但是不可能说全部把这个项目推到重来,于是我们决定中间的部分还是用网页的形式,而那些菜单,比如下拉框,横向菜单等都用原生来做。然后当点击原生的菜单,来与web端进行交互,来使网页刷新。

好,我们现在看到了,上面的菜单我们需要的东西是左上角一个返回按钮,二个下拉框,一个横向的滚动菜单(图片里面只显示了五个,其实有9个,可以横向滚动)。

下面菜单其实就是三个按钮,或者设置成底部tab菜单也可以。


本文重点就说讲解上面的菜单实现,及如果与网页来进行交互。

第一:原生处的菜单实现

Spinner(下拉选择框)

Spinner选择框的基本使用方式,我这边不会多提,比较一般开发的人都会。
比如:Spinner下拉框功能使用

这里我提二个大家可能会额外遇到的情况:
在写完spinner的每个选项的点击事件后。

spinner.setOnItemSelectedListener(newAdapterView.OnItemSelectedListener() {      @Override      public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {            //这个方法里可以对点击事件进行处理            //i指的是点击的位置,通过i可以取到相应的数据源}      @Override      public void onNothingSelected(AdapterView<?> adapterView) {}});

然后你就开心的跑起了你的代码,发现我们刚进去界面,onItemSelected就被调用了一次。 what the fuck,我都还没有进行点击选项,怎么就被调用了。因为Spinner默认显示第一项内容,等于就是选中了第一项,也就会执行一遍onItemSelected方法。

解决方法:在调用setOnItemSelectedListener方法前,调用spinner.setSelection(0, false);默认不选中第一个,就OK了。

2.Spinner下拉框中的布局,也就是我点了Spinner后,出现的让你选择的界面的每个item的样式很简单,也就是Spinner.setAdapter中的adapter的布局设置为我们自己的布局就可以了。好。我们又开心的跑动起了代码,我们那个时间选择框选了2015年,但是我们发现。我们的 Spinner选中后的字体颜色可能是黑色,但是我们的背景也是黑色。WHF,所以我们要把选中的字体颜色也要换成白色。

我们就要设置我们选好后的字体的颜色值,或者是字体大小怎么办。

解决方法:这个选好后显示结果的其实是个TextView。而且刚上面设置spinner点击事件的监听的方法
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l)中的这个view就是我们选中的view.所以我们只需要((TextView) view).setTextColor(getResources().getColor(android.R.color.white));同理设置大小等就都能处理。

TabLayout (横向选择菜单)

同样基本的操作使用大家应该还是都会。比如说Material Design 之 TabLayout 使用

同样也会提到一个比较好的需求:
需求1:比如菜单只有3个,那我们肯定是希望在一个屏幕中就能显示,并且是平分的方式,呈现:

需求2:比如恰好菜单有8个之多,我们肯定就希望是滚动的,不是挤在一个屏幕:

大家都知道,让TabLayout实现需求1和需求2,我们只要设置TabLayout的Mode分比为:TabLayout.MODE_FIXEDTabLayout.MODE_SCROLLABLE

那我们就想到了。我们在TabLayout把菜单Tab都加入后。我们把这些Tab的宽度的总和算出来。再和整个屏幕的宽度进行比较,如果比屏幕宽度小,就设为TabLayout.MODE_FIXED,如果比手机屏幕宽度大就设为TabLayout.MODE_SCROLLABLE

public class TabLayoutUtil {    public static void dynamicSetTabLayoutMode(TabLayout tabLayout) {        int tabWidth = calculateTabWidth(tabLayout);        int screenWidth = getScreenWidth();        if (tabWidth <= screenWidth) {            tabLayout.setTabMode(TabLayout.MODE_FIXED);        } else {            tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);        }    }    private static int calculateTabWidth(TabLayout tabLayout) {        int tabWidth = 0;        for (int i = 0; i < tabLayout.getChildCount(); i++) {            final View view = tabLayout.getChildAt(i);            view.measure(0,0); //通知父 View 测量,以便于能够保证获取到宽高            tabWidth += view.getMeasuredWidth();        }        return tabWidth;    }    public static int getScreenWidth() {        return LockWebAppliction.getInstance().getResources().getDisplayMetrics().widthPixels;    }}
public class LockWebAppliction extends Application {    private static Context context;    public static Context getInstance(){        return context;    }    @Override    public void onCreate() {        super.onCreate();        this.context = this;            }}

所以我们接下去有了这个工具类,只需要:

        TabLayout tablayout = (TabLayout) findViewById(R.id.tablayout);        tablayout.addTab(tablayout.newTab().setText("资产"));        tablayout.addTab(tablayout.newTab().setText("设备"));        tablayout.addTab(tablayout.newTab().setText("支出"));        tablayout.addTab(tablayout.newTab().setText("收入"));        tablayout.addTab(tablayout.newTab().setText("车辆"));        tablayout.addTab(tablayout.newTab().setText("物流"));        tablayout.addTab(tablayout.newTab().setText("库存"));        TabLayoutUtil.dynamicSetTabLayoutMode(tablayout);

第二:我们写好的控件与网页进行交互。

首先我们应该知道安卓手机显示网页用的是webview控件。
我们直接在layout中添加

然后在

WebView webView = (ProgressWebView) findViewById(R.id.webview);WebSettings webSettings = webView.getSettings();        //设置支持js        webSettings.setJavaScriptEnabled(true);        //webView.loadData("","text/html","UTF-8");        // 设置可以支持缩放        webSettings.setSupportZoom(true);        // 设置出现缩放工具        webSettings.setBuiltInZoomControls(true);        webSettings.setDisplayZoomControls(false);        webSettings.setUseWideViewPort(false);        webView.setInitialScale(250);        webSettings.setSavePassword(false);        webView.loadUrl("http://XXXXXXXXXX/index.html");

OK .我们已经先可以看到网页了。接下去就是我们点击我们原生的按钮的时候,可以去让这个网页发生变化。让网页发生变化其实就是网页端调用js方法来让页面动态发生变化,那问题就知道了。我们的java就远程调用JS的方法不就OK了么。

所以上面的Spinner点击事件中,我们选了某个选项,然后调用下面的方法就等于调用了js方法。

webView.post(new Runnable() {    @Override    public void run() {        //loadMap就是js处写的方法的名字,要一模一样。        webView.loadUrl("javascript:loadMap("+"这里是要转的参数"+")");        //如果没有参数就直接写方法loadMap()即可    }});

这样我们就成功调用了JS方法,重而更改了页面的数据。

有些需求是要JS回调我们这边JAVA的方法,这个项目中,我们用户登录界面等都是在网页处的,但是要求我们这个原生App的外壳本身要有自动登录功能,登录一次后就不需要在网页上再次登录。所以在用户网页里面第一次登录后。那边JS 判断客户成功把账号和处理过的密码发给我们这个原生APP,也就是回调我们这边JAVA写好的方法,然后我们拿到了账号和处理过的密码,保存到本地,比如Sharepreference中,下次客户再打开,我们用原生App去SharePreference中查看是否有账号密码存在,如果存在,就直接调用js的登录方法,把账号密码传入即可。webview里面的页面就自动转到了首页中了。同理用户在网页里面的个人中心修改了密码。也是要再次回调我们的java方法,把新的密码发给我们。

/**     * 获取密码      */    @JavascriptInterface    public void getPassword(final String password){        webView.post(new Runnable() {            @Override            public void run() {                webView.loadUrl(userName);            }        });    }

上面的 @JavascriptInterface是一定要写的。
然后再调用

webView.addJavascriptInterface(this,"webtest");

这里的webtest是随便取名字,等会js调用的时候跟我们这里写的名字一样即可。

然后js处调用:

window.webtest.getPassword(XXXXX)就可以了。

附上一些别人的webview的介绍:Android Webview总结

更多相关文章

  1. Android(安卓)Hybird App开发
  2. Back Stack学习之Android退出方法小结
  3. 关于Unity与Android通信与交互
  4. Zygote进程的创建过程(Android(安卓)8.1)
  5. Unity 与 Android(安卓)互调用
  6. app与Android以及IOS的交互
  7. ReactNative学习笔记之调用原生模块(进阶)之Callback、Promise使用
  8. 让JNI告诉你 你的应用为什么被卸载
  9. 第四章 常见 Android(安卓)文件格式(一)(库文件、APK)

随机推荐

  1. Tasker, Android系统增强神器
  2. Android(安卓)基于Socket.io即时通讯IM实
  3. Android静态安全检测 -> 明文数字证书风
  4. Genymotion安装
  5. 〖Android〗代理与正常网络分开同步Cyang
  6. 【Android(安卓)Developers Training】 8
  7. Mac下Qt for android 环境配置
  8. Android(安卓)创建与解析XML(四)—— Pull
  9. android 下修改 hosts文件 及 out of mem
  10. systemtap在android、pandaboard上的移植