From 1ca23e4a5fcd3e0b7ea2af2e7352d8da668d9930 Mon Sep 17 00:00:00 2001 From: Phillip Hsu Date: Mon, 26 Sep 2016 17:01:05 -0700 Subject: [PATCH] Toolbar changes --- app/build.gradle | 3 + app/src/main/AndroidManifest.xml | 1 + .../com/philliphsu/clock2/BaseActivity.java | 1 - .../com/philliphsu/clock2/MainActivity.java | 268 +++++++----------- .../main/res/drawable/ic_settings_24dp.xml | 9 + app/src/main/res/layout/activity_main.xml | 15 +- app/src/main/res/menu/menu_main.xml | 3 +- 7 files changed, 123 insertions(+), 177 deletions(-) create mode 100644 app/src/main/res/drawable/ic_settings_24dp.xml diff --git a/app/build.gradle b/app/build.gradle index 139271b..98fb09f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -51,6 +51,9 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config } + debug { + applicationIdSuffix ".debug" + } } productFlavors { } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6f24fec..3db3c62 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ diff --git a/app/src/main/java/com/philliphsu/clock2/BaseActivity.java b/app/src/main/java/com/philliphsu/clock2/BaseActivity.java index f898541..45271c1 100644 --- a/app/src/main/java/com/philliphsu/clock2/BaseActivity.java +++ b/app/src/main/java/com/philliphsu/clock2/BaseActivity.java @@ -59,7 +59,6 @@ public abstract class BaseActivity extends AppCompatActivity { if (ab != null) { ab.setDisplayHomeAsUpEnabled(isDisplayHomeUpEnabled()); ab.setDisplayShowTitleEnabled(isDisplayShowTitleEnabled()); - ab.setElevation(getResources().getDimension(R.dimen.appbar_elevation)); } } } diff --git a/app/src/main/java/com/philliphsu/clock2/MainActivity.java b/app/src/main/java/com/philliphsu/clock2/MainActivity.java index 36ca3c0..f2b49b8 100644 --- a/app/src/main/java/com/philliphsu/clock2/MainActivity.java +++ b/app/src/main/java/com/philliphsu/clock2/MainActivity.java @@ -9,10 +9,8 @@ import android.os.PersistableBundle; import android.preference.PreferenceManager; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; -import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.util.Log; import android.util.SparseArray; @@ -40,6 +38,7 @@ public class MainActivity extends BaseActivity { private static final String LAST_TAB = "last_tab"; private static final int DEFAULT_TAB = 0; + private ModifyOffsetOnPageChangeListener mModifyFabPositionListener; /** * The {@link android.support.v4.view.PagerAdapter} that will provide * fragments for each of the sections. We use a @@ -51,25 +50,11 @@ public class MainActivity extends BaseActivity { private SectionsPagerAdapter mSectionsPagerAdapter; private Drawable mAddItemDrawable; -// // For delaying fab.show() on SCROLL_STATE_SETTLING -// private final Handler mHandler = new Handler(); -// -// private boolean mScrollStateDragging; -// private int mPageDragging = -1; // TOneverDO: initial value >= 0 -// private boolean mDraggingPastEndBoundaries; - @Bind(R.id.container) - ViewPager mViewPager; - + ViewPager mViewPager; @Bind(R.id.fab) FloatingActionButton mFab; -// // https://medium.com/@chrisbanes/appcompat-v23-2-age-of-the-vectors-91cbafa87c88#.141274xy8 -// // This is needed to load vector drawables from 23.4.0 -// static { -// AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); -// } - @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -86,7 +71,7 @@ public class MainActivity extends BaseActivity { public void run() { if (mViewPager.getCurrentItem() == mSectionsPagerAdapter.getCount() - 1) { // Restore the FAB's translationX from a previous configuration. - mFab.setTranslationX(mViewPager.getWidth() / -2f + getFabPixelOffsetForXTranslation()); + mFab.setTranslationX(mViewPager.getWidth() / -2f + getFabPixelOffsetForXTranslation(mFab)); } } }); @@ -95,124 +80,7 @@ public class MainActivity extends BaseActivity { // primary sections of the activity. mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); mViewPager.setAdapter(mSectionsPagerAdapter); - mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - /** - * @param position Either the current page position if the offset is increasing, - * or the previous page position if it is decreasing. - * @param positionOffset If increasing from [0, 1), scrolling right and position = currentPagePosition - * If decreasing from (1, 0], scrolling left and position = (currentPagePosition - 1) - */ - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - Log.d(TAG, String.format("pos = %d, posOffset = %f, posOffsetPixels = %d", - position, positionOffset, positionOffsetPixels)); - int pageBeforeLast = mSectionsPagerAdapter.getCount() - 2; - if (position <= pageBeforeLast) { - if (position < pageBeforeLast) { - // When the scrolling is due to tab selection between multiple tabs apart, - // this callback is called for each intermediate page, but each of those pages - // will briefly register a sparsely decreasing range of positionOffsets, always - // from (1, 0). As such, you would notice the FAB to jump back and forth between - // x-positions as each intermediate page is scrolled through. - // This is a visual optimization that ends the translation motion, immediately - // returning the FAB to its target position. - // TODO: The animation visibly skips to the end. We could interpolate - // intermediate x-positions if we cared to smooth it out. - mFab.setTranslationX(0); - } else { - // Initially, the FAB's translationX property is zero because, at its original - // position, it is not translated. setTranslationX() is relative to the view's - // left position, at its original position; this left position is taken to be - // the zero point of the coordinate system relative to this view. As your - // translationX value is increasingly negative, the view is translated left. - // But as translationX is decreasingly negative and down to zero, the view - // is translated right, back to its original position. - float translationX = positionOffsetPixels / -2f; - // NOTE: You MUST scale your own additional pixel offsets by positionOffset, - // or else the FAB will immediately translate by that many pixels, appearing - // to skip/jump. - translationX += positionOffset * getFabPixelOffsetForXTranslation(); - mFab.setTranslationX(translationX); - } - } - } - - @Override - public void onPageSelected(int position) { - Log.d(TAG, "onPageSelected"); - if (position < mSectionsPagerAdapter.getCount() - 1) { - mFab.setImageDrawable(mAddItemDrawable); - } - Fragment f = mSectionsPagerAdapter.getFragment(mViewPager.getCurrentItem()); - // NOTE: This callback is fired after a rotation, right after onStart(). - // Unfortunately, the FragmentManager handling the rotation has yet to - // tell our adapter to re-instantiate the Fragments, so our collection - // of fragments is empty. You MUST keep this check so we don't cause a NPE. - if (f instanceof BaseFragment) { - ((BaseFragment) f).onPageSelected(); - } - } -// @Override -// public void onPageScrollStateChanged(int state) { -// // TODO: This was not sufficient to prevent the user from quickly -// // hitting the fab for the previous page. -// switch (state) { -// case ViewPager.SCROLL_STATE_DRAGGING: -// if (mDraggingPastEndBoundaries) { -// return; -// } -// mScrollStateDragging = true; -// mPageDragging = mViewPager.getCurrentItem(); -// mFab.hide(); -// break; -// case ViewPager.SCROLL_STATE_SETTLING: -// if (!mScrollStateDragging) { -// mFab.hide(); -// } -// mScrollStateDragging = false; -// // getCurrentItem() has changed to the target page we're settling on. -// // 200ms is the same as show/hide animation duration -// int targetPage = mViewPager.getCurrentItem(); -// if (targetPage != 2) { // TODO: Use page constant -// int delay = mPageDragging == targetPage ? 0 : 200; -// mHandler.postDelayed(new Runnable() { -// @Override -// public void run() { -// mFab.show(); -// } -// }, delay); -// } -// mPageDragging = -1; -// break; -// case ViewPager.SCROLL_STATE_IDLE: -// // Nothing -// break; -// } -// } - }); -// mViewPager.setPageTransformer(false, new ViewPager.PageTransformer() { -// @Override -// public void transformPage(View page, float position) { -// Log.d(TAG, "position: " + position); -// // position represents a page's offset from the front-and-center position of 0 (the page -// // that is in full view). Consider pages A, B, C, D. -// // If we are now on page A (position 0), then pages B, C, and D are respectively -// // in positions 1, 2, 3. -// // If we move to the right to page B (now in position 0), then pages A, C, D are -// // respectively in positions -1, 1, 2. -// int currentPage = mViewPager.getCurrentItem(); -// // TODO: Use page constants -// // Page 0 can't move one full page position to the right (i.e. there is no page to -// // the left of page 0 that can adopt the front-and-center position of 0 while page 0 -// // moves to adopt position 1) -// mDraggingPastEndBoundaries = currentPage == 0 && position >= 0f -// // The last page can't move one full page position to the left (i.e. there -// // is no page to the right of the last page that can adopt the front-and-center -// // position of 0 while the last page moves to adopt position -1) -// || currentPage == mSectionsPagerAdapter.getCount() - 1 && position <= 0f; -// Log.d(TAG, "Draggin past end bounds: " + mDraggingPastEndBoundaries); -// } -// }); + this.mModifyFabPositionListener = new ModifyOffsetOnPageChangeListener(mFab, mSectionsPagerAdapter, mViewPager); TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(mViewPager); @@ -225,15 +93,13 @@ public class MainActivity extends BaseActivity { mFab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - Fragment f = mSectionsPagerAdapter.getFragment(mViewPager.getCurrentItem()); + BaseFragment f = mSectionsPagerAdapter.getFragment(mViewPager.getCurrentItem()); if (f instanceof RecyclerViewFragment) { ((RecyclerViewFragment) f).onFabClick(); } } }); - mAddItemDrawable = ContextCompat.getDrawable(this, R.drawable.ic_add_24dp); - final int initialPage = getIntent().getIntExtra(EXTRA_SHOW_PAGE, -1); if (initialPage >= 0 && initialPage <= mSectionsPagerAdapter.getCount() - 1) { // This is so we don't keep it around when the configuration changes. @@ -298,12 +164,9 @@ public class MainActivity extends BaseActivity { // http://stackoverflow.com/a/24303360/5055032 super.onActivityResult(requestCode, resultCode, data); - switch (requestCode) { - case REQUEST_THEME_CHANGE: - if (data != null && data.getBooleanExtra(SettingsActivity.EXTRA_THEME_CHANGED, false)) { - recreate(); - } - break; + if (requestCode == REQUEST_THEME_CHANGE + && data != null && data.getBooleanExtra(SettingsActivity.EXTRA_THEME_CHANGED, false)) { + recreate(); } } @@ -319,6 +182,18 @@ public class MainActivity extends BaseActivity { restoreTab(savedInstanceState, DEFAULT_TAB); } + @Override + protected void onStart() { + super.onStart(); + mViewPager.addOnPageChangeListener(mModifyFabPositionListener); + } + + @Override + protected void onStop() { + super.onStop(); + mViewPager.removeOnPageChangeListener(mModifyFabPositionListener); + } + @SuppressLint("CommitPrefEdits") @Override protected void onDestroy() { @@ -329,6 +204,7 @@ public class MainActivity extends BaseActivity { .commit(); super.onDestroy(); + this.mModifyFabPositionListener = null; } @Override @@ -367,11 +243,11 @@ public class MainActivity extends BaseActivity { * relative to its center position. An X-translation normally is done relative to a view's * left position. */ - private float getFabPixelOffsetForXTranslation() { + private static float getFabPixelOffsetForXTranslation(FloatingActionButton fab) { final int margin; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Since each side's margin is the same, any side's would do. - margin = ((ViewGroup.MarginLayoutParams) mFab.getLayoutParams()).rightMargin; + margin = ((ViewGroup.MarginLayoutParams) fab.getLayoutParams()).rightMargin; } else { // Pre-Lollipop has measurement issues with FAB margins. This is // probably as good as we can get to centering the FAB, without @@ -381,7 +257,7 @@ public class MainActivity extends BaseActivity { // X-translation is done relative to a view's left position; by adding // an offset of half the FAB's width, we effectively rebase the translation // relative to the view's center position. - return mFab.getWidth() / 2f + margin; + return fab.getWidth() / 2f + margin; } /** @@ -392,14 +268,14 @@ public class MainActivity extends BaseActivity { // We can't use an ArrayList because the structure reorganizes as elements are removed, // so page indices won't stay in sync with list indices. SparseArray allows you to have // gaps in your range of indices. - private final SparseArray mFragments = new SparseArray<>(getCount()); + private final SparseArray mFragments = new SparseArray<>(getCount()); - public SectionsPagerAdapter(FragmentManager fm) { + private SectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override - public Fragment getItem(int position) { + public BaseFragment getItem(int position) { // getItem is called to instantiate the fragment for the given page. switch (position) { case PAGE_ALARMS: @@ -415,7 +291,7 @@ public class MainActivity extends BaseActivity { @Override public Object instantiateItem(ViewGroup container, int position) { - Fragment fragment = (Fragment) super.instantiateItem(container, position); + BaseFragment fragment = (BaseFragment) super.instantiateItem(container, position); mFragments.put(position, fragment); return fragment; } @@ -432,22 +308,80 @@ public class MainActivity extends BaseActivity { return 3; } - // TODO: If you wish to have text labels for your tabs, then implement this method. -// @Override -// public CharSequence getPageTitle(int position) { -// switch (position) { -// case 0: -// return "SECTION 1"; -// case 1: -// return "SECTION 2"; -// case 2: -// return "SECTION 3"; -// } -// return null; -// } - - public Fragment getFragment(int position) { + BaseFragment getFragment(int position) { return mFragments.get(position); } } + + private static final class ModifyOffsetOnPageChangeListener extends ViewPager.SimpleOnPageChangeListener { + + private final FloatingActionButton mFab; + private final SectionsPagerAdapter mSectionsPagerAdapter; + private final ViewPager mViewPager; + + private ModifyOffsetOnPageChangeListener(final FloatingActionButton mFab, + final SectionsPagerAdapter mSectionsPagerAdapter, + final ViewPager mViewPager) { + this.mFab = mFab; + this.mSectionsPagerAdapter = mSectionsPagerAdapter; + this.mViewPager = mViewPager; + } + + /** + * @param position Either the current page position if the offset is increasing, + * or the previous page position if it is decreasing. + * @param positionOffset If increasing from [0, 1), scrolling right and position = currentPagePosition + * If decreasing from (1, 0], scrolling left and position = (currentPagePosition - 1) + */ + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + Log.d(TAG, String.format("pos = %d, posOffset = %f, posOffsetPixels = %d", + position, positionOffset, positionOffsetPixels)); + int pageBeforeLast = mSectionsPagerAdapter.getCount() - 2; + if (position <= pageBeforeLast) { + if (position < pageBeforeLast) { + // When the scrolling is due to tab selection between multiple tabs apart, + // this callback is called for each intermediate page, but each of those pages + // will briefly register a sparsely decreasing range of positionOffsets, always + // from (1, 0). As such, you would notice the FAB to jump back and forth between + // x-positions as each intermediate page is scrolled through. + // This is a visual optimization that ends the translation motion, immediately + // returning the FAB to its target position. + // TODO: The animation visibly skips to the end. We could interpolate + // intermediate x-positions if we cared to smooth it out. + mFab.setTranslationX(0); + } else { + // Initially, the FAB's translationX property is zero because, at its original + // position, it is not translated. setTranslationX() is relative to the view's + // left position, at its original position; this left position is taken to be + // the zero point of the coordinate system relative to this view. As your + // translationX value is increasingly negative, the view is translated left. + // But as translationX is decreasingly negative and down to zero, the view + // is translated right, back to its original position. + float translationX = positionOffsetPixels / -2f; + // NOTE: You MUST scale your own additional pixel offsets by positionOffset, + // or else the FAB will immediately translate by that many pixels, appearing + // to skip/jump. + translationX += positionOffset * getFabPixelOffsetForXTranslation(mFab); + mFab.setTranslationX(translationX); + } + } + } + + @Override + public void onPageSelected(int position) { + Log.d(TAG, "onPageSelected"); + if (position < mSectionsPagerAdapter.getCount() - 1) { + mFab.setImageResource(R.drawable.ic_add_24dp); + } + BaseFragment f = mSectionsPagerAdapter.getFragment(mViewPager.getCurrentItem()); + // NOTE: This callback is fired after a rotation, right after onStart(). + // Unfortunately, the FragmentManager handling the rotation has yet to + // tell our adapter to re-instantiate the Fragments, so our collection + // of fragments is empty. You MUST keep this check so we don't cause a NPE. + if (f != null) { + f.onPageSelected(); + } + } + } } diff --git a/app/src/main/res/drawable/ic_settings_24dp.xml b/app/src/main/res/drawable/ic_settings_24dp.xml new file mode 100644 index 0000000..b40b68f --- /dev/null +++ b/app/src/main/res/drawable/ic_settings_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index da17cb6..aff3466 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,13 +1,13 @@ + tools:context="com.philliphsu.clock2.MainActivity"> + app:popupTheme="?themedPopupOverlay"> + app:tabMode="scrollable"/> @@ -44,8 +43,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" - app:srcCompat="@drawable/ic_add_24dp" android:layout_margin="@dimen/fab_margin" - android:tint="@android:color/white"/> + android:tint="@android:color/white" + app:srcCompat="@drawable/ic_add_24dp"/> diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index 9242898..ee557b3 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -6,5 +6,6 @@ android:id="@+id/action_settings" android:orderInCategory="100" android:title="@string/action_settings" - app:showAsAction="never"/> + android:icon="@drawable/ic_settings_24dp" + app:showAsAction="always"/>