This commit is contained in:
Phillip Hsu 2016-08-15 15:28:18 -07:00
parent b1f3c9c8c7
commit a7861a04c1
14 changed files with 170 additions and 32 deletions

View File

@ -1,14 +1,15 @@
package com.philliphsu.clock2;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
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.SparseArray;
import android.view.LayoutInflater;
@ -36,13 +37,14 @@ public class MainActivity extends BaseActivity {
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
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;
// // 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;
@ -81,6 +83,8 @@ public class MainActivity extends BaseActivity {
// 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
@ -116,8 +120,7 @@ public class MainActivity extends BaseActivity {
@Override
public void onPageSelected(int position) {
if (position < mSectionsPagerAdapter.getCount() - 1) {
// TODO: Plus icon. Consider caching the Drawable in a member variable.
mFab.setImageResource(android.R.drawable.ic_dialog_email);
mFab.setImageDrawable(mAddItemDrawable);
}
}
// @Override
@ -184,6 +187,10 @@ public class MainActivity extends BaseActivity {
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
// Using the resources is fine since tab icons will never change once they are set.
tabLayout.getTabAt(0).setIcon(R.drawable.ic_alarm_24dp);
tabLayout.getTabAt(1).setIcon(R.drawable.ic_timer_24dp);
tabLayout.getTabAt(2).setIcon(R.drawable.ic_stopwatch_24dp);
// TODO: @OnCLick instead.
mFab.setOnClickListener(new View.OnClickListener() {
@ -203,6 +210,8 @@ public class MainActivity extends BaseActivity {
}
}
});
mAddItemDrawable = ContextCompat.getDrawable(this, R.drawable.ic_add_24dp);
}
@Override
@ -319,18 +328,19 @@ public class MainActivity extends BaseActivity {
return 3;
}
@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;
}
// 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) {
return mFragments.get(position);

View File

@ -1,3 +1,19 @@
/*
* Copyright (C) 2008 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.
*/
package com.philliphsu.clock2.stopwatch;
import android.annotation.TargetApi;

View File

@ -2,11 +2,13 @@ package com.philliphsu.clock2.stopwatch;
import android.animation.ObjectAnimator;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.LayoutInflater;
@ -45,6 +47,8 @@ public class StopwatchFragment extends RecyclerViewFragment<
private ObjectAnimator mProgressAnimator;
private SharedPreferences mPrefs;
private WeakReference<FloatingActionButton> mActivityFab;
private Drawable mStartDrawable;
private Drawable mPauseDrawable;
@Bind(R.id.chronometer) ChronometerWithMillis mChronometer;
@Bind(R.id.new_lap) FloatingActionButton mNewLapButton;
@ -65,8 +69,13 @@ public class StopwatchFragment extends RecyclerViewFragment<
mPauseTime = mPrefs.getLong(KEY_PAUSE_TIME, 0);
Log.d(TAG, "mStartTime = " + mStartTime
+ ", mPauseTime = " + mPauseTime);
// TODO: Will these be kept alive after onDestroyView()? If not, we should move these to
// onCreateView() or any other callback that is guaranteed to be called.
mStartDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_start_24dp);
mPauseDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_pause_24dp);
}
// TODO: Restore progress bar animator on rotate
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -88,12 +97,25 @@ public class StopwatchFragment extends RecyclerViewFragment<
if (mPrefs.getBoolean(KEY_CHRONOMETER_RUNNING, false)) {
mChronometer.start();
}
// Hides the mini fabs prematurely, so when we actually select this tab
// they don't show at all before hiding.
// Hides the mini fabs prematurely, so when we actually display this tab
// they won't show even briefly at all before hiding.
updateButtonControls();
return view;
}
@Override
public void onResume() {
super.onResume();
// FAB icon change won't happen when selecting this tab from multiple tabs away,
// because isResumed() and isVisible() both return false, respectively from
// setUserVisibleHint() and from updateButtonControls() when called by onCreateView().
// TODO: Since this is only called to change the FAB icon, just allow duplicate
// code and manipulate the FAB directly.
// TODO: This has the side effect of prematurely changing the icon for the
// page directly before this page.
updateButtonControls();
}
/**
* If the user navigates away, this is the furthest point in the lifecycle
* this Fragment gets to. Here, the view hierarchy returned from onCreateView()
@ -199,6 +221,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
// We will get called again when we actually have this page selected, and by that time
// onCreateView() will have been called. Wait until we're resumed to call through.
if (isVisibleToUser && isResumed()) {
Log.d(TAG, "setUserVisibleHint called thru");
// At this point, the only thing this does is change the fab icon
// TODO: allow duplicate code and manipulate the fab icon directly?
// TODO: There is noticeable latency between showing this tab and
@ -274,8 +297,8 @@ public class StopwatchFragment extends RecyclerViewFragment<
mNewLapButton.setVisibility(vis);
mStopButton.setVisibility(vis);
if (isVisible()) { // avoid changing the icon prematurely, esp. when we're not on this tab
// TODO: pause and start icon, resp.
mActivityFab.get().setImageResource(mChronometer.isRunning() ? 0 : 0);
Log.d(TAG, "Fab icon changing");
mActivityFab.get().setImageDrawable(mChronometer.isRunning() ? mPauseDrawable : mStartDrawable);
}
}

View File

@ -1,3 +1,19 @@
/*
* Copyright (C) 2008 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.
*/
package com.philliphsu.clock2.timers;
import android.annotation.TargetApi;

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M22,5.72l-4.6,-3.86 -1.29,1.53 4.6,3.86L22,5.72zM7.88,3.39L6.6,1.86 2,5.71l1.29,1.53 4.59,-3.85zM12.5,8H11v6l4.75,2.85 0.75,-1.23 -4,-2.37V8zM12,4c-4.97,0 -9,4.03 -9,9s4.02,9 9,9c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zm0,16c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7L11,7v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M6,19h4V5H6v14zm8,-14v14h4V5h-4z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M8,5v14l11,-7z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M6,6h12v12H6z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M15,1H9v2h6V1zm-4,13h2V8h-2v6zm8.03,-6.61l1.42,-1.42c-0.43,-0.51 -0.9,-0.99 -1.41,-1.41l-1.42,1.42C16.07,4.74 14.12,4 12,4c-4.97,0 -9,4.03 -9,9s4.02,9 9,9 9,-4.03 9,-9c0,-2.12 -0.74,-4.07 -1.97,-5.61zM12,20c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M11,17c0,0.55 0.45,1 1,1s1,-0.45 1,-1 -0.45,-1 -1,-1 -1,0.45 -1,1zm0,-14v4h2V5.08c3.39,0.49 6,3.39 6,6.92 0,3.87 -3.13,7 -7,7s-7,-3.13 -7,-7c0,-1.68 0.59,-3.22 1.58,-4.42L12,13l1.41,-1.41 -6.8,-6.8v0.02C4.42,6.45 3,9.05 3,12c0,4.97 4.02,9 9,9 4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9h-1zm7,9c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1 0.45,1 1,1 1,-0.45 1,-1zM6,12c0,0.55 0.45,1 1,1s1,-0.45 1,-1 -0.45,-1 -1,-1 -1,0.45 -1,1z"/>
</vector>

View File

@ -43,7 +43,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:src="@android:drawable/ic_dialog_email"
android:layout_margin="@dimen/fab_margin"/>
android:src="@drawable/ic_add_24dp"
android:layout_margin="@dimen/fab_margin"
android:tint="@android:color/white"/>
</android.support.design.widget.CoordinatorLayout>

View File

@ -45,22 +45,22 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_half_day_1_black_24dp"
android:tint="@android:color/darker_gray"
android:tint="@android:color/white"
app:layout_columnWeight="1"
app:layout_gravity="center"
app:fabSize="mini"
app:backgroundTint="@android:color/white"/>
app:backgroundTint="@color/colorPrimary"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_half_day_1_black_24dp"
android:tint="@android:color/darker_gray"
android:src="@drawable/ic_stop_24dp"
android:tint="@android:color/white"
app:layout_columnWeight="1"
app:layout_gravity="center"
app:fabSize="mini"
app:backgroundTint="@android:color/white"/>
app:backgroundTint="@color/colorPrimary"/>
</android.support.v7.widget.GridLayout>