Java tutorial
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(); } } }