Java tutorial
// Copyright (c) 2017-2018, Tom Geiselmann // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software // and associated documentation files (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY,WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package com.none.tom.simplerssreader.activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.LoaderManager; import android.content.Intent; import android.content.Loader; import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.support.annotation.ColorRes; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.design.widget.BottomNavigationView; import android.support.v7.app.ActionBar; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.ImageButton; import android.widget.TextView; import com.none.tom.simplerssreader.R; import com.none.tom.simplerssreader.activity.base.BaseActivity; import com.none.tom.simplerssreader.feed.CurrentFeed; import com.none.tom.simplerssreader.feed.SavedEntries; import com.none.tom.simplerssreader.fragment.ExportSubscriptionsFragment; import com.none.tom.simplerssreader.fragment.FeedSubscriptionBaseFragment; import com.none.tom.simplerssreader.fragment.FeedSubscriptionEditFragment; import com.none.tom.simplerssreader.fragment.InitialSetupFragment; import com.none.tom.simplerssreader.fragment.LoadCurrentFeedFragment; import com.none.tom.simplerssreader.fragment.FeedSubscriptionFragment; import com.none.tom.simplerssreader.fragment.SavedEntriesDeleteEntriesFragment; import com.none.tom.simplerssreader.fragment.SavedEntriesFragment; import com.none.tom.simplerssreader.fragment.CurrentFeedFragment; import com.none.tom.simplerssreader.fragment.SavedEntriesSavePasswordFragment; import com.none.tom.simplerssreader.fragment.UnsubscribeFromFeedsFragment; import com.none.tom.simplerssreader.fragment.FeedSubscriptionsFragment; import com.none.tom.simplerssreader.loader.IsFeedUpdateAvailableLoader; import com.none.tom.simplerssreader.loader.ImportSubscriptionsLoader; import com.none.tom.simplerssreader.loader.SavedEntriesSaveLoader; import com.none.tom.simplerssreader.utils.ExportUtils; import com.none.tom.simplerssreader.utils.SnackbarUtils; import com.none.tom.simplerssreader.utils.ErrorHandler; import com.none.tom.simplerssreader.utils.SearchResults; import com.none.tom.simplerssreader.utils.SharedPrefUtils; import com.none.tom.simplerssreader.utils.SoftInputUtils; import com.none.tom.simplerssreader.utils.ThemeUtils; import com.none.tom.simplerssreader.utils.TypedValueUtils; import com.none.tom.simplerssreader.view.HistoryAwareBottomNavigationView; import com.rometools.rome.feed.synd.SyndEntry; import org.joda.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static com.none.tom.simplerssreader.activity.Constants.ICON_ALPHA_LOW; import static com.none.tom.simplerssreader.activity.Constants.ICON_ALPHA_NORMAL; import static com.none.tom.simplerssreader.activity.Constants.INTENT_EXTRA_FONT_SIZE_CHANGED; import static com.none.tom.simplerssreader.activity.Constants.INTENT_EXTRA_THEME_CHANGED; import static com.none.tom.simplerssreader.utils.Constants.*; public class MainActivity extends BaseActivity implements LoaderManager.LoaderCallbacks { private static final String KEY_FRAGMENT_TAG = "key_fragment_tag"; private static final String KEY_IMPORT_SUBSCRIPTIONS = "key_import_subscriptions"; private static final String KEY_ENTRY_URLS = "key_entry_urls"; private static final String KEY_ENTRY_TITLES = "key_entry_titles"; private static final String KEY_SEARCH_VIEW = "key_search_view"; private static final String KEY_SEARCH_QUERY = "key_search_query"; private boolean mNavigateBackNewCurrentFeed; private boolean mFeedSubscriptionsChanged; private boolean mLoadNewCurrentFeed; private boolean mIsCategoriesFilterApplied; private boolean mRetainCategories; private int[] mActionBarInsets; private List<Integer> mSelectedRecyclerViewPositions; private SearchResults mSearchResults; private HistoryAwareBottomNavigationView mBottomNavigationView; private android.view.ActionMode mActionMode; private EditText mSearchEditText; private CurrentFeedFragment mCurrentFeedFragment; private FeedSubscriptionsFragment mFeedSubscriptionsFragment; private SavedEntriesFragment mSavedEntriesFragment; private InitialSetupFragment mInitialSetupFragment; private LoadCurrentFeedFragment mLoadCurrentFeedFragment; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBottomNavigationView = findViewById(R.id.ActivityMainBottomNavigationView); mBottomNavigationView .setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull final MenuItem item) { if (mActionMode != null) { mActionMode.finish(); } if (searchViewIsVisible()) { searchViewHide(); } getCurrentFeedFragment().finishLayoutRefreshing(); switch (item.getItemId()) { case R.id.action_current_feed: if (loadNewCurrentFeed() || getLoadCurrentFeedFragment().isLoadingOrFailed()) { replaceFragment(getLoadCurrentFeedFragment(), true); } else if (getSavedEntriesFragment().isAdded()) { removeFragment(getSavedEntriesFragment(), false); addFragment(getCurrentFeedFragment(), false, false); } else { replaceFragment(getCurrentFeedFragment(), true); } return true; case R.id.action_feed_subscriptions: if (getSavedEntriesFragment().isAdded()) { removeFragment(getSavedEntriesFragment(), false); addFragment(getFeedSubscriptionsFragment(), false, false); } else { replaceFragment(getFeedSubscriptionsFragment(), true); } return true; case R.id.action_saved_entries: replaceFragment(getSavedEntriesFragment(), false); return true; default: return false; } } }); mBottomNavigationView.setOnNavigationItemReselectedListener( new BottomNavigationView.OnNavigationItemReselectedListener() { @Override public void onNavigationItemReselected(@NonNull final MenuItem item) { switch (item.getItemId()) { case R.id.action_current_feed: if (getCurrentFeedFragment().isVisible()) { getCurrentFeedFragment().scrollTo(0); } break; case R.id.action_feed_subscriptions: if (getFeedSubscriptionsFragment().isVisible()) { getFeedSubscriptionsFragment().scrollToTop(); } break; case R.id.action_saved_entries: if (getSavedEntriesFragment().isVisible()) { getSavedEntriesFragment().scrollToTop(); } break; default: break; } } }); final Intent intent = getIntent(); if (!TextUtils.isEmpty(intent.getDataString())) { addSubscription(intent.getDataString(), true); } else if (savedInstanceState == null) { loadCurrentFeedOrShowInitialSetup(); } } @Override public void onBackPressed() { if (searchViewIsVisible()) { searchViewHide(); } else if (!navigateBackInFragmentBackStack()) { super.onBackPressed(); } } @Override protected void onNewIntent(final Intent intent) { super.onNewIntent(intent); setIntent(intent); if (!TextUtils.isEmpty(intent.getDataString())) { addSubscription(intent.getDataString(), false); } } @Override public void onSaveInstanceState(final Bundle outState) { super.onSaveInstanceState(outState); final FragmentManager fm = getFragmentManager(); if (fm.findFragmentByTag(CurrentFeedFragment.TAG) != null) { outState.putString(KEY_FRAGMENT_TAG, CurrentFeedFragment.TAG); } else if (fm.findFragmentByTag(FeedSubscriptionsFragment.TAG) != null) { outState.putString(KEY_FRAGMENT_TAG, FeedSubscriptionsFragment.TAG); } else if (fm.findFragmentByTag(SavedEntriesFragment.TAG) != null) { outState.putString(KEY_FRAGMENT_TAG, SavedEntriesFragment.TAG); } else if (fm.findFragmentByTag(InitialSetupFragment.TAG) != null) { outState.putString(KEY_FRAGMENT_TAG, InitialSetupFragment.TAG); } else if (fm.findFragmentByTag(LoadCurrentFeedFragment.TAG) != null) { outState.putString(KEY_FRAGMENT_TAG, LoadCurrentFeedFragment.TAG); } if (searchViewIsVisible()) { outState.putBoolean(KEY_SEARCH_VIEW, true); outState.putString(KEY_SEARCH_QUERY, searchViewGetQuery()); } if (mActionMode != null) { mActionMode.finish(); } } @Override public void onRestoreInstanceState(final Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); final String tag = savedInstanceState.getString(KEY_FRAGMENT_TAG); if (!TextUtils.isEmpty(tag) && tag.equals(InitialSetupFragment.TAG)) { mBottomNavigationView.setVisibility(View.GONE); } if (savedInstanceState.getBoolean(KEY_SEARCH_VIEW)) { searchViewShow(savedInstanceState.getString(KEY_SEARCH_QUERY)); } } @Override protected void onActivityResult(final int requestCode, final int resultCode, final Intent resultData) { super.onActivityResult(requestCode, resultCode, resultData); switch (resultCode) { case RESULT_OK: switch (requestCode) { case REQUEST_CODE_IMPORT_SUBSCRIPTIONS: importSubscriptions(resultData.getData()); break; case REQUEST_CODE_EXPORT_SUBSCRIPTIONS: exportSubscriptions(resultData.getData()); break; case REQUEST_CODE_EXPORT_SAVED_ENTRIES: exportSavedEntries(resultData.getData(), MIME_TYPE_JSON); break; case REQUEST_CODE_SETTINGS: if (resultData.getBooleanExtra(INTENT_EXTRA_THEME_CHANGED, false) || resultData.getBooleanExtra(INTENT_EXTRA_FONT_SIZE_CHANGED, false)) { recreate(); } break; } break; case RESULT_CANCELED: switch (requestCode) { case REQUEST_CODE_IMPORT_SUBSCRIPTIONS: if (isNotInInitialSetup()) { FeedSubscriptionBaseFragment.getInstance().show(getSupportFragmentManager(), FeedSubscriptionBaseFragment.TAG); } break; case REQUEST_CODE_EXPORT_SUBSCRIPTIONS: ExportSubscriptionsFragment.getInstance().show(getFragmentManager(), ExportSubscriptionsFragment.TAG); break; default: break; } break; default: break; } } @Override public boolean onCreateOptionsMenu(final Menu menu) { getMenuInflater().inflate(R.menu.activity_main_action_bar, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onPrepareOptionsMenu(final Menu menu) { final MenuItem update = menu.findItem(R.id.action_update); final MenuItem sortEntries = menu.findItem(R.id.action_sort_entries); final MenuItem exportSubscriptions = menu.findItem(R.id.action_export_subscriptions); final MenuItem exportSavedEntries = menu.findItem(R.id.action_export_saved_entries); final MenuItem filter = menu.findItem(R.id.action_filter_by_categories); final MenuItem search = menu.findItem(R.id.action_search); final MenuItem settings = menu.findItem(R.id.action_settings); final MenuItem category = menu.findItem(R.id.action_filter_subscriptions_by_category); final boolean searchViewVisible = searchViewIsVisible(); if (isNotInInitialSetup()) { if (getLoadCurrentFeedFragment().isAdded()) { toggleMenuItemVisibility(search, false); toggleMenuItemVisibility(sortEntries, false); toggleMenuItemVisibility(category, false); toggleMenuItemVisibility(exportSubscriptions, false); toggleMenuItemVisibility(exportSavedEntries, false); } else if (getCurrentFeedFragment().isAdded()) { toggleMenuItemVisibility(sortEntries, false); toggleMenuItemVisibility(category, false); toggleMenuItemVisibility(exportSubscriptions, false); toggleMenuItemVisibility(exportSavedEntries, false); if (!searchViewVisible) { toggleMenuItemVisibility(update, true); toggleMenuItemVisibility(search, true); } if (CurrentFeed.isRSSFeed() && CurrentFeed.isCategoriesAvailable() && !searchViewVisible) { toggleMenuItemVisibility(filter, true); } } else if (getFeedSubscriptionsFragment().isAdded()) { toggleMenuItemVisibility(update, false); toggleMenuItemVisibility(sortEntries, false); toggleMenuItemVisibility(filter, false); toggleMenuItemVisibility(exportSavedEntries, false); if (!searchViewVisible) { toggleMenuItemVisibility(category, true); toggleMenuItemVisibility(exportSubscriptions, true); toggleMenuItemVisibility(search, true); } } else if (getSavedEntriesFragment().isAdded()) { toggleMenuItemVisibility(update, false); toggleMenuItemVisibility(filter, false); toggleMenuItemVisibility(category, false); toggleMenuItemVisibility(exportSubscriptions, false); if (!searchViewVisible) { toggleMenuItemVisibility(sortEntries, true); toggleMenuItemVisibility(search, true); toggleMenuItemVisibility(exportSavedEntries, true); } final MenuItem itemSortOrderAsc = menu.findItem(R.id.action_sort_order_ascending); final MenuItem itemSortOrderDesc = menu.findItem(R.id.action_sort_order_descending); if (getSavedEntriesFragment().getSortOrder() == SavedEntriesFragment.SORT_ORDER_DESCENDING) { itemSortOrderDesc.setEnabled(false); if (!itemSortOrderAsc.isVisible()) { itemSortOrderAsc.setVisible(true); } } else { itemSortOrderAsc.setEnabled(false); if (!itemSortOrderDesc.isVisible()) { itemSortOrderDesc.setVisible(true); } } } if (!searchViewVisible) { toggleMenuItemVisibility(settings, true); } } return true; } @Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case R.id.action_search: searchViewShow(); return true; case R.id.action_settings: final Intent intent = new Intent(this, SettingsActivity.class); startActivityForResult(intent, REQUEST_CODE_SETTINGS); return true; case android.R.id.home: onBackPressed(); return true; default: return super.onOptionsItemSelected(item); } } @Override public Loader onCreateLoader(final int id, final Bundle args) { switch (id) { case IsFeedUpdateAvailableLoader.ID: return new IsFeedUpdateAvailableLoader(this); case ImportSubscriptionsLoader.ID: final Uri uri = Uri.parse(args.getString(KEY_IMPORT_SUBSCRIPTIONS)); return new ImportSubscriptionsLoader(this, uri); case SavedEntriesSaveLoader.ID: final List<String> urls = args.getStringArrayList(KEY_ENTRY_URLS); final List<String> titles = args.getStringArrayList(KEY_ENTRY_TITLES); return new SavedEntriesSaveLoader(this, urls, titles); default: return null; } } @Override public void onLoadFinished(final Loader loader, final Object data) { final int id = loader.getId(); switch (id) { case IsFeedUpdateAvailableLoader.ID: onFeedUpdateResult((String) data); break; case ImportSubscriptionsLoader.ID: onSubscriptionImportResult((List) data); break; case SavedEntriesSaveLoader.ID: showSnackbar(getString(R.string.saved_entries_save_succeeded)); break; default: break; } getLoaderManager().destroyLoader(id); } @Override public void onLoaderReset(final Loader loader) { } private void onFeedUpdateResult(final String id) { getCurrentFeedFragment().currentFeedUpdateCheckFinished(); final int errno = ErrorHandler.getErrno(); if (errno < 0) { showSnackbar(ErrorHandler.resolveErrorMessage(this, errno)); } else { final int position = SharedPrefUtils.getCurrentFeedPosition(this); SharedPrefUtils.updateSubscriptionIdAt(this, id, position); getCurrentFeedFragment().scrollToTop(); } } private void onSubscriptionImportResult(final List outlines) { final int errno = ErrorHandler.getErrno(); final boolean isNotInInitialSetup = isNotInInitialSetup(); if (errno < 0) { if (isNotInInitialSetup) { showSnackbar(ErrorHandler.resolveErrorMessage(this, errno)); } } else { SharedPrefUtils.addSubscriptions(this, outlines); if (isNotInInitialSetup) { showSnackbar(getString(R.string.subscription_import_succeeded)); getFeedSubscriptionsFragment().feedSubscriptionsChanged(); } else { removeFragment(getInitialSetupFragment(), true); mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_current_feed); mBottomNavigationView.setVisibility(View.VISIBLE); toggleActionBarVisibility(true); loadCurrentFeed(true); } } } private void addSubscription(final String url, final boolean coldLaunch) { if (isNotInInitialSetup()) { mBottomNavigationView.setSelectedItemId(R.id.action_feed_subscriptions); if (!coldLaunch && FeedSubscriptionFragment.getInstance().isAdded()) { FeedSubscriptionFragment.getInstance().dismiss(); } } else { addFragment(getInitialSetupFragment(), false, false); mBottomNavigationView.setVisibility(View.GONE); } FeedSubscriptionFragment.getInstance(url).show(getFragmentManager(), FeedSubscriptionFragment.TAG); } public void addSubscription(final String title, final String category, final String url) { final int position = SharedPrefUtils.addSubscription(this, title, category, url); if (getFeedSubscriptionsFragment().isAdded()) { getFeedSubscriptionsFragment().feedSubscriptionsChanged(position); showSnackbar(getString(R.string.subscription_added)); } if (getInitialSetupFragment().isAdded()) { removeFragment(getInitialSetupFragment(), false); mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_current_feed); mBottomNavigationView.setVisibility(View.VISIBLE); toggleActionBarVisibility(true); loadCurrentFeed(false); } } private void addFragment(final Fragment fragment, final boolean addToBackStack, final boolean allowStateLoss) { final FragmentManager fm = getFragmentManager(); final FragmentTransaction transaction = fm.beginTransaction(); final String tag; if (fragment instanceof CurrentFeedFragment) { tag = CurrentFeedFragment.TAG; } else if (fragment instanceof FeedSubscriptionsFragment) { tag = FeedSubscriptionsFragment.TAG; } else if (fragment instanceof SavedEntriesFragment) { tag = SavedEntriesFragment.TAG; } else if (fragment instanceof InitialSetupFragment) { tag = InitialSetupFragment.TAG; } else { tag = LoadCurrentFeedFragment.TAG; } transaction.add(R.id.ActivityMainFragmentContainer, fragment, tag); if (addToBackStack) { transaction.addToBackStack(tag); } if (allowStateLoss) { transaction.commitAllowingStateLoss(); } else { transaction.commit(); } fm.executePendingTransactions(); } private void alterMenuItemAlpha(final MenuItem item, final boolean enable) { if (enable) { if (!item.isEnabled()) { item.setEnabled(true); item.getIcon().setAlpha(ICON_ALPHA_NORMAL); } } else if (item.isEnabled()) { item.setEnabled(false); item.getIcon().setAlpha(ICON_ALPHA_LOW); } } public void currentFeedLoaded() { if (getLoadCurrentFeedFragment().isAdded()) { removeFragment(getLoadCurrentFeedFragment(), true); addFragment(getCurrentFeedFragment(), true, true); } final List<SyndEntry> entries = CurrentFeed.getEntries(); if (!entries.isEmpty()) { final int position = SharedPrefUtils.getCurrentFeedPosition(this); SharedPrefUtils.updateSubscriptionIdAt(this, entries.get(0).getUri(), position); } } public void editSubscription(final String category, final String title, final int position) { SharedPrefUtils.updateSubscriptionCategoryTitleAt(this, category, title, position); getFeedSubscriptionsFragment().feedSubscriptionsChanged(); showSnackbar(getString(R.string.subscription_edit_succeeded)); } @SuppressWarnings("SameParameterValue") private void exportSavedEntries(final Uri uri, final String mimeType) { if (mimeType.equals(MIME_TYPE_JSON)) { ExportUtils.exportSavedEntriesAsJSON(this, uri); } } private void exportSubscriptions(final Uri uri) { ExportUtils.exportSubscriptions(this, uri, mRetainCategories); final int errno = ErrorHandler.getErrno(); if (errno < 0) { showSnackbar(ErrorHandler.resolveErrorMessage(this, ErrorHandler.getErrno())); } else { showSnackbar(getString(R.string.subscription_export_succeeded)); } } private String getActionModeQuantityString(final int quantity) { final Resources res = getResources(); if (getCurrentFeedFragment().isAdded()) { return res.getQuantityString(R.plurals.action_mode_current_feed, quantity); } else if (getFeedSubscriptionsFragment().isAdded()) { return res.getQuantityString(R.plurals.action_mode_feed_subscriptions, quantity); } return res.getQuantityString(R.plurals.action_mode_saved_entries, quantity); } public HistoryAwareBottomNavigationView getBottomNavigationView() { return mBottomNavigationView; } private CurrentFeedFragment getCurrentFeedFragment() { if (mCurrentFeedFragment == null) { final Fragment fragment = getFragmentManager().findFragmentByTag(CurrentFeedFragment.TAG); if (fragment != null) { mCurrentFeedFragment = (CurrentFeedFragment) fragment; } else { mCurrentFeedFragment = new CurrentFeedFragment(); } } return mCurrentFeedFragment; } private FeedSubscriptionsFragment getFeedSubscriptionsFragment() { if (mFeedSubscriptionsFragment == null) { final Fragment fragment = getFragmentManager().findFragmentByTag(FeedSubscriptionsFragment.TAG); if (fragment != null) { mFeedSubscriptionsFragment = (FeedSubscriptionsFragment) fragment; } else { mFeedSubscriptionsFragment = new FeedSubscriptionsFragment(); } } return mFeedSubscriptionsFragment; } private InitialSetupFragment getInitialSetupFragment() { if (mInitialSetupFragment == null) { final Fragment fragment = getFragmentManager().findFragmentByTag(InitialSetupFragment.TAG); if (fragment != null) { mInitialSetupFragment = (InitialSetupFragment) fragment; } else { mInitialSetupFragment = new InitialSetupFragment(); } } return mInitialSetupFragment; } private LoadCurrentFeedFragment getLoadCurrentFeedFragment() { if (mLoadCurrentFeedFragment == null) { final Fragment fragment = getFragmentManager().findFragmentByTag(LoadCurrentFeedFragment.TAG); if (fragment != null) { mLoadCurrentFeedFragment = (LoadCurrentFeedFragment) fragment; } else { mLoadCurrentFeedFragment = new LoadCurrentFeedFragment(); } } return mLoadCurrentFeedFragment; } public SavedEntriesFragment getSavedEntriesFragment() { if (mSavedEntriesFragment == null) { final Fragment fragment = getFragmentManager().findFragmentByTag(SavedEntriesFragment.TAG); if (fragment != null) { mSavedEntriesFragment = (SavedEntriesFragment) fragment; } else { mSavedEntriesFragment = new SavedEntriesFragment(); } } return mSavedEntriesFragment; } private void importSubscriptions(final Uri uri) { final Bundle args = new Bundle(); args.putString(KEY_IMPORT_SUBSCRIPTIONS, uri.toString()); getLoaderManager().restartLoader(ImportSubscriptionsLoader.ID, args, this); } public boolean isCategoriesFilterNotApplied() { return !mIsCategoriesFilterApplied; } private boolean isNotInInitialSetup() { return !TextUtils.isEmpty(SharedPrefUtils.getCurrentFeedUrl(this)); } public boolean isRecyclerViewItemSelected(final int position) { return mSelectedRecyclerViewPositions != null && mSelectedRecyclerViewPositions.contains(position); } private void loadCurrentFeed(final boolean allowStateLoss) { if (getFeedSubscriptionsFragment().isAdded()) { replaceFragment(getLoadCurrentFeedFragment(), true); } addFragment(getLoadCurrentFeedFragment(), false, allowStateLoss); } private void loadCurrentFeedOrShowInitialSetup() { if (isNotInInitialSetup()) { loadCurrentFeed(false); } else { mBottomNavigationView.setVisibility(View.GONE); addFragment(getInitialSetupFragment(), false, false); } } private boolean loadNewCurrentFeed() { if (mLoadNewCurrentFeed) { mLoadNewCurrentFeed = false; return true; } return false; } private boolean navigateBackInFragmentBackStack() { final FragmentManager fm = getFragmentManager(); fm.popBackStackImmediate(); if (fm.getBackStackEntryCount() <= 0) { return false; } if (mNavigateBackNewCurrentFeed) { fm.popBackStackImmediate(); getLoadCurrentFeedFragment().cancelFeedLoading(); SharedPrefUtils.putCurrentFeedPosition(this, SharedPrefUtils.getPreviousFeedPosition(this)); replaceFragment(getLoadCurrentFeedFragment(), false); mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_current_feed); mNavigateBackNewCurrentFeed = false; } else { final String tag = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName(); if (tag.equals(CurrentFeedFragment.TAG)) { mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_current_feed); } else if (tag.equals(FeedSubscriptionsFragment.TAG)) { mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_feed_subscriptions); } else { fm.popBackStackImmediate(); mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_feed_subscriptions); mNavigateBackNewCurrentFeed = true; } } return true; } private void recyclerViewScrollTo(final int position, final List<Integer> highlight) { if (getCurrentFeedFragment().isAdded()) { if (highlight != null) { getCurrentFeedFragment().highlightVisibleSearchResults(highlight); } getCurrentFeedFragment().scrollTo(position); } else if (getFeedSubscriptionsFragment().isAdded()) { if (highlight != null) { getFeedSubscriptionsFragment().highlightVisibleSearchResults(highlight); } getFeedSubscriptionsFragment().scrollTo(position); } else { if (highlight != null) { getSavedEntriesFragment().highlightVisibleSearchResults(highlight); } getSavedEntriesFragment().scrollTo(position); } } private void removeFragment(final Fragment fragment, final boolean allowStateLoss) { final FragmentManager fm = getFragmentManager(); final FragmentTransaction transaction = fm.beginTransaction(); transaction.remove(fragment); if (allowStateLoss) { transaction.commitAllowingStateLoss(); } else { transaction.commit(); } fm.executePendingTransactions(); } private void replaceFragment(final Fragment fragment, final boolean addToBackStack) { final FragmentManager fm = getFragmentManager(); final FragmentTransaction transaction = fm.beginTransaction(); final String tag; if (fragment instanceof CurrentFeedFragment) { tag = CurrentFeedFragment.TAG; } else if (fragment instanceof FeedSubscriptionsFragment) { tag = FeedSubscriptionsFragment.TAG; } else if (fragment instanceof SavedEntriesFragment) { tag = SavedEntriesFragment.TAG; } else if (fragment instanceof InitialSetupFragment) { tag = InitialSetupFragment.TAG; } else { tag = LoadCurrentFeedFragment.TAG; } transaction.replace(R.id.ActivityMainFragmentContainer, fragment, tag); if (addToBackStack) { transaction.addToBackStack(tag); } transaction.commit(); fm.executePendingTransactions(); } private <T> void resetCardViewBackground(final T positions, final Class<T> clazz) { if (getCurrentFeedFragment().isAdded()) { getCurrentFeedFragment().resetCardViewBackground(positions, clazz); } else if (getFeedSubscriptionsFragment().isAdded()) { getFeedSubscriptionsFragment().resetCardViewBackground(positions, clazz); } else { getSavedEntriesFragment().resetCardViewBackground(positions, clazz); } } private void saveEntries() { if (!TextUtils.isEmpty(SharedPrefUtils.get(MainActivity.this, KEY_HASHED_PASSWORD, String.class))) { final int size = mSelectedRecyclerViewPositions.size(); final ArrayList<String> entryUrls = new ArrayList<>(size); final ArrayList<String> entryTitles = new ArrayList<>(size); final List<SyndEntry> entries = CurrentFeed.getEntries(); for (final Integer position : mSelectedRecyclerViewPositions) { final SyndEntry entry = entries.get(position); entryUrls.add(entry.getLink()); entryTitles.add(entry.getTitle()); } SavedEntriesSavePasswordFragment.getInstance(entryUrls, entryTitles).show(getFragmentManager(), SavedEntriesSavePasswordFragment.TAG); } else { showSnackbar(getString(R.string.saved_entries_setup_password)); } } @SuppressWarnings("ConstantConditions") private void setActionBarColor(@ColorRes final int colorRes) { getSupportActionBar().setBackgroundDrawable(new ColorDrawable(getColor(colorRes))); } private void setStatusBarColor(@ColorRes final int colorRes) { getWindow().setStatusBarColor(getColor(colorRes)); } public void showFeedSubscriptionBaseFragment() { if (isNotInInitialSetup()) { FeedSubscriptionBaseFragment.getInstance().show(getSupportFragmentManager(), FeedSubscriptionBaseFragment.TAG); } } private void showSnackbar(final String msg) { if (getCurrentFeedFragment().isAdded()) { SnackbarUtils.show(this, getCurrentFeedFragment().getLayout(), msg); } else if (getFeedSubscriptionsFragment().isAdded()) { SnackbarUtils.show(this, getFeedSubscriptionsFragment().getLayout(), msg); } else { SnackbarUtils.show(this, getSavedEntriesFragment().getLayout(), msg); } } public void showSubscriptionAt(final int position) { if (mFeedSubscriptionsChanged || SharedPrefUtils.getCurrentFeedPosition(this) != position) { updateCurrentFeedPosition(position); } mBottomNavigationView.setSelectedItemId(R.id.action_current_feed); invalidateOptionsMenu(); } @SuppressWarnings("SameParameterValue") public void startActivity(final String action, final String mimeType, final boolean... retainCategories) { final Intent intent = new Intent(action).setType(mimeType); if (action.equals(Intent.ACTION_OPEN_DOCUMENT)) { startActivityForResult(intent, REQUEST_CODE_IMPORT_SUBSCRIPTIONS); } else if (action.equals(Intent.ACTION_CREATE_DOCUMENT)) { final String title = TAG.toLowerCase() + "_" + new LocalDateTime().toString(); if (mimeType.equals(MIME_TYPE_OPML)) { if (retainCategories.length > 0) { mRetainCategories = retainCategories[0]; } intent.putExtra(Intent.EXTRA_TITLE, title); startActivityForResult(intent, REQUEST_CODE_EXPORT_SUBSCRIPTIONS); } else if (mimeType.equals(MIME_TYPE_JSON)) { intent.putExtra(Intent.EXTRA_TITLE, title + ".json"); startActivityForResult(intent, REQUEST_CODE_EXPORT_SAVED_ENTRIES); } } } @SuppressWarnings("ConstantConditions") private void toggleActionBarVisibility(final boolean visible) { final ActionBar actionBar = getSupportActionBar(); if (visible) { if (!actionBar.isShowing()) { actionBar.show(); } } else if (actionBar.isShowing()) { actionBar.hide(); } } private void toggleMenuItemVisibility(final MenuItem item, final boolean visible) { if (visible) { if (!item.isVisible()) { item.setVisible(true); } } else if (item.isVisible()) { item.setVisible(false); } } private void toggleSystemUiVisibility(final boolean reset) { final View view = getWindow().getDecorView(); if (reset) { view.setSystemUiVisibility(0); } else { view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); } } public void unsubscribe(final List<String> titles) { mActionMode.finish(); if (SharedPrefUtils.unsubscribe(this, titles)) { updateCurrentFeedPosition(0); getFeedSubscriptionsFragment().feedSubscriptionsChanged(); mFeedSubscriptionsChanged = true; } if (SharedPrefUtils.isSubscriptionsEmpty(this)) { getLoadCurrentFeedFragment().cancelFeedLoading(); final Loader loader = getLoaderManager().getLoader(IsFeedUpdateAvailableLoader.ID); if (loader != null && loader.isStarted()) { loader.cancelLoad(); } CurrentFeed.set(null); removeFragment(getFeedSubscriptionsFragment(), false); toggleActionBarVisibility(false); getFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); mCurrentFeedFragment = null; mFeedSubscriptionsFragment = null; mSavedEntriesFragment = null; mInitialSetupFragment = null; mLoadCurrentFeedFragment = null; mBottomNavigationView.setVisibility(View.GONE); replaceFragment(getInitialSetupFragment(), false); } } private void updateActionModeTitles(final String element) { if (mActionMode != null) { final StringBuilder subtitle = new StringBuilder(); final int size = mSelectedRecyclerViewPositions.size(); for (int i = 0; i < size; i++) { final Integer position = mSelectedRecyclerViewPositions.get(i); final String title; if (getCurrentFeedFragment().isAdded()) { title = CurrentFeed.getTitleForEntry(CurrentFeed.getEntries().get(position)); } else if (getFeedSubscriptionsFragment().isAdded()) { title = SharedPrefUtils.getSubscriptionTitleAt(this, position); } else { title = SavedEntries.getSavedEntryTitleAt(position); } if (i > 0) { subtitle.append(", "); subtitle.append(title); } else { subtitle.append(title); } } mActionMode.setTitle(String.valueOf(mSelectedRecyclerViewPositions.size()) + ' ' + element + ' ' + getString(R.string.selected)); mActionMode.setSubtitle(subtitle.toString()); } } private void updateCurrentFeedPosition(final int position) { getLoadCurrentFeedFragment().cancelFeedLoading(); SharedPrefUtils.putCurrentFeedPosition(this, position); mFeedSubscriptionsChanged = false; mLoadNewCurrentFeed = true; } @SuppressWarnings("ConstantConditions") public boolean searchViewIsVisible() { return TextUtils.isEmpty(getSupportActionBar().getTitle()); } private String searchViewGetQuery() { return mSearchEditText.getText().toString(); } public SearchResults searchViewGetSearchResultsCursor() { return mSearchResults; } private void searchViewNavigateCursor(final boolean next) { if (mSearchResults != null && !mSearchResults.isEmpty()) { final int previous = mSearchResults.current(); if (next) { recyclerViewScrollTo(mSearchResults.next(), null); } else { recyclerViewScrollTo(mSearchResults.previous(), null); } final int current = mSearchResults.current(); if (getCurrentFeedFragment().isAdded()) { getCurrentFeedFragment().updateHighlightedSearchResult(previous, current); } else if (getFeedSubscriptionsFragment().isAdded()) { getFeedSubscriptionsFragment().updateHighlightedSearchResult(previous, current); } else { getSavedEntriesFragment().updateHighlightedSearchResult(previous, current); } } } @SuppressWarnings("ConstantConditions") private void searchViewQueryTextChange(final CharSequence query, final ImageButton navigateBack, final TextView results) { @DrawableRes final int drawableRes; if (!TextUtils.isEmpty(query)) { if (ThemeUtils.isDarkThemeSelected(this)) { drawableRes = R.drawable.ic_clear_white_24dp; } else { drawableRes = R.drawable.ic_clear_black_24dp; } } else { if (results.getVisibility() != View.INVISIBLE) { results.setVisibility(View.INVISIBLE); } if (ThemeUtils.isDarkThemeSelected(this)) { drawableRes = R.drawable.ic_arrow_back_white_24dp; } else { drawableRes = R.drawable.ic_arrow_back_black_24dp; } } if (navigateBack.getDrawable().getConstantState() != getDrawable(drawableRes).getConstantState()) { navigateBack.setImageResource(drawableRes); } if (mSearchResults != null && !mSearchResults.isEmpty()) { resetCardViewBackground(mSearchResults.getAll(), List.class); mSearchResults = null; } } @SuppressWarnings("ConstantConditions") private void searchViewQueryTextSubmit(final TextView results) { final String query = searchViewGetQuery(); if (TextUtils.isEmpty(query)) { return; } if (getCurrentFeedFragment().isAdded()) { mSearchResults = CurrentFeed.getSearchResultsFor(query, getCurrentFeedFragment().getFirstCompletelyVisibleItemPosition()); } else if (getFeedSubscriptionsFragment().isAdded()) { mSearchResults = SharedPrefUtils.getSearchResultsFor(MainActivity.this, query, getFeedSubscriptionsFragment().getFirstCompletelyVisibleItemPosition()); } else { mSearchResults = SavedEntries.getSearchResultsFor((query), getSavedEntriesFragment().getFirstCompletelyVisibleItemPosition()); } if (!mSearchResults.isEmpty()) { searchViewShowCursorPosition(results); recyclerViewScrollTo(mSearchResults.current(), mSearchResults.getAll()); } else { showSnackbar(getString(R.string.no_search_results)); } } @SuppressWarnings("ConstantConditions") private void searchViewHide() { final ActionBar actionBar = getSupportActionBar(); final android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) actionBar .getCustomView().getParent(); if (!TextUtils.isEmpty(searchViewGetQuery())) { mSearchEditText.setText(null); SoftInputUtils.forceShowSoftInput(this, mSearchEditText); } else { setActionBarColor(TypedValueUtils.resolve(this, R.attr.colorPrimary)); setStatusBarColor(TypedValueUtils.resolve(this, R.attr.colorPrimaryDark)); toggleSystemUiVisibility(true); toolbar.setContentInsetsAbsolute(mActionBarInsets[0], mActionBarInsets[1]); SoftInputUtils.dismissSoftInput(this, toolbar); actionBar.setCustomView(null); actionBar.setDisplayShowCustomEnabled(false); actionBar.setDisplayShowTitleEnabled(true); invalidateOptionsMenu(); } } private void searchViewShowCursorPosition(final TextView results) { if (mSearchResults != null) { final String currentPosition = mSearchResults.toString(); if (!TextUtils.isEmpty(currentPosition)) { results.setText(currentPosition); if (results.getVisibility() != View.VISIBLE) { results.setVisibility(View.VISIBLE); } } } } @SuppressWarnings("ConstantConditions") private void searchViewShow(final String... query) { final ActionBar actionBar = getSupportActionBar(); setActionBarColor(TypedValueUtils.resolve(this, R.attr.colorActionBarSearchViewExpanded)); setStatusBarColor(TypedValueUtils.resolve(this, R.attr.colorStatusBarSearchViewExpanded)); actionBar.setDisplayShowTitleEnabled(false); actionBar.setCustomView(R.layout.activity_main_search_view); actionBar.setDisplayShowCustomEnabled(true); invalidateOptionsMenu(); final View view = actionBar.getCustomView(); final android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) view.getParent(); mActionBarInsets = new int[] { toolbar.getContentInsetLeft(), toolbar.getContentInsetRight() }; toolbar.setContentInsetsAbsolute(0, 0); mSearchEditText = view.findViewById(R.id.ActivityMainSearchEditText); final TextView results = view.findViewById(R.id.ActivityMainResultsTextView); final ImageButton navigateBack = view.findViewById(R.id.ActivityMainBackImageButton); final ImageButton previous = view.findViewById(R.id.ActivityMainSearchPreviousImageButton); final ImageButton next = view.findViewById(R.id.ActivityMainSearchNextImageButton); results.setVisibility(View.INVISIBLE); if (ThemeUtils.isDarkThemeSelected(this)) { navigateBack.setImageDrawable(getDrawable(R.drawable.ic_arrow_back_white_24dp)); previous.setImageDrawable(getDrawable(R.drawable.ic_navigate_before_white_24dp)); next.setImageDrawable(getDrawable(R.drawable.ic_navigate_next_white_24dp)); } else { toggleSystemUiVisibility(false); } mSearchEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(final CharSequence query, final int i, final int i1, final int i2) { } @Override public void onTextChanged(final CharSequence query, final int i, final int i1, final int i2) { searchViewQueryTextChange(query, navigateBack, results); } @Override public void afterTextChanged(final Editable editable) { } }); mSearchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(final TextView textView, final int id, final KeyEvent keyEvent) { if (id == EditorInfo.IME_ACTION_SEARCH) { SoftInputUtils.dismissSoftInput(MainActivity.this, mSearchEditText); searchViewQueryTextSubmit(results); } return results.getVisibility() != View.INVISIBLE; } }); navigateBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View view) { searchViewHide(); } }); previous.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View view) { searchViewNavigateCursor(false); searchViewShowCursorPosition(results); } }); next.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View view) { searchViewNavigateCursor(true); searchViewShowCursorPosition(results); } }); if (query.length > 0) { mSearchEditText.setText(query[0]); } SoftInputUtils.forceShowSoftInput(this, mSearchEditText); } public void startOrUpdateActionMode(final int position) { final boolean isCurrentFeedSelected = getCurrentFeedFragment().isAdded(); final boolean isFeedSubscriptionsSelected = getFeedSubscriptionsFragment().isAdded(); if (mActionMode != null) { if (!mSelectedRecyclerViewPositions.contains(position)) { mSelectedRecyclerViewPositions.add(position); updateActionModeTitles(getActionModeQuantityString(mSelectedRecyclerViewPositions.size())); } else { mSelectedRecyclerViewPositions.remove(Integer.valueOf(position)); if (mSelectedRecyclerViewPositions.isEmpty()) { resetCardViewBackground(position, Integer.class); mActionMode.finish(); } else { updateActionModeTitles(getActionModeQuantityString(mSelectedRecyclerViewPositions.size())); } resetCardViewBackground(position, Integer.class); } return; } mSelectedRecyclerViewPositions = new ArrayList<>(Collections.singletonList(position)); mActionMode = startActionMode(new android.view.ActionMode.Callback() { @Override public boolean onCreateActionMode(final android.view.ActionMode mode, final Menu menu) { mode.getMenuInflater().inflate(R.menu.activity_main_action_mode, menu); setStatusBarColor(TypedValueUtils.resolve(MainActivity.this, R.attr.colorStatusBarActionMode)); final int size = mSelectedRecyclerViewPositions.size(); mode.setTitle(String.valueOf(size) + ' ' + getActionModeQuantityString(size) + ' ' + getString(R.string.selected)); final StringBuilder subtitle = new StringBuilder(); if (isCurrentFeedSelected) { subtitle.append(CurrentFeed.getTitleForEntry(CurrentFeed.getEntries().get(position))); } else if (isFeedSubscriptionsSelected) { subtitle.append(SharedPrefUtils.getSubscriptionTitleAt(MainActivity.this, position)); } else { subtitle.append(SavedEntries.getSavedEntryTitleAt(position)); } if (mSelectedRecyclerViewPositions.size() > 1) { subtitle.append(",\u2026"); } mode.setSubtitle(subtitle.toString()); return true; } @Override public boolean onPrepareActionMode(final android.view.ActionMode mode, final Menu menu) { final MenuItem readEntry = menu.findItem(R.id.action_read_entry); final MenuItem readComments = menu.findItem(R.id.action_read_comments); final MenuItem saveEntries = menu.findItem(R.id.action_save_entries); if (isCurrentFeedSelected) { final SyndEntry entry = CurrentFeed.getEntries().get(position); if (mSelectedRecyclerViewPositions.size() > 1) { readEntry.setVisible(false); readComments.setVisible(false); if (TextUtils.isEmpty(CurrentFeed.getLinkForEntry(entry))) { saveEntries.setVisible(false); } } else { if (!TextUtils.isEmpty(CurrentFeed.getLinkForEntry(entry))) { readEntry.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); readEntry.setVisible(true); } else { readEntry.setVisible(false); } if (!TextUtils.isEmpty(CurrentFeed.getCommentsForEntry(entry))) { readComments.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); readComments.setVisible(true); } else { readComments.setVisible(false); } saveEntries.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); } } else if (isFeedSubscriptionsSelected) { final MenuItem itemUnsubscribeFromFeeds = menu.findItem(R.id.action_unsubscribe_from_feeds); final MenuItem itemEditSubscription = menu.findItem(R.id.action_edit_subscription); readEntry.setVisible(false); readComments.setVisible(false); saveEntries.setVisible(false); itemUnsubscribeFromFeeds.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); itemUnsubscribeFromFeeds.setVisible(true); if (mSelectedRecyclerViewPositions.size() > 1) { itemEditSubscription.setVisible(false); } else { itemEditSubscription.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); itemEditSubscription.setVisible(true); } } else { final MenuItem itemDeleteSavedEntries = menu.findItem(R.id.action_delete_entries); readComments.setVisible(false); saveEntries.setVisible(false); itemDeleteSavedEntries.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); itemDeleteSavedEntries.setVisible(true); if (mSelectedRecyclerViewPositions.size() > 1) { readEntry.setVisible(false); } else { readEntry.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); if (!readEntry.isVisible()) { readEntry.setVisible(true); } } } return true; } @Override public boolean onActionItemClicked(final android.view.ActionMode mode, final MenuItem item) { switch (item.getItemId()) { case R.id.action_read_entry: final String link; if (isCurrentFeedSelected) { link = CurrentFeed.getLinkForEntry(CurrentFeed.getEntries().get(position)); } else { link = SavedEntries.getSavedEntryUrlAt(mSelectedRecyclerViewPositions.get(0)); } startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link))); mode.finish(); return true; case R.id.action_read_comments: mode.finish(); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(CurrentFeed.getCommentsForEntry(CurrentFeed.getEntries().get(position))))); return true; case R.id.action_save_entries: saveEntries(); mode.finish(); return true; case R.id.action_unsubscribe_from_feeds: final List<String> feedUnsubscriptions = SharedPrefUtils .getSubscriptionTitlesFor(MainActivity.this, mSelectedRecyclerViewPositions); UnsubscribeFromFeedsFragment.getInstance((ArrayList<String>) feedUnsubscriptions) .show(getFragmentManager(), UnsubscribeFromFeedsFragment.TAG); return true; case R.id.action_delete_entries: SavedEntriesDeleteEntriesFragment.getInstance(mSelectedRecyclerViewPositions) .show(getFragmentManager(), SavedEntriesDeleteEntriesFragment.TAG); mode.finish(); return true; case R.id.action_edit_subscription: FeedSubscriptionEditFragment.getInstance(position).show(getFragmentManager(), FeedSubscriptionEditFragment.TAG); mode.finish(); return true; default: return false; } } @Override public void onDestroyActionMode(final android.view.ActionMode mode) { setStatusBarColor(TypedValueUtils.resolve(MainActivity.this, R.attr.colorPrimaryDark)); resetCardViewBackground(mSelectedRecyclerViewPositions, List.class); mSelectedRecyclerViewPositions = null; mActionMode = null; } }); } public void startActionMode(final List<Integer> positions) { if (mActionMode != null) { return; } mIsCategoriesFilterApplied = true; mSelectedRecyclerViewPositions = positions; mActionMode = startActionMode(new android.view.ActionMode.Callback() { private int mCursor; @Override public boolean onCreateActionMode(final android.view.ActionMode mode, final Menu menu) { mode.getMenuInflater().inflate(R.menu.activity_main_action_mode_filter, menu); final MenuItem previous = menu.findItem(R.id.action_filter_previous); final MenuItem next = menu.findItem(R.id.action_filter_next); setStatusBarColor(TypedValueUtils.resolve(MainActivity.this, R.attr.colorStatusBarActionMode)); if (ThemeUtils.isDarkThemeSelected(MainActivity.this)) { previous.setIcon(getDrawable(R.drawable.ic_arrow_upward_white_24dp)); next.setIcon(getDrawable(R.drawable.ic_arrow_downward_white_24dp)); } final CurrentFeedFragment fragment = getCurrentFeedFragment(); fragment.highlightVisibleSearchResults(positions); fragment.scrollTo(positions.get(mCursor)); return true; } @Override public boolean onPrepareActionMode(final android.view.ActionMode mode, final Menu menu) { final MenuItem previous = menu.findItem(R.id.action_filter_previous); final MenuItem next = menu.findItem(R.id.action_filter_next); final MenuItem skipToStart = menu.findItem(R.id.action_filter_skip_to_start); final MenuItem skipToEnd = menu.findItem(R.id.action_filter_skip_to_end); final int size = positions.size(); if (size == 1) { alterMenuItemAlpha(previous, false); alterMenuItemAlpha(next, false); alterMenuItemAlpha(skipToStart, false); alterMenuItemAlpha(skipToEnd, false); } else if (mCursor == 0) { alterMenuItemAlpha(previous, false); alterMenuItemAlpha(skipToStart, false); if (!next.isEnabled()) { alterMenuItemAlpha(next, true); alterMenuItemAlpha(skipToEnd, true); } } else if (mCursor == size - 1) { alterMenuItemAlpha(next, false); alterMenuItemAlpha(skipToEnd, false); if (!previous.isEnabled()) { alterMenuItemAlpha(previous, true); alterMenuItemAlpha(skipToStart, true); } } else if (!previous.isEnabled()) { alterMenuItemAlpha(previous, true); alterMenuItemAlpha(skipToStart, true); } else if (!next.isEnabled()) { alterMenuItemAlpha(next, true); alterMenuItemAlpha(skipToEnd, true); } mode.setTitle(String.valueOf(mCursor + 1) + ' ' + getString(R.string.of) + ' ' + size); mode.setSubtitle( CurrentFeed.getTitleForEntry(CurrentFeed.getEntries().get(positions.get(mCursor) - 1))); return true; } @Override public boolean onActionItemClicked(final android.view.ActionMode mode, final MenuItem item) { switch (item.getItemId()) { case R.id.action_filter_next: mCursor++; getCurrentFeedFragment().scrollTo(positions.get(mCursor)); mode.invalidate(); return true; case R.id.action_filter_previous: mCursor--; getCurrentFeedFragment().scrollTo(positions.get(mCursor)); mode.invalidate(); return true; case R.id.action_filter_skip_to_start: mCursor = 0; getCurrentFeedFragment().scrollTo(positions.get(mCursor)); mode.invalidate(); return true; case R.id.action_filter_skip_to_end: mCursor = positions.size() - 1; getCurrentFeedFragment().scrollTo(positions.get(mCursor)); mode.invalidate(); return true; default: return false; } } @Override public void onDestroyActionMode(final android.view.ActionMode mode) { setStatusBarColor(TypedValueUtils.resolve(MainActivity.this, R.attr.colorPrimaryDark)); resetCardViewBackground(positions, List.class); final Menu menu = mode.getMenu(); menu.findItem(R.id.action_filter_next).getIcon().setAlpha(ICON_ALPHA_NORMAL); menu.findItem(R.id.action_filter_previous).getIcon().setAlpha(ICON_ALPHA_NORMAL); menu.findItem(R.id.action_filter_skip_to_end).getIcon().setAlpha(ICON_ALPHA_NORMAL); menu.findItem(R.id.action_filter_skip_to_start).getIcon().setAlpha(ICON_ALPHA_NORMAL); mIsCategoriesFilterApplied = false; mSelectedRecyclerViewPositions = null; mActionMode = null; } }); } }