com.esri.android.ecologicalmarineunitexplorer.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.esri.android.ecologicalmarineunitexplorer.MainActivity.java

Source

/* Copyright 2017 Esri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * For additional information, contact:
 * Environmental Systems Research Institute, Inc.
 * Attn: Contracts Dept
 * 380 New York Street
 * Redlands, California, USA 92373
 *
 * email: contracts@esri.com
 *
 */

package com.esri.android.ecologicalmarineunitexplorer;

import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.Context;
import android.content.DialogInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import com.esri.android.ecologicalmarineunitexplorer.bottomsheet.BottomSheetFragment;
import com.esri.android.ecologicalmarineunitexplorer.bottomsheet.BottomSheetPresenter;
import com.esri.android.ecologicalmarineunitexplorer.chartsummary.SummaryChartFragment;
import com.esri.android.ecologicalmarineunitexplorer.chartsummary.SummaryChartPresenter;
import com.esri.android.ecologicalmarineunitexplorer.data.DataManager;
import com.esri.android.ecologicalmarineunitexplorer.data.WaterColumn;
import com.esri.android.ecologicalmarineunitexplorer.map.MapFragment;
import com.esri.android.ecologicalmarineunitexplorer.map.MapPresenter;
import com.esri.android.ecologicalmarineunitexplorer.util.ActivityUtils;
import com.esri.android.ecologicalmarineunitexplorer.waterprofile.WaterProfileFragment;
import com.esri.android.ecologicalmarineunitexplorer.waterprofile.WaterProfilePresenter;
import com.esri.arcgisruntime.geometry.Point;

/**
 * The single activity in the application that orchestrates fragments,
 * adjusts toolbar behavior, and checks for internet connectivity.
 */
public class MainActivity extends AppCompatActivity
        implements BottomSheetFragment.OnDetailClickedListener, MapFragment.NoEmuFound {

    private BottomSheetPresenter mBottomSheetPresenter = null;

    private DataManager mDataManager = null;
    private MapPresenter mMapPresenter = null;
    private BottomSheetBehavior mBottomSheetBehavior = null;
    private WaterColumn mWaterColumn = null;
    private boolean mInMapState = false;
    private FloatingActionButton mFab = null;
    private SummaryChartFragment mSummaryChartFragment = null;
    private SummaryChartPresenter mSummaryChartPresenter = null;

    public MainActivity() {
    }

    /**
     * Set up the FAB and ensure internect connectivity exists before
     * getting map ready.
     * @param savedInstanceState Bundle
     */
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        /*
         * If you have a basic license key, uncomment line 102.
         * See directions in the README about how to Configure a Basic License
         */

        //   ArcGISRuntimeEnvironment.setLicense(BuildConfig.LICENSE_KEY);

        // Initially hide the FAB
        mFab = (FloatingActionButton) findViewById(R.id.fab);
        if (mFab != null) {
            mFab.setVisibility(View.INVISIBLE);
            mFab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View v) {
                    if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
                        mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                    } else if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_HIDDEN) {
                        mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                    }

                }
            });
        }

        // Check for internet connectivity
        if (!checkForInternetConnectivity()) {
            final ProgressDialog progressDialog = new ProgressDialog(this);
            progressDialog.setMessage(getString(R.string.internet_connectivity));
            progressDialog.setTitle(getString(R.string.wireless_problem));
            progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "CANCEL",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(final DialogInterface dialog, final int which) {
                            progressDialog.dismiss();
                            finish();
                        }
                    });
            progressDialog.show();

        } else {
            // Get data access setup
            mDataManager = DataManager.getDataManagerInstance(getApplicationContext());

            // Set up fragments
            setUpMagFragment();

            setUpBottomSheetFragment();
        }
    }

    /**
     * Attach display logic to bottom sheet behavior.
     */
    private void setUpBottomSheetFragment() {
        final FragmentManager fm = getSupportFragmentManager();
        BottomSheetFragment mBottomSheetFragment = (BottomSheetFragment) fm
                .findFragmentById(R.id.bottom_sheet_view);

        if (mBottomSheetFragment == null) {
            mBottomSheetFragment = BottomSheetFragment.newInstance();
            ActivityUtils.addFragmentToActivity(fm, mBottomSheetFragment, R.id.bottom_sheet_view,
                    getString(R.string.fragment_summary));
            mBottomSheetPresenter = new BottomSheetPresenter(mBottomSheetFragment);
        }

        mBottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet_view));
        if (mBottomSheetBehavior != null) {
            mBottomSheetBehavior.setHideable(true);
            mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);

            mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
                @Override
                public void onStateChanged(@NonNull final View bottomSheet, final int newState) {
                    invalidateOptionsMenu();

                    if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
                        showBottomSheetContent();
                        mFab.setVisibility(View.VISIBLE);
                        final LinearLayout layout = (LinearLayout) findViewById(R.id.horizontalLinearLayout);
                        final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                        layoutParams.setMargins(0, 0, 0, 0);
                        layout.setLayoutParams(layoutParams);
                        layout.requestLayout();

                    }
                    if (newState == BottomSheetBehavior.STATE_EXPANDED) {

                        final LinearLayout layout = (LinearLayout) findViewById(R.id.horizontalLinearLayout);
                        final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                        final int toolbarSize = findViewById(R.id.toolbar).getHeight();
                        layoutParams.setMargins(0, toolbarSize, 0, 0);
                        layout.setLayoutParams(layoutParams);
                        layout.requestLayout();
                    }
                    if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                        final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.chartContainer);
                        if (fragment == null) {
                            mFab.setVisibility(View.VISIBLE);
                        } else {
                            mFab.setVisibility(View.INVISIBLE);
                        }
                    }
                }

                @Override
                public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {

                    final float scaleFactor = 1 - slideOffset;
                    if (mFab != null) {
                        if (scaleFactor <= 1) {
                            mFab.setVisibility(View.VISIBLE);
                            mFab.animate().scaleX(1 - slideOffset).scaleY(1 - slideOffset).setDuration(0).start();
                        }
                        if (slideOffset == 1.00f) {
                            mFab.setVisibility(View.INVISIBLE);
                        }
                    }
                }
            });
        }
    }

    /**
     *
     * @param menu Menu
     * @return boolean
     */
    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.menu, menu);
        // Retrieve the SearchView and plug it into SearchManager
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
        searchView.setQueryHint(getString(R.string.query_hint));
        final SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(final String query) {
                mMapPresenter.geocodeAddress(query);
                searchView.clearFocus();
                return true;
            }

            @Override
            public boolean onQueryTextChange(final String newText) {
                return false;
            }
        });
        return true;
    }

    /**
     *
     * @param menu Menu
     * @return boolean
     */
    @Override
    public boolean onPrepareOptionsMenu(final Menu menu) {
        final MenuItem profile = menu.findItem(R.id.action_profile);
        final MenuItem search = menu.findItem(R.id.action_search);
        final int state = mBottomSheetBehavior.getState();
        if ((state == BottomSheetBehavior.STATE_COLLAPSED) || (state == BottomSheetBehavior.STATE_EXPANDED)) {
            profile.setVisible(true);
            search.setVisible(false);
        } else if (mInMapState) {
            profile.setVisible(false);
            search.setVisible(true);
        } else {
            profile.setVisible(false);
            search.setVisible(false);
        }
        return super.onPrepareOptionsMenu(menu);
    }

    /**
     * Show the view with the water column profiles
     * @param point - Point representing clicked geo location
     */
    private void showWaterColumnProfile(final Point point) {
        // Remove water column, summary, text and button
        mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
        // hideMapView();

        setUpWaterProfileToolbar();

        final FrameLayout layout = (FrameLayout) findViewById(R.id.chartContainer);
        if (layout != null) {
            layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT));
            layout.requestLayout();
        }

        final WaterProfileFragment waterProfileFragment = WaterProfileFragment.newInstance();
        new WaterProfilePresenter(point, waterProfileFragment, mDataManager);

        // Add the chart view to the column container
        final FragmentManager fm = getSupportFragmentManager();
        final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        final Fragment f = fm.findFragmentById(R.id.chartContainer);
        if (f == null) {
            transaction.addToBackStack(getString(R.string.fragment_detail_chart));
        }
        transaction.replace(R.id.chartContainer, waterProfileFragment);
        transaction.commit();

        // Hide the FAB
        mFab.setVisibility(View.INVISIBLE);

        mInMapState = false;
    }

    /**
     * Configure the map fragment
     */
    private void setUpMagFragment() {
        // Set up the toolbar for the map fragment
        setUpMapToolbar();

        final FragmentManager fm = getSupportFragmentManager();

        MapFragment mapFragment = (MapFragment) fm.findFragmentById(R.id.map_container);

        if (mapFragment == null) {
            mapFragment = MapFragment.newInstance();
            mMapPresenter = new MapPresenter(mapFragment, mDataManager);
            ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), mapFragment, R.id.map_container,
                    getString(R.string.fragment_map));
        }
    }

    /**
     * Override the application label used for the toolbar title
     */
    private void setUpMapToolbar() {
        final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
            final ActionBar actionBar = (this).getSupportActionBar();
            if (actionBar != null) {
                actionBar.setTitle(R.string.explore_ocean);
            }
            toolbar.setNavigationIcon(null);
        }
        mInMapState = true;
    }

    /**
     * Set up toolbar for chart detail
     * @param EMUid - integer representing the name of the EMU
     */
    private void setUpChartSummaryToolbar(final int EMUid) {
        final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
            final ActionBar actionBar = (this).getSupportActionBar();
            if (actionBar != null) {
                actionBar.setTitle(getString(R.string.detail_emu) + EMUid);
            }

            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View v) {
                    returnToSummary();
                }
            });
        }
    }

    /**
     * Logic for returning from chart detail to bottom sheet
     */
    private void returnToSummary() {
        // Remove the chart fragment
        removeChartContainer();

        // Shrink parent container
        shrinkChartContainer();

        // Show the FAB
        mFab.setVisibility(View.VISIBLE);

        // Restore the bottom sheet
        mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);

        // Restore the bottom sheet toolbar
        setUpBottomSheetToolbar();
    }

    /**
     * Remove the water column profile fragment
     */
    private void removeChartContainer() {
        final FragmentManager fm = getSupportFragmentManager();
        final Fragment fragment = fm.findFragmentById(R.id.chartContainer);
        if (fragment != null) {
            final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.remove(fragment);
            transaction.commit();
            fm.popBackStack();
        }
    }

    /**
     * Set the text for the summary toolbar and listen
     * for navigation requests
     */
    private void setUpBottomSheetToolbar() {
        final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
            if (getSupportActionBar() != null) {
                getSupportActionBar().setTitle(R.string.ocean_summary_location_title);
            }
            toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24px);
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View v) {
                    returnToMap();
                }
            });

            toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(final MenuItem item) {
                    showWaterColumnProfile(mWaterColumn.getLocation());
                    return false;
                }
            });
        }
    }

    private void returnToMap() {
        // Hide the bottom sheet
        mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);

        // Set the map toolbar title and remove navigation
        setUpMapToolbar();
    }

    /**
     * Customize toolbar for water profile view
     */
    private void setUpWaterProfileToolbar() {
        final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
            if (getSupportActionBar() != null) {
                getSupportActionBar().setTitle(R.string.water_column_profile);
            }
            toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24px);

            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View v) {
                    returnToSummary();
                }
            });
        }
    }

    /**
     * Show the bottom sheet
     */
    public void showBottomSheet() {

        mFab.setVisibility(View.VISIBLE);
        // Change the state of bottom sheet
        if (mBottomSheetBehavior.getState() != BottomSheetBehavior.STATE_COLLAPSED) {
            mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
        } else if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
            showBottomSheetContent();
        }

        mInMapState = false;
    }

    /**
     * Populate bottom sheet with water column details
     */
    private void showBottomSheetContent() {
        // Show summary info about location and water column
        mWaterColumn = mDataManager.getCurrentWaterColumn();

        mBottomSheetPresenter.setWaterColumn(mWaterColumn);

        // Set up the summary toolbar
        setUpBottomSheetToolbar();
    }

    /**
     * Show the candlestick charts for a specific EMU layer
     * @param emuName - int representing an EMU layer name
     */
    private void showSummaryDetail(final int emuName) {
        // Hide the bottom sheet containing the summary view
        mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);

        // Expand the layout for the charts
        final FrameLayout layout = (FrameLayout) findViewById(R.id.chartContainer);
        if (layout != null) {
            layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT));
            layout.requestLayout();
        }

        if (mSummaryChartFragment == null) {
            mSummaryChartFragment = SummaryChartFragment.newInstance();
            mSummaryChartPresenter = new SummaryChartPresenter(emuName, mSummaryChartFragment, mDataManager);
        } else {
            mSummaryChartPresenter.setEmuName(emuName);
        }

        // Add the chart view to the column container
        final FragmentManager fm = getSupportFragmentManager();
        final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        final Fragment f = fm.findFragmentById(R.id.chartContainer);
        if (f == null) {
            transaction.addToBackStack(getString(R.string.fragment_detail_chart));
        }
        transaction.replace(R.id.chartContainer, mSummaryChartFragment);
        transaction.commit();

        // Hide the FAB
        mFab.setVisibility(View.INVISIBLE);
        mInMapState = false;

        setUpChartSummaryToolbar(emuName);
    }

    /**
     * Shrink layout for candlestick charts
     */
    private void shrinkChartContainer() {
        final FrameLayout layout = (FrameLayout) findViewById(R.id.chartContainer);
        if (layout != null) {
            layout.setLayoutParams(new LinearLayout.LayoutParams(0, 0));
            layout.requestLayout();
        }
    }

    /**
     * When a DETAILS button is clicked for a particular EMU, show
     * the candlestick charts.
     * @param emuName - int representing an EMU name (id).
     */
    @Override
    public void onButtonClick(final int emuName) {
        showSummaryDetail(emuName);
    }

    /**
     * Get the state of the network info
     * @return - boolean, false if network state is unavailable
     * and true if device is connected to a network.
     */
    private boolean checkForInternetConnectivity() {
        final ConnectivityManager connManager = (ConnectivityManager) getSystemService(
                Context.CONNECTIVITY_SERVICE);
        final NetworkInfo wifi = connManager.getActiveNetworkInfo();
        return wifi != null && wifi.isConnected();
    }

    /**
     * Show a message at the bottom of the screen prompting user to action
     */
    public void showSnackbar() {
        final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinator_layout);
        if (coordinatorLayout != null) {
            final Snackbar snackbar = Snackbar.make(coordinatorLayout, R.string.tap_location, Snackbar.LENGTH_LONG);

            snackbar.show();
        }
    }

    /**
     * Adjust the view when user clicks on an
     * area with no EMU data.
     */
    @Override
    public void handleNoEmu() {
        mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
        mInMapState = true;
        setUpMapToolbar();
        // Trigger the onPrepareOptionsMenu
        invalidateOptionsMenu();
    }

    /**
     * Customize the behavior to hide/show
     * fragments as user navigates with back button.
     */
    @Override
    public void onBackPressed() {
        final int count = getSupportFragmentManager().getBackStackEntryCount();
        if (count == 0) {
            super.onBackPressed();
        } else {
            final FragmentManager.BackStackEntry entry = getSupportFragmentManager().getBackStackEntryAt(count - 1);
            final String fragmentName = entry.getName();

            if (fragmentName.equalsIgnoreCase(getString(R.string.fragment_detail_chart))) {
                returnToSummary();
            } else if (fragmentName.equalsIgnoreCase(getString(R.string.fragment_summary))) {
                if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
                    mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
                    setUpMapToolbar();
                } else {
                    finish();
                }
            }
        }
    }
}