com.dunrite.aisle5.activities.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.dunrite.aisle5.activities.MainActivity.java

Source

package com.dunrite.aisle5.activities;

/*
 * Copyright 2013 The Android Open Source Project
 *
 * 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.
 */

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.dunrite.aisle5.R;
import com.dunrite.aisle5.SwipeableRecyclerViewTouchListener;
import com.dunrite.aisle5.adapters.MyPerformanceArrayAdapter;
import com.dunrite.aisle5.adapters.RecAdapter;
import com.dunrite.aisle5.list_managment.MyListItem;
import com.dunrite.aisle5.list_managment.MyListMgr;
import com.dunrite.aisle5.list_managment.QuickListItem;
import com.dunrite.aisle5.list_managment.QuickListMgr;
import com.dunrite.aisle5.parse.ParseMgr;
import com.dunrite.aisle5.util.Utils;
import com.google.gson.Gson;

import uk.co.chrisjenx.calligraphy.CalligraphyConfig;
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;

public class MainActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;
    private String[] mCategories;
    private ArrayAdapter<String> adapter;
    private static Context context;
    private static Animator a;
    private static RecyclerView.Adapter mAdapter;
    private static String PACKAGE_NAME;
    public static boolean myListHasItems;
    public static final String MyPrefs = "MyPrefs";

    @Override
    public void onBackPressed() {
        if (MyFragment.mDetailsView.getVisibility() == View.VISIBLE) {
            MyFragment.hide(); // Hide the details view when you press back
            // Might want to add saving?
        } else {
            super.onBackPressed();
        }
    }

    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Set what the default font is throughout the whole app
        CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                .setDefaultFontPath("fonts/RobotoSlab-Regular.ttf").setFontAttrId(R.attr.fontPath).build());
        setContentView(R.layout.activity_main);

        //Start First-launch intro
        SharedPreferences sp = getSharedPreferences(MyPrefs, Context.MODE_PRIVATE);
        if (!sp.getBoolean("first", false)) {
            SharedPreferences.Editor editor = sp.edit();
            editor.putBoolean("first", true);
            editor.commit();
            Intent intent = new Intent(this, IntroActivity.class); //call Intro class
            startActivity(intent);
        }

        MainActivity.context = getApplicationContext();

        PACKAGE_NAME = getApplicationContext().getPackageName();

        /* manages user preference objects */
        prefLoad();

        mCategories = getResources().getStringArray(R.array.categories);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        adapter = new MyPerformanceArrayAdapter(this, mCategories);
        // set a custom shadow that overlays the main content when the drawer opens
        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

        mDrawerList.setAdapter(adapter);
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
        mDrawerList.setScrollingCacheEnabled(false);
        mDrawerList.setAnimationCacheEnabled(false);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);

        // ActionBarDrawerToggle ties together the the proper interactions
        // between the sliding drawer and the action bar app icon
        mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
                mDrawerLayout, /* DrawerLayout object */
                R.string.drawer_open, /* "open drawer" description for accessibility */
                R.string.drawer_close /* "close drawer" description for accessibility */
        ) {
            @Override
            public void onDrawerClosed(View view) {
                supportInvalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                getSupportActionBar().setTitle(MyFragment.cat);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                supportInvalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                getSupportActionBar().setTitle("Aisle5");
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        /* Select MyList if no previous selection is detected */
        if (savedInstanceState == null) {
            selectItem(0);
        }
    }

    /**
     * This method loads objs that have been saved in the user preferences.
     */
    public void prefLoad() {
        SharedPreferences appSharedPrefs = PreferenceManager
                .getDefaultSharedPreferences(this.getApplicationContext());
        Gson gson = new Gson();
        String myListJson = appSharedPrefs.getString("myList", "");
        String quickListJson = appSharedPrefs.getString("quickList", "");
        String parseObjectIDJson = appSharedPrefs.getString("parseObjectID", "");
        String isSyncingJson = appSharedPrefs.getString("isSyncing", "");
        /* Check if the Mgr Objs are saved in the user preferences and load them*/
        if (!("".equals(myListJson) && "".equals(quickListJson) && "".equals(isSyncingJson))) {
            //load them
            MyListMgr.setInstance(gson.fromJson(myListJson, MyListMgr.class));
            QuickListMgr.setInstance(gson.fromJson(quickListJson, QuickListMgr.class));
            ParseMgr.getInstance().syncToggle(gson.fromJson(isSyncingJson, Boolean.class));
            //Log.d("TIM", "BEFORE THE IF");
            if (!("".equals(parseObjectIDJson))) {
                //Log.d("", "objID saved in gson");
                //TODO: set this in the ParseMgr Obj
                ParseMgr.getInstance().setParseObjID(gson.fromJson(parseObjectIDJson, String.class));
            }
        } else {
            /* If they weren't present in the user preferences
            then create them (this only happens on the first app run)*/
            //save them
            Utils.prefSave(getApplicationContext());
        }
        //TODO: Do this better
        Log.d("Syncing", "false");
        if (ParseMgr.getInstance().syncStatus()) {
            Log.d("Syncing", "true");
            ParseMgr.getInstance().parsePull(false);
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    /* Called whenever we call invalidateOptionsMenu() */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        //boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);

        //Manages when to show what buttons in the Actionbar
        //0=Share, 1=Clear, 2=About, 3=GoToMyList
        if ("MyList".equals(getSupportActionBar().getTitle())) {
            if (myListHasItems) {
                menu.getItem(1).setVisible(true);
            } else {
                menu.getItem(1).setVisible(false);
            }
            menu.getItem(3).setVisible(false);
        } else if ("Aisle5".equals(getSupportActionBar().getTitle())) {
            menu.getItem(1).setVisible(false);
            menu.getItem(3).setVisible(false);
        } else {
            menu.getItem(1).setVisible(false);
            menu.getItem(3).setVisible(true);
        }

        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Intent intent;
        // The action bar home/up action should open or close the drawer.
        // ActionBarDrawerToggle will take care of this.
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }

        // Handle action buttons
        switch (item.getItemId()) {
        case R.id.clear_all:
            MyListMgr.getInstance().clearAll();
            while (mAdapter.getItemCount() != 0) {
                ((RecAdapter) mAdapter).remove(0);
            }
            mAdapter.notifyDataSetChanged();
            ImageView empty = (ImageView) findViewById(R.id.empty);
            empty.setVisibility(View.VISIBLE);
            myListHasItems = false;
            supportInvalidateOptionsMenu();
            return true;
        case R.id.go_to_myList:
            selectItem(0);
            supportInvalidateOptionsMenu();
            return true;
        case R.id.action_share:
            supportInvalidateOptionsMenu();
            intent = new Intent(this, SharingActivity.class); //call Sharing class
            startActivity(intent);
            return true;
        case R.id.action_about:
            supportInvalidateOptionsMenu();
            intent = new Intent(this, AboutActivity.class); //call About class
            startActivity(intent);
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    /**
     * The click listener for ListView in the navigation drawer.
     */
    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position);
        }
    }

    private void selectItem(int position) {
        // update the main content by replacing fragments
        Fragment fragment = new MyFragment();
        Bundle args = new Bundle();
        args.putInt(MyFragment.ARG_CAT_NUMBER, position);
        fragment.setArguments(args);

        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();

        // update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        mDrawerLayout.closeDrawer(mDrawerList);
    }

    /**
     * When using the ActionBarDrawerToggle, you must call it during
     * onPostCreate() and onConfigurationChanged()...
     */
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Pass any configuration change to the drawer toggles
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    /**
     * Static way for the java classes to receive the application context.
     */
    public static Context getAppContext() {
        return MainActivity.context;
    }

    /*****************************************************************************
     * MyFragment Class
     *****************************************************************************/
    public static class MyFragment extends Fragment {

        public static final String ARG_CAT_NUMBER = "cat_number";
        private RecyclerView mRecyclerView;
        private GridLayoutManager mLayoutManager;
        public static String cat;
        private static View rootView;
        private String[] myDataset = {};
        //This is for the detailslayout
        private static RelativeLayout mDetailsView;

        /**
         * Constructor
         */
        public MyFragment() {
            //empty constructor
        }

        //Allow RecAdapter to receive the item category
        public static String getCat() {
            return cat;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            int i = getArguments().getInt(ARG_CAT_NUMBER);

            cat = getResources().getStringArray(R.array.categories)[i];
            rootView = inflater.inflate(R.layout.fragment_cat, container, false);

            mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
            //This enables the detailslayout
            mDetailsView = (RelativeLayout) rootView.findViewById(R.id.detailslayout);
            mRecyclerView.setHasFixedSize(true); //not sure if this is needed

            /* Dynamically sets the amount of columns in the RecyclerView */
            Display display = getActivity().getWindowManager().getDefaultDisplay();
            DisplayMetrics outMetrics = new DisplayMetrics();
            display.getMetrics(outMetrics);
            float density = getResources().getDisplayMetrics().density;
            float dpWidth = outMetrics.widthPixels / density;
            int columns = Math.round(dpWidth / 125);
            mLayoutManager = new GridLayoutManager(getActivity(), columns);
            mRecyclerView.setLayoutManager(mLayoutManager);

            ImageView empty = (ImageView) rootView.findViewById(R.id.empty);
            empty.setVisibility(View.INVISIBLE);

            //Decide what to set the Dataset to depending on what category was selected.
            //The Dataset is the Array sent to RecAdapter, which populates the cards
            //with items
            switch (cat) {
            case "MyList":
                ParseMgr.getInstance().parsePull(false);
                //show empty mylist indicator when empty
                if (MyListMgr.getInstance().size() == 0) {
                    empty.setVisibility(View.VISIBLE);
                    MainActivity.myListHasItems = false;
                } else {
                    myDataset = new String[MyListMgr.getInstance().size()];
                    MainActivity.myListHasItems = true;
                    int j = 0;
                    for (MyListItem q : MyListMgr.getInstance().getMyList()) {
                        myDataset[j++] = q.getName();
                    }
                }
                break;
            case "QuickList":
                myDataset = new String[QuickListMgr.getInstance().size()];
                int k = 0;
                for (QuickListItem q : QuickListMgr.getInstance().getQuickList()) {
                    myDataset[k++] = q.getName();
                }
                break;
            case "Fruits":
                myDataset = getResources().getStringArray(R.array.Fruits);
                break;
            case "Dairy":
                myDataset = getResources().getStringArray(R.array.Dairy);
                break;
            case "Vegetables":
                myDataset = getResources().getStringArray(R.array.Vegetables);
                break;
            case "Meats":
                myDataset = getResources().getStringArray(R.array.Meats);
                break;
            case "Misc":
                myDataset = getResources().getStringArray(R.array.Misc);
                break;
            default:
                break;
            }
            // specify an adapter (see also next example)
            mAdapter = new RecAdapter(getActivity(), myDataset);
            //Tells the RecAdapter whether it's in MyList or not
            if ("MyList".equals(cat))
                ((RecAdapter) mAdapter).setInMyList(true);
            else
                ((RecAdapter) mAdapter).setInMyList(false);

            mRecyclerView.setAdapter(mAdapter);

            /**Adds a swipe listener that handles swipe to delete*/
            if ("MyList".equals(cat)) {
                SwipeableRecyclerViewTouchListener swipeTouchListener = new SwipeableRecyclerViewTouchListener(
                        mRecyclerView, new SwipeableRecyclerViewTouchListener.SwipeListener() {
                            @Override
                            public boolean canSwipe(int position) {
                                return true;
                            }

                            @Override
                            public void onDismissedBySwipeLeft(RecyclerView recyclerView,
                                    int[] reverseSortedPositions) {
                                for (int position : reverseSortedPositions) {
                                    MyListMgr.getInstance().removeItem(myDataset[position]);
                                    ((RecAdapter) mAdapter).remove(position);
                                }
                                mAdapter.notifyDataSetChanged();
                                ((MainActivity) getActivity()).selectItem(0);
                            }

                            @Override
                            public void onDismissedBySwipeRight(RecyclerView recyclerView,
                                    int[] reverseSortedPositions) {
                                for (int position : reverseSortedPositions) {
                                    MyListMgr.getInstance().removeItem(myDataset[position]);
                                    ((RecAdapter) mAdapter).remove(position);
                                }
                                mAdapter.notifyDataSetChanged();
                                ((MainActivity) getActivity()).selectItem(0);
                            }
                        });
                mRecyclerView.addOnItemTouchListener(swipeTouchListener);
                final Button addButton = (Button) mDetailsView.findViewById(R.id.addbutton);
                final Button subButton = (Button) mDetailsView.findViewById(R.id.subbutton);
                final Button saveButton = (Button) mDetailsView.findViewById(R.id.save);

                OnClickListener c = new OnClickListener() {
                    TextView theName = (TextView) mDetailsView.findViewById(R.id.itemName);
                    TextView theCount = (TextView) mDetailsView.findViewById(R.id.itemcount);
                    EditText theNote = (EditText) mDetailsView.findViewById(R.id.noteText);

                    @Override
                    public void onClick(View v) {
                        MyListItem i = MyListMgr.getInstance().getMyItem(theName.getText().toString());
                        int temp = Integer.parseInt(theCount.getText().toString());
                        if (v == subButton) {
                            if (temp > 1) {
                                temp--;
                                theCount.setText("" + temp);
                            }
                        }
                        if (v == addButton) {
                            temp++;
                            theCount.setText("" + temp);
                        }
                        if (v == saveButton) {
                            i.setQuantity(temp);
                            i.setNotes(theNote.getText().toString());
                            Utils.prefSave(context);
                            hide();
                            ((MainActivity) getActivity()).selectItem(0); //refreshes Mylist
                        }
                        if (v != theNote) {
                            //Hides keyboard when you tap anything but the note text
                            InputMethodManager imm = (InputMethodManager) getAppContext()
                                    .getSystemService(Context.INPUT_METHOD_SERVICE);
                            imm.hideSoftInputFromWindow(
                                    getActivity().getWindow().getCurrentFocus().getWindowToken(), 0);
                            theNote.clearFocus();
                        }
                    }
                };
                addButton.setOnClickListener(c);
                subButton.setOnClickListener(c);
                saveButton.setOnClickListener(c);
            }
            ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(cat);
            return rootView;
        }

        /**
         * Invokes a Lollipop specific CircleReveal animation that plays when
         * showing the detialsview. If not on lollipop, just plays fade animation
         */
        private static void reveal() {
            final RelativeLayout details = mDetailsView;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                a = ViewAnimationUtils
                        .createCircularReveal(details, (Math.round(RecAdapter.coordX) - 40),
                                (Math.round(RecAdapter.coordY) - 360), 0, details.getHeight() * 2)
                        .setDuration(1250);
                a.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationStart(Animator animation) {
                        super.onAnimationStart(animation);
                        details.setVisibility(View.VISIBLE);
                    }
                });
                a.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        // details.setVisibility(View.INVISIBLE);
                    }
                });
                a.start();
            } else {
                mDetailsView.setVisibility(View.VISIBLE);
            }
        }

        /**
         * Invokes a Lollipop specific CircleReveal animation that plays in reverse
         * when hiding the detialsview. If not on lollipop, just plays fade animation
         */
        private static void hide() {
            // previously visible view
            final RelativeLayout details = mDetailsView;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                // get the center for the clipping circle
                int cx = Math.round(RecAdapter.coordX) - 40;
                int cy = Math.round(RecAdapter.coordY) - 360;

                // get the initial radius for the clipping circle
                int initialRadius = details.getWidth() / 2;

                // create the animation (the final radius is zero)
                Animator anim = ViewAnimationUtils.createCircularReveal(details, cx, cy, initialRadius, 0);

                anim.setDuration(1250);

                // make the view invisible when the animation is done
                anim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        details.setVisibility(View.INVISIBLE);
                    }
                });
                // start the animation
                anim.start();
            } else {
                details.setVisibility(View.INVISIBLE);
            }
        }

        /**
         * Sets the content values inside of the details view of selected item.
         */
        public static void setDetails(String pName, String pCount) {
            int theCount = Integer.parseInt(pCount);
            MyListItem theItem = MyListMgr.getInstance().getMyItem(pName);
            EditText theNoteText = (EditText) mDetailsView.findViewById(R.id.noteText);
            TextView theCountText = (TextView) mDetailsView.findViewById(R.id.itemcount);
            TextView theName = (TextView) mDetailsView.findViewById(R.id.itemName);
            ImageView theImage = (ImageView) mDetailsView.findViewById(R.id.itemImg);

            theName.setText(pName);
            theNoteText.setText(theItem.getNotes());
            theCountText.setText("" + theCount);
            int pic = context.getResources().getIdentifier(pName.toLowerCase(), "drawable",
                    context.getPackageName());
            if (pic == 0) {
                pic = context.getResources().getIdentifier("noart", "drawable", context.getPackageName());
            }
            Glide.with(context).load(pic).centerCrop().into(theImage);
            reveal();
        }
    }
}