項目需求討論-HyBrid模式需求改造

公司有個項目,是需要有呈現(xiàn)大量的圖表及統(tǒng)計的餅狀圖,因為考慮到要有ios,Android及web端。所以為了統(tǒng)一就ios和Android都是做一個外殼,也就是打開原生的APP,但是其實里面就是個webview,直接瀏覽固定網(wǎng)址,然后所有的登錄,查看等操作就是直接在網(wǎng)頁上面操作,這樣需求改了圖表等,就可以直接web前段做完,我們Android和ios就都更新好了。但是這樣就帶來一個問題,比如在手機上瀏覽這個網(wǎng)頁,像一些下拉框,點擊按鈕,橫向滑動菜單等,操作起來很不方便。體驗效果很差。但是不可能說全部把這個項目推到重來,于是我們決定中間的部分還是用網(wǎng)頁的形式,而那些菜單,比如下拉框,橫向菜單等都用原生來做。然后當點擊原生的菜單,來與web端進行交互,來使網(wǎng)頁刷新。

好,我們現(xiàn)在看到了,上面的菜單我們需要的東西是左上角一個返回按鈕,二個下拉框,一個橫向的滾動菜單(圖片里面只顯示了五個,其實有9個,可以橫向滾動)。

下面菜單其實就是三個按鈕,或者設(shè)置成底部tab菜單也可以。


本文重點就說講解上面的菜單實現(xiàn),及如果與網(wǎng)頁來進行交互。

第一:原生處的菜單實現(xiàn)

Spinner(下拉選擇框)

Spinner選擇框的基本使用方式,我這邊不會多提,比較一般開發(fā)的人都會。
比如:Spinner下拉框功能使用

這里我提二個大家可能會額外遇到的情況:
在寫完spinner的每個選項的點擊事件后。

spinner.setOnItemSelectedListener(newAdapterView.OnItemSelectedListener() {
      @Override
      public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            //這個方法里可以對點擊事件進行處理
            //i指的是點擊的位置,通過i可以取到相應(yīng)的數(shù)據(jù)源
}
      @Override
      public void onNothingSelected(AdapterView<?> adapterView) {
}
});

然后你就開心的跑起了你的代碼,發(fā)現(xiàn)我們剛進去界面,onItemSelected就被調(diào)用了一次。 what the fuck,我都還沒有進行點擊選項,怎么就被調(diào)用了。因為Spinner默認顯示第一項內(nèi)容,等于就是選中了第一項,也就會執(zhí)行一遍onItemSelected方法。

解決方法:在調(diào)用setOnItemSelectedListener方法前,調(diào)用spinner.setSelection(0, false);默認不選中第一個,就OK了。

2.Spinner下拉框中的布局,也就是我點了Spinner后,出現(xiàn)的讓你選擇的界面的每個item的樣式很簡單,也就是Spinner.setAdapter中的adapter的布局設(shè)置為我們自己的布局就可以了。好。我們又開心的跑動起了代碼,我們那個時間選擇框選了2015年,但是我們發(fā)現(xiàn)。我們的 Spinner選中后的字體顏色可能是黑色,但是我們的背景也是黑色。WHF,所以我們要把選中的字體顏色也要換成白色。

我們就要設(shè)置我們選好后的字體的顏色值,或者是字體大小怎么辦。

解決方法:這個選好后顯示結(jié)果的其實是個TextView。而且剛上面設(shè)置spinner點擊事件的監(jiān)聽的方法
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l)中的這個view就是我們選中的view.所以我們只需要((TextView) view).setTextColor(getResources().getColor(android.R.color.white));同理設(shè)置大小等就都能處理。

TabLayout (橫向選擇菜單)

同樣基本的操作使用大家應(yīng)該還是都會。比如說Material Design 之 TabLayout 使用

同樣也會提到一個比較好的需求:
需求1:比如菜單只有3個,那我們肯定是希望在一個屏幕中就能顯示,并且是平分的方式,呈現(xiàn):

需求2:比如恰好菜單有8個之多,我們肯定就希望是滾動的,不是擠在一個屏幕:

大家都知道,讓TabLayout實現(xiàn)需求1和需求2,我們只要設(shè)置TabLayout的Mode分比為:TabLayout.MODE_FIXEDTabLayout.MODE_SCROLLABLE

那我們就想到了。我們在TabLayout把菜單Tab都加入后。我們把這些Tab的寬度的總和算出來。再和整個屏幕的寬度進行比較,如果比屏幕寬度小,就設(shè)為TabLayout.MODE_FIXED,如果比手機屏幕寬度大就設(shè)為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("資產(chǎn)"));
        tablayout.addTab(tablayout.newTab().setText("設(shè)備"));
        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);

第二:我們寫好的控件與網(wǎng)頁進行交互。

首先我們應(yīng)該知道安卓手機顯示網(wǎng)頁用的是webview控件。
我們直接在layout中添加

<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
/>

然后在

WebView webView = (ProgressWebView) findViewById(R.id.webview);

WebSettings webSettings = webView.getSettings();

        //設(shè)置支持js
        webSettings.setJavaScriptEnabled(true);
        //webView.loadData("","text/html","UTF-8");

        // 設(shè)置可以支持縮放
        webSettings.setSupportZoom(true);
        // 設(shè)置出現(xiàn)縮放工具
        webSettings.setBuiltInZoomControls(true);
        webSettings.setDisplayZoomControls(false);
        webSettings.setUseWideViewPort(false);

        webView.setInitialScale(250);

        webSettings.setSavePassword(false);
        webView.loadUrl("http://XXXXXXXXXX/index.html");

OK .我們已經(jīng)先可以看到網(wǎng)頁了。接下去就是我們點擊我們原生的按鈕的時候,可以去讓這個網(wǎng)頁發(fā)生變化。讓網(wǎng)頁發(fā)生變化其實就是網(wǎng)頁端調(diào)用js方法來讓頁面動態(tài)發(fā)生變化,那問題就知道了。我們的java就遠程調(diào)用JS的方法不就OK了么。

所以上面的Spinner點擊事件中,我們選了某個選項,然后調(diào)用下面的方法就等于調(diào)用了js方法。

webView.post(new Runnable() {
    @Override
    public void run() {
        //loadMap就是js處寫的方法的名字,要一模一樣。
        webView.loadUrl("javascript:loadMap("+"這里是要轉(zhuǎn)的參數(shù)"+")");
        //如果沒有參數(shù)就直接寫方法loadMap()即可
    }
});

這樣我們就成功調(diào)用了JS方法,重而更改了頁面的數(shù)據(jù)。

有些需求是要JS回調(diào)我們這邊JAVA的方法,這個項目中,我們用戶登錄界面等都是在網(wǎng)頁處的,但是要求我們這個原生App的外殼本身要有自動登錄功能,登錄一次后就不需要在網(wǎng)頁上再次登錄。所以在用戶網(wǎng)頁里面第一次登錄后。那邊JS 判斷客戶成功把賬號和處理過的密碼發(fā)給我們這個原生APP,也就是回調(diào)我們這邊JAVA寫好的方法,然后我們拿到了賬號和處理過的密碼,保存到本地,比如Sharepreference中,下次客戶再打開,我們用原生App去SharePreference中查看是否有賬號密碼存在,如果存在,就直接調(diào)用js的登錄方法,把賬號密碼傳入即可。webview里面的頁面就自動轉(zhuǎn)到了首頁中了。同理用戶在網(wǎng)頁里面的個人中心修改了密碼。也是要再次回調(diào)我們的java方法,把新的密碼發(fā)給我們。

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

上面的 @JavascriptInterface是一定要寫的。
然后再調(diào)用

webView.addJavascriptInterface(this,"webtest");

這里的webtest是隨便取名字,等會js調(diào)用的時候跟我們這里寫的名字一樣即可。

然后js處調(diào)用:

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

附上一些別人的webview的介紹:Android Webview總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容