The company has a project that needs to have a pie chart that presents a large number of charts and statistics, because of the need to have ios, Android and Web. So in order to unify ios and Android is to make a shell, that is to open the native APP, but in fact, it is a WebView, directly browse fixed url, and then all login, view and other operations are directly on the web page, so that the need to change the chart, etc., can be directly done in the web section. We’ve got updates for both Android and ios. However, this brings a problem, such as browsing the website on the mobile phone, such as some drop-down boxes, clicking buttons, horizontal sliding menus, etc., it is very inconvenient to operate. The experience is poor. However, it was not possible to complete the project from scratch, so we decided to use the web in the middle, and the menus, such as dropdown boxes and horizontal menus, were made native. Then click on the native menu to interact with the Web side to refresh the page.





Ok, now that we see the menu above, what we need is a back button in the upper left corner, two drop-down boxes, and a horizontal scroll menu (there are only five in the picture, but there are actually nine, which can be scrolled horizontally).

The following menu is actually three buttons, or the bottom TAB menu can be set.


This article focuses on the above menu implementation, and how to interact with the web.

First: native menu implementation

Spinner (drop down selection box)

Spinner select box basic use, I will not mention, more general development people will. For example, the Spinner drop-down box function is used

Here I’ll mention two additional situations you might encounter: after writing the click event for each spinner option.

spinner.setOnItemSelectedListener(newAdapterView.OnItemSelectedListener() {
      @Overridepublic void onItemSelected(AdapterView<? > adapterView, View view, int i, long l) {// This method can handle click events
            // I refers to the location of the click, through which I can fetch the corresponding data source
}
      @Overridepublic void onNothingSelected(AdapterView<? > adapterView) { } });Copy the code

And then you’re happy to run through your code and see that onItemSelected is called once as soon as we get into the screen. What the fuck, I haven’t even clicked the option yet. Since Spinner displays the first item by default, the onItemSelected method is executed once the first item is selected.

Solution: before a call setOnItemSelectedListener method, call the spinner. SetSelection (0, false); By default, do not select the first one, OK.

2. The layout of the Spinner dropdown box, that is, after I click Spinner, the style of each item in the screen that you can select is very simple, that is, the layout of the Adapter in Spinner. SetAdapter is set to our own layout. Ok. We happily ran through the code again, and we chose 2015 for that time box, but we found that. The font color of our Spinner may be black, but so is our background. WHF, so we need to change the selected font color to white as well.





We need to set the color value of the selected font, or the size of the font.

Solution: The selected result is actually a TextView. Public void onItemSelected(AdapterView
adapterView, View View, int I, long l) this View is our selected View. So we just need ((TextView) view).settextColor (getResources().getColor(Android.r.color.white)); The same goes for setting the size and so on.

TabLayout (Landscape Selection menu)

The same basic operation should still be able to use. For example, TabLayout of Material Design is used

A good requirement will also be mentioned: Requirement 1: For example, there are only three menus, so we definitely want to display them in one screen and divide them equally:





Requirement 2: For example, if there are 8 menus, we definitely want them to be scrolling, not crowded into one screen:





MODE_FIXED tabLayout. MODE_SCROLLABLE tabLayout. MODE_SCROLLABLE tabLayout. MODE_FIXED tabLayout. MODE_SCROLLABLE

Then we have an idea. We added the menu Tab in TabLayout. So let’s sum up the widths of these tabs. If it is smaller than the width of the screen, set it to TabLayout.mode_fixed. If it is larger than the width of the phone screen, set it to 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); // Notify the parent View of the measurement so that the width and height can be guaranteed
            tabWidth += view.getMeasuredWidth();
        }
        return tabWidth;
    }

    public static int getScreenWidth(a) {
        returnLockWebAppliction.getInstance().getResources().getDisplayMetrics().widthPixels; }}Copy the code
public class LockWebAppliction extends Application {
    private static Context context;

    public static Context getInstance(){
        return context;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        this.context = this; }}Copy the code

So now that we have this tool class, we just need to:

        TabLayout tablayout = (TabLayout) findViewById(R.id.tablayout);


        tablayout.addTab(tablayout.newTab().setText("Assets"));
        tablayout.addTab(tablayout.newTab().setText("Equipment"));
        tablayout.addTab(tablayout.newTab().setText("Spending."));
        tablayout.addTab(tablayout.newTab().setText("Income"));
        tablayout.addTab(tablayout.newTab().setText("Vehicle"));
        tablayout.addTab(tablayout.newTab().setText("Logistics"));
        tablayout.addTab(tablayout.newTab().setText("Inventory"));


        TabLayoutUtil.dynamicSetTabLayoutMode(tablayout);Copy the code

Second: we have written controls that interact with the web page.

The first thing we should know is that Android phones use webView controls to display web pages. We add it directly in 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"
/>Copy the code

Then, in

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

WebSettings webSettings = webView.getSettings();

        //Set up support js webSettings. SetJavaScriptEnabled (true);
        //webView.loadData(""."text/html"."UTF-8");

        //Setting can support zooming webSettings. SetSupportZoom (true);
        //Set a zoom tool webSettings. SetBuiltInZoomControls (true);
        webSettings.setDisplayZoomControls(false);
        webSettings.setUseWideViewPort(false);

        webView.setInitialScale(250);

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

OK. We can see the web page first. The next step is to change the page by clicking on our native button. Let the webpage change is actually the webpage to call the JS method to dynamically change the page, then the problem is known. Our Java on the remote call JS method is not OK yao.

So in the Spinner click above, we select one of the options and then call the method below is equivalent to calling the JS method.

webView.post(new Runnable() {
    @Override
    public void run(a) {
        //loadMap is the name of the method written in js, which should be identical.
        webView.loadUrl("javascript:loadMap("+"Here are the parameters to rotate."+")");
        // If there are no arguments, just write the loadMap() method}});Copy the code

We have successfully called the JS method and changed the data on the page.

In this project, our user login interface is all in the web page, but it requires that the shell of our native App itself should have automatic login function. After logging in once, we do not need to log in again on the web page. So after the user logs in for the first time. JS judged that the customer successfully sent the account number and processed password to our native APP, which is to call back the method written in JAVA. Then we got the account number and processed password and saved it locally, such as Sharepreference, and the customer opened it again next time. We use the native App to check whether there is an account password in SharePreference. If there is, we can directly call the JS login method and pass in the account password. The page in the WebView automatically goes to the home page. Similarly, the user has changed the password in the personal center of the web page. Again, call back to our Java method and send us the new password.

/** * Get the password */
    @JavascriptInterface
    public void getPassword(final String password){
        webView.post(new Runnable() {
            @Override
            public void run(a) { webView.loadUrl(userName); }}); }Copy the code

The @JavascriptInterface above is mandatory. And then call

webView.addJavascriptInterface(this."webtest");Copy the code

The webtest name is arbitrary, and the js call will be the same as the name we wrote here.

Then call from js:

Window.webtest.getpassword (XXXXX) will do the job.

Android WebView summary