Java tutorial
/* * Copyright (c) 2015 Ngewi Fet <ngewif@gmail.com> * * 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. */ package org.gnucash.android.ui.common; import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.database.Cursor; import android.graphics.Color; import android.graphics.PorterDuff; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.LayoutRes; import android.support.annotation.StringRes; import android.support.design.widget.NavigationView; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; import com.uservoice.uservoicesdk.UserVoice; import org.gnucash.android.R; import org.gnucash.android.app.GnuCashApplication; import org.gnucash.android.db.DatabaseSchema; import org.gnucash.android.db.adapter.BooksDbAdapter; import org.gnucash.android.ui.account.AccountsActivity; import org.gnucash.android.ui.passcode.PasscodeLockActivity; import org.gnucash.android.ui.report.ReportsActivity; import org.gnucash.android.ui.settings.PreferenceActivity; import org.gnucash.android.ui.transaction.ScheduledActionsActivity; import butterknife.BindView; import butterknife.ButterKnife; /** * Base activity implementing the navigation drawer, to be extended by all activities requiring one. * <p> * Each activity inheriting from this class has an indeterminate progress bar at the top, * (above the action bar) which can be used to display busy operations. See {@link #getProgressBar()} * </p> * * <p>Sub-classes should simply provide their layout using {@link #getContentView()} and then annotate * any variables they wish to use with {@link ButterKnife#bind(Activity)} annotations. The view * binding will be done in this base abstract class.<br> * The activity layout of the subclass is expected to contain {@code DrawerLayout} and * a {@code NavigationView}.<br> * Sub-class should also consider using the {@code toolbar.xml} or {@code toolbar_with_spinner.xml} * for the action bar in their XML layout. Otherwise provide another which contains widgets for the * toolbar and progress indicator with the IDs {@code R.id.toolbar} and {@code R.id.progress_indicator} respectively. * </p> * @author Ngewi Fet <ngewif@gmail.com> */ public abstract class BaseDrawerActivity extends PasscodeLockActivity implements PopupMenu.OnMenuItemClickListener { public static final int ID_MANAGE_BOOKS = 0xB00C; @BindView(R.id.drawer_layout) DrawerLayout mDrawerLayout; @BindView(R.id.nav_view) NavigationView mNavigationView; @BindView(R.id.toolbar) Toolbar mToolbar; @BindView(R.id.toolbar_progress) ProgressBar mToolbarProgress; protected TextView mBookNameTextView; protected ActionBarDrawerToggle mDrawerToggle; public static final int REQUEST_OPEN_DOCUMENT = 0x20; private class DrawerItemClickListener implements NavigationView.OnNavigationItemSelectedListener { @Override public boolean onNavigationItemSelected(MenuItem menuItem) { onDrawerMenuItemClicked(menuItem.getItemId()); return true; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(getContentView()); //if a parameter was passed to open an account within a specific book, then switch String bookUID = getIntent().getStringExtra(UxArgument.BOOK_UID); if (bookUID != null && !bookUID.equals(BooksDbAdapter.getInstance().getActiveBookUID())) { GnuCashApplication.activateBook(bookUID); } ButterKnife.bind(this); setSupportActionBar(mToolbar); final ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setHomeButtonEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setTitle(getTitleRes()); } mToolbarProgress.getIndeterminateDrawable().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN); View headerView = mNavigationView.getHeaderView(0); headerView.findViewById(R.id.drawer_title).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onClickAppTitle(v); } }); mBookNameTextView = (TextView) headerView.findViewById(R.id.book_name); mBookNameTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onClickBook(v); } }); updateActiveBookName(); setUpNavigationDrawer(); } @Override protected void onResume() { super.onResume(); updateActiveBookName(); } /** * Return the layout to inflate for this activity * @return Layout resource identifier */ public abstract @LayoutRes int getContentView(); /** * Return the title for this activity. * This will be displayed in the action bar * @return String resource identifier */ public abstract @StringRes int getTitleRes(); /** * Returns the progress bar for the activity. * <p>This progress bar is displayed above the toolbar and should be used to show busy status * for long operations.<br/> * The progress bar visibility is set to {@link View#GONE} by default. Make visible to use </p> * @return Indeterminate progress bar. */ public ProgressBar getProgressBar() { return mToolbarProgress; } /** * Sets up the navigation drawer for this activity. */ private void setUpNavigationDrawer() { mNavigationView.setNavigationItemSelectedListener(new DrawerItemClickListener()); mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */ mDrawerLayout, /* DrawerLayout object */ R.string.drawer_open, /* "open drawer" description */ R.string.drawer_close /* "close drawer" description */ ) { /** Called when a drawer has settled in a completely closed state. */ public void onDrawerClosed(View view) { super.onDrawerClosed(view); } /** Called when a drawer has settled in a completely open state. */ public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); } }; mDrawerLayout.setDrawerListener(mDrawerToggle); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mDrawerToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mDrawerToggle.onConfigurationChanged(newConfig); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { if (!mDrawerLayout.isDrawerOpen(mNavigationView)) mDrawerLayout.openDrawer(mNavigationView); else mDrawerLayout.closeDrawer(mNavigationView); return true; } return super.onOptionsItemSelected(item); } /** * Update the display name of the currently active book */ protected void updateActiveBookName() { mBookNameTextView.setText(BooksDbAdapter.getInstance().getActiveBookDisplayName()); } /** * Handler for the navigation drawer items * */ protected void onDrawerMenuItemClicked(int itemId) { switch (itemId) { case R.id.nav_item_open: { //Open... files if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //use the storage access framework Intent openDocument = new Intent(Intent.ACTION_OPEN_DOCUMENT); openDocument.addCategory(Intent.CATEGORY_OPENABLE); openDocument.setType("*/*"); startActivityForResult(openDocument, REQUEST_OPEN_DOCUMENT); } else { AccountsActivity.startXmlFileChooser(this); } } break; case R.id.nav_item_favorites: { //favorite accounts Intent intent = new Intent(this, AccountsActivity.class); intent.putExtra(AccountsActivity.EXTRA_TAB_INDEX, AccountsActivity.INDEX_FAVORITE_ACCOUNTS_FRAGMENT); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(intent); } break; case R.id.nav_item_reports: { Intent intent = new Intent(this, ReportsActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(intent); } break; /* //todo: Re-enable this when Budget UI is complete case R.id.nav_item_budgets: startActivity(new Intent(this, BudgetsActivity.class)); break; */ case R.id.nav_item_scheduled_actions: { //show scheduled transactions Intent intent = new Intent(this, ScheduledActionsActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(intent); } break; case R.id.nav_item_export: AccountsActivity.openExportFragment(this); break; case R.id.nav_item_settings: //Settings activity startActivity(new Intent(this, PreferenceActivity.class)); break; case R.id.nav_item_help: SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.edit().putBoolean(UxArgument.SKIP_PASSCODE_SCREEN, true).apply(); UserVoice.launchUserVoice(this); break; } mDrawerLayout.closeDrawer(mNavigationView); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_CANCELED) { super.onActivityResult(requestCode, resultCode, data); return; } switch (requestCode) { case AccountsActivity.REQUEST_PICK_ACCOUNTS_FILE: AccountsActivity.importXmlFileFromIntent(this, data, null); break; case BaseDrawerActivity.REQUEST_OPEN_DOCUMENT: //this uses the Storage Access Framework final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); AccountsActivity.importXmlFileFromIntent(this, data, null); getContentResolver().takePersistableUriPermission(data.getData(), takeFlags); break; default: super.onActivityResult(requestCode, resultCode, data); break; } } @Override public boolean onMenuItemClick(MenuItem item) { long id = item.getItemId(); if (id == ID_MANAGE_BOOKS) { Intent intent = new Intent(this, PreferenceActivity.class); intent.setAction(PreferenceActivity.ACTION_MANAGE_BOOKS); startActivity(intent); mDrawerLayout.closeDrawer(mNavigationView); return true; } BooksDbAdapter booksDbAdapter = BooksDbAdapter.getInstance(); String bookUID = booksDbAdapter.getUID(id); if (!bookUID.equals(booksDbAdapter.getActiveBookUID())) { GnuCashApplication.loadBook(bookUID); finish(); } AccountsActivity.start(GnuCashApplication.getAppContext()); return true; } public void onClickAppTitle(View view) { mDrawerLayout.closeDrawer(mNavigationView); AccountsActivity.start(this); } public void onClickBook(View view) { PopupMenu popup = new PopupMenu(this, view); popup.setOnMenuItemClickListener(this); Menu menu = popup.getMenu(); int maxRecent = 0; Cursor cursor = BooksDbAdapter.getInstance().fetchAllRecords(null, null, DatabaseSchema.BookEntry.COLUMN_MODIFIED_AT + " DESC"); while (cursor.moveToNext() && maxRecent++ < 5) { long id = cursor.getLong(cursor.getColumnIndexOrThrow(DatabaseSchema.BookEntry._ID)); String name = cursor .getString(cursor.getColumnIndexOrThrow(DatabaseSchema.BookEntry.COLUMN_DISPLAY_NAME)); menu.add(0, (int) id, maxRecent, name); } menu.add(0, ID_MANAGE_BOOKS, maxRecent, R.string.menu_manage_books); popup.show(); } }