前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >项目需求讨论 - HyBrid 模式需求改造

项目需求讨论 - HyBrid 模式需求改造

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

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

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


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

第一:原生处的菜单实现

Spinner(下拉选择框)

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

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

代码语言:javascript
复制
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

代码语言:javascript
复制
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;
    }
}
代码语言:javascript
复制
public class LockWebAppliction extends Application {
    private static Context context;

    public static Context getInstance(){
        return context;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        this.context = this;

    }
}

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

代码语言:javascript
复制
        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中添加

代码语言:javascript
复制
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
/>

然后在

代码语言:javascript
复制
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方法。

代码语言:javascript
复制
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方法,把新的密码发给我们。

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

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

代码语言:javascript
复制
webView.addJavascriptInterface(this,"webtest");

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-02-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一:原生处的菜单实现
    • Spinner(下拉选择框)
      • TabLayout (横向选择菜单)
      • 第二:我们写好的控件与网页进行交互。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档