diff options
author | Michael W <baddaemon87@gmail.com> | 2020-06-07 14:12:38 +0200 |
---|---|---|
committer | Michael Bestas <mkbestas@lineageos.org> | 2020-12-08 19:39:12 +0200 |
commit | 248c6793c4892b8444d64e89c221533270b2946a (patch) | |
tree | 72ede7dc1bd3a42f0ac4d86160eb740a52a88600 | |
parent | 7829e74d9028bda24f05ff93ca5b14ef9b9a0dba (diff) |
DeskClock: Move navigation bar to bottom
* Wrap the desk_clock layout into a LinearLayout so the Snackbar
appears above the BottomNavigationView
* Change the icon tint and text color to reflect the changes for the dark
layout
* Use a BottomNavigationView instead of a TabLayout
* Reorder imports - looks like someone didn't care before
Co-authored-by: Arian <arian.kulmer@web.de>
Co-authored-by: Jesse Chan <jc@lineageos.org>
Signed-off-by: Jesse Chan <jc@lineageos.org>
Change-Id: I780713dcbeb58256b2660a9631d48e5f7259fb11
-rw-r--r-- | res/color/tab_tint_color.xml | 8 | ||||
-rw-r--r-- | res/layout/desk_clock.xml | 161 | ||||
-rw-r--r-- | res/layout/tab_item.xml | 26 | ||||
-rw-r--r-- | res/menu/bottom_navigation_menu.xml | 23 | ||||
-rw-r--r-- | res/values-night/colors.xml | 1 | ||||
-rw-r--r-- | res/values/colors.xml | 2 | ||||
-rw-r--r-- | res/values/styles.xml | 4 | ||||
-rw-r--r-- | src/com/android/deskclock/DeskClock.java | 130 | ||||
-rw-r--r-- | src/com/android/deskclock/uidata/UiDataModel.java | 18 |
9 files changed, 170 insertions, 203 deletions
diff --git a/res/color/tab_tint_color.xml b/res/color/tab_tint_color.xml index 912a9fe6a..3814e506f 100644 --- a/res/color/tab_tint_color.xml +++ b/res/color/tab_tint_color.xml @@ -15,7 +15,7 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_focused="true" android:color="@color/white" /> - <item android:state_selected="true" android:color="@color/white" /> - <item android:color="@color/white_63p" /> -</selector>
\ No newline at end of file + <item android:state_focused="true" android:color="@color/accent_color" /> + <item android:state_selected="true" android:color="@color/accent_color" /> + <item android:color="@color/white_50p" /> +</selector> diff --git a/res/layout/desk_clock.xml b/res/layout/desk_clock.xml index d25e4f628..76ea224c3 100644 --- a/res/layout/desk_clock.xml +++ b/res/layout/desk_clock.xml @@ -15,117 +15,118 @@ limitations under the License. --> -<androidx.coordinatorlayout.widget.CoordinatorLayout +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" - android:fitsSystemWindows="true" - app:statusBarBackground="@null"> + android:orientation="vertical" + app:statusBarBackground="@null" + android:fitsSystemWindows="true"> - <com.google.android.material.appbar.AppBarLayout + <androidx.coordinatorlayout.widget.CoordinatorLayout + android:id="@+id/content" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@null" - app:elevation="0dp"> + android:layout_height="0dp" + android:layout_weight="1"> - <androidx.appcompat.widget.Toolbar - android:id="@+id/toolbar" + <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" - app:contentInsetStart="0dp" - tools:ignore="RtlSymmetry"> + android:background="@null" + app:elevation="0dp"> - <com.google.android.material.tabs.TabLayout - android:id="@+id/tabs" + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar" android:layout_width="match_parent" - android:layout_height="match_parent" - app:tabGravity="fill" - app:tabIndicatorColor="@android:color/transparent" - app:tabMaxWidth="0dp" - app:tabMode="fixed" - app:tabPaddingEnd="0dp" - app:tabPaddingStart="0dp" /> - - </androidx.appcompat.widget.Toolbar> - - <View - android:id="@+id/tab_hairline" - android:layout_width="match_parent" - android:layout_height="@dimen/hairline_height" - android:layout_gravity="bottom" - android:background="@color/hairline" - android:importantForAccessibility="no" /> + android:layout_height="wrap_content" + app:contentInsetStart="0dp" + tools:ignore="RtlSymmetry" + android:gravity="center"> - </com.google.android.material.appbar.AppBarLayout> + <TextView + android:id="@+id/title_view" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" /> - <FrameLayout - android:layout_width="match_parent" - android:layout_height="match_parent" - app:layout_behavior="@string/appbar_scrolling_view_behavior"> + </androidx.appcompat.widget.Toolbar> + </com.google.android.material.appbar.AppBarLayout> <androidx.viewpager.widget.ViewPager android:id="@+id/desk_clock_pager" android:layout_width="match_parent" android:layout_height="match_parent" android:importantForAccessibility="no" - android:saveEnabled="false" /> + android:saveEnabled="false" + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - <include layout="@layout/drop_shadow" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:baselineAligned="false" + android:orientation="horizontal" + app:layout_behavior="com.android.deskclock.widget.toast.SnackbarSlidingBehavior"> - </FrameLayout> + <FrameLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_gravity="start|center_vertical" + android:layout_weight="1"> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="bottom" - android:baselineAligned="false" - android:orientation="horizontal" - app:layout_behavior="com.android.deskclock.widget.toast.SnackbarSlidingBehavior"> + <Button + android:id="@+id/left_button" + style="?attr/borderlessButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:scaleType="centerInside" /> - <FrameLayout - android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_gravity="start|center_vertical" - android:layout_weight="1"> + </FrameLayout> - <Button - android:id="@+id/left_button" - style="?attr/borderlessButtonStyle" + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:scaleType="centerInside" /> + android:layout_margin="@dimen/fab_margin" + app:borderWidth="0dp" + app:elevation="@dimen/fab_elevation" /> - </FrameLayout> + <FrameLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_gravity="end|center_vertical" + android:layout_weight="1"> - <com.google.android.material.floatingactionbutton.FloatingActionButton - android:id="@+id/fab" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:layout_margin="@dimen/fab_margin" - app:borderWidth="0dp" - app:elevation="@dimen/fab_elevation" /> + <Button + android:id="@+id/right_button" + style="?attr/borderlessButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:scaleType="centerInside" /> - <FrameLayout - android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_gravity="end|center_vertical" - android:layout_weight="1"> + </FrameLayout> - <Button - android:id="@+id/right_button" - style="?attr/borderlessButtonStyle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:scaleType="centerInside" /> + </LinearLayout> - </FrameLayout> + </androidx.coordinatorlayout.widget.CoordinatorLayout> - </LinearLayout> - -</androidx.coordinatorlayout.widget.CoordinatorLayout> + <com.google.android.material.bottomnavigation.BottomNavigationView + android:id="@+id/bottom_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/content" + android:background="@color/secondary_color" + app:menu="@menu/bottom_navigation_menu" + app:itemIconTint="@color/tab_tint_color" + app:itemTextColor="@color/tab_tint_color" + app:itemTextAppearanceActive="@style/navText" + app:itemTextAppearanceInactive="@style/navText" + app:labelVisibilityMode="labeled" /> + +</LinearLayout> diff --git a/res/layout/tab_item.xml b/res/layout/tab_item.xml deleted file mode 100644 index 4d8b17c19..000000000 --- a/res/layout/tab_item.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 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. ---> - -<TextView - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@android:id/text1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:drawablePadding="10dp" - android:gravity="center" - android:includeFontPadding="false" - android:singleLine="true" - android:textAppearance="@style/TextAppearance.Tab" /> diff --git a/res/menu/bottom_navigation_menu.xml b/res/menu/bottom_navigation_menu.xml new file mode 100644 index 000000000..1ad8469de --- /dev/null +++ b/res/menu/bottom_navigation_menu.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/page_alarm" + android:enabled="true" + android:icon="@drawable/ic_tab_alarm" + android:title="@string/menu_alarm"/> + <item + android:id="@+id/page_clock" + android:enabled="true" + android:icon="@drawable/ic_tab_clock" + android:title="@string/menu_clock"/> + <item + android:id="@+id/page_timer" + android:enabled="true" + android:icon="@drawable/ic_tab_timer" + android:title="@string/menu_timer"/> + <item + android:id="@+id/page_stopwatch" + android:enabled="true" + android:icon="@drawable/ic_tab_stopwatch" + android:title="@string/menu_stopwatch"/> +</menu> diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml index a555c4981..be5642398 100644 --- a/res/values-night/colors.xml +++ b/res/values-night/colors.xml @@ -18,4 +18,5 @@ <resources> <color name="default_background">#121212</color> <color name="accent_color">#FEF177</color> + <color name="secondary_color">#212121</color> </resources> diff --git a/res/values/colors.xml b/res/values/colors.xml index a6a127480..519b470ba 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -24,6 +24,7 @@ <color name="white">#FFFFFFFF</color> <color name="white_08p">#14FFFFFF</color> <color name="white_63p">#A0FFFFFF</color> + <color name="white_50p">#80FFFFFF</color> <color name="no_alarms">#4CFFFFFF</color> <color name="transparent">#00000000</color> @@ -38,4 +39,5 @@ <color name="widget_shadow_color">#000000</color> <color name="accent_color">#FFEB40</color> + <color name="secondary_color">#2F378A</color> </resources> diff --git a/res/values/styles.xml b/res/values/styles.xml index f247f655b..fbe62ae3a 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -98,8 +98,7 @@ <style name="SecondaryLabelTextAppearance" parent="SecondaryLabelTextParentAppearance" /> - <style name="TextAppearance.Tab" parent="TextAppearance.Design.Tab"> - <item name="android:fontFamily">sans-serif-medium</item> + <style name="navText"> <item name="android:textSize">12sp</item> </style> @@ -133,7 +132,6 @@ <item name="android:headerBackground">@android:color/transparent</item> <item name="android:numbersBackgroundColor">@android:color/transparent</item> <item name="android:numbersSelectorColor">?attr/colorAccent</item> - <item name="android:numbersTextColor">?android:attr/textColorPrimary</item> </style> </resources> diff --git a/src/com/android/deskclock/DeskClock.java b/src/com/android/deskclock/DeskClock.java index 580e31201..cc3687002 100644 --- a/src/com/android/deskclock/DeskClock.java +++ b/src/com/android/deskclock/DeskClock.java @@ -32,6 +32,7 @@ import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.annotation.StringRes; import androidx.appcompat.app.ActionBar; import androidx.appcompat.widget.Toolbar; @@ -53,8 +54,8 @@ import com.android.deskclock.uidata.TabListener; import com.android.deskclock.uidata.UiDataModel; import com.android.deskclock.widget.toast.SnackbarManager; +import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.snackbar.Snackbar; -import com.google.android.material.tabs.TabLayout; import static androidx.viewpager.widget.ViewPager.SCROLL_STATE_DRAGGING; import static androidx.viewpager.widget.ViewPager.SCROLL_STATE_IDLE; @@ -115,17 +116,17 @@ public class DeskClock extends BaseActivity /** The button right of the {@link #mFab} shared across all tabs in the user interface. */ private Button mRightButton; - /** The controller that shows the drop shadow when content is not scrolled to the top. */ - private DropShadowController mDropShadowController; - /** The ViewPager that pages through the fragments representing the content of the tabs. */ private ViewPager mFragmentTabPager; /** Generates the fragments that are displayed by the {@link #mFragmentTabPager}. */ private FragmentTabPagerAdapter mFragmentTabPagerAdapter; - /** The container that stores the tab headers. */ - private TabLayout mTabLayout; + /** The view that displays the current tab's title */ + private TextView mTitleView; + + /** The bottom navigation bar */ + private BottomNavigationView mBottomNavigation; /** {@code true} when a settings change necessitates recreating this activity. */ private boolean mRecreateActivity; @@ -171,43 +172,6 @@ public class DeskClock extends BaseActivity // inflation occurs *after* the initial draw and a second layout pass adds in the menu. onCreateOptionsMenu(toolbar.getMenu()); - // Create the tabs that make up the user interface. - mTabLayout = (TabLayout) findViewById(R.id.tabs); - final int tabCount = UiDataModel.getUiDataModel().getTabCount(); - final boolean showTabLabel = getResources().getBoolean(R.bool.showTabLabel); - final boolean showTabHorizontally = getResources().getBoolean(R.bool.showTabHorizontally); - for (int i = 0; i < tabCount; i++) { - final UiDataModel.Tab tabModel = UiDataModel.getUiDataModel().getTab(i); - final @StringRes int labelResId = tabModel.getLabelResId(); - - final TabLayout.Tab tab = mTabLayout.newTab() - .setTag(tabModel) - .setIcon(tabModel.getIconResId()) - .setContentDescription(labelResId); - - if (showTabLabel) { - tab.setText(labelResId); - tab.setCustomView(R.layout.tab_item); - - @SuppressWarnings("ConstantConditions") - final TextView text = (TextView) tab.getCustomView() - .findViewById(android.R.id.text1); - text.setTextColor(mTabLayout.getTabTextColors()); - - // Bind the icon to the TextView. - final Drawable icon = tab.getIcon(); - if (showTabHorizontally) { - // Remove the icon so it doesn't affect the minimum TabLayout height. - tab.setIcon(null); - text.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null); - } else { - text.setCompoundDrawablesRelativeWithIntrinsicBounds(null, icon, null, null); - } - } - - mTabLayout.addTab(tab); - } - // Configure the buttons shared by the tabs. mFab = (ImageView) findViewById(R.id.fab); mLeftButton = (Button) findViewById(R.id.left_button); @@ -297,24 +261,47 @@ public class DeskClock extends BaseActivity mFragmentTabPager.setAdapter(mFragmentTabPagerAdapter); // Mirror changes made to the selected tab into UiDataModel. - mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { - @Override - public void onTabSelected(TabLayout.Tab tab) { - UiDataModel.getUiDataModel().setSelectedTab((UiDataModel.Tab) tab.getTag()); - } + mBottomNavigation = findViewById(R.id.bottom_view); + mBottomNavigation.setOnNavigationItemSelectedListener(mNavigationListener); - @Override - public void onTabUnselected(TabLayout.Tab tab) { + // Honor changes to the selected tab from outside entities. + UiDataModel.getUiDataModel().addTabListener(mTabChangeWatcher); + + mTitleView = findViewById(R.id.title_view); + } + + private BottomNavigationView.OnNavigationItemSelectedListener mNavigationListener + = new BottomNavigationView.OnNavigationItemSelectedListener() { + + @Override + public boolean onNavigationItemSelected(@NonNull MenuItem item) { + UiDataModel.Tab tab = null; + switch (item.getItemId()) { + case R.id.page_alarm: + tab = UiDataModel.Tab.ALARMS; + break; + + case R.id.page_clock: + tab = UiDataModel.Tab.CLOCKS; + break; + + case R.id.page_timer: + tab = UiDataModel.Tab.TIMERS; + break; + + case R.id.page_stopwatch: + tab = UiDataModel.Tab.STOPWATCH; + break; } - @Override - public void onTabReselected(TabLayout.Tab tab) { + if (tab != null) { + UiDataModel.getUiDataModel().setSelectedTab(tab); + return true; } - }); - // Honor changes to the selected tab from outside entities. - UiDataModel.getUiDataModel().addTabListener(mTabChangeWatcher); - } + return false; + } + }; @Override protected void onStart() { @@ -327,10 +314,6 @@ public class DeskClock extends BaseActivity protected void onResume() { super.onResume(); - final View dropShadow = findViewById(R.id.drop_shadow); - mDropShadowController = new DropShadowController(dropShadow, UiDataModel.getUiDataModel(), - mSnackbarAnchor.findViewById(R.id.tab_hairline)); - // ViewPager does not save state; this honors the selected tab in the user interface. updateCurrentTab(); } @@ -354,16 +337,6 @@ public class DeskClock extends BaseActivity } @Override - public void onPause() { - if (mDropShadowController != null) { - mDropShadowController.stop(); - mDropShadowController = null; - } - - super.onPause(); - } - - @Override protected void onStop() { DataModel.getDataModel().removeSilentSettingsListener(mSilentSettingChangeWatcher); if (!isChangingConfigurations()) { @@ -487,21 +460,14 @@ public class DeskClock extends BaseActivity } /** - * Configure the {@link #mFragmentTabPager} and {@link #mTabLayout} to display UiDataModel's - * selected tab. + * Configure the {@link #mFragmentTabPager} and {@link #mBottomNavigation} to display + * UiDataModel's selected tab. */ private void updateCurrentTab() { // Fetch the selected tab from the source of truth: UiDataModel. final UiDataModel.Tab selectedTab = UiDataModel.getUiDataModel().getSelectedTab(); - - // Update the selected tab in the tablayout if it does not agree with UiDataModel. - for (int i = 0; i < mTabLayout.getTabCount(); i++) { - final TabLayout.Tab tab = mTabLayout.getTabAt(i); - if (tab != null && tab.getTag() == selectedTab && !tab.isSelected()) { - tab.select(); - break; - } - } + // Update the selected tab in the mBottomNavigation if it does not agree with UiDataModel. + mBottomNavigation.setSelectedItemId(selectedTab.getPageResId()); // Update the selected fragment in the viewpager if it does not agree with UiDataModel. for (int i = 0; i < mFragmentTabPagerAdapter.getCount(); i++) { @@ -511,6 +477,8 @@ public class DeskClock extends BaseActivity break; } } + + mTitleView.setText(selectedTab.getLabelResId()); } /** diff --git a/src/com/android/deskclock/uidata/UiDataModel.java b/src/com/android/deskclock/uidata/UiDataModel.java index f7a691756..3d592d405 100644 --- a/src/com/android/deskclock/uidata/UiDataModel.java +++ b/src/com/android/deskclock/uidata/UiDataModel.java @@ -19,7 +19,7 @@ package com.android.deskclock.uidata; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Typeface; -import androidx.annotation.DrawableRes; +import androidx.annotation.IntegerRes; import androidx.annotation.StringRes; import com.android.deskclock.AlarmClockFragment; @@ -39,23 +39,23 @@ public final class UiDataModel { /** Identifies each of the primary tabs within the application. */ public enum Tab { - ALARMS(AlarmClockFragment.class, R.drawable.ic_tab_alarm, R.string.menu_alarm), - CLOCKS(ClockFragment.class, R.drawable.ic_tab_clock, R.string.menu_clock), - TIMERS(TimerFragment.class, R.drawable.ic_tab_timer, R.string.menu_timer), - STOPWATCH(StopwatchFragment.class, R.drawable.ic_tab_stopwatch, R.string.menu_stopwatch); + ALARMS(AlarmClockFragment.class, R.id.page_alarm, R.string.menu_alarm), + CLOCKS(ClockFragment.class, R.id.page_clock, R.string.menu_clock), + TIMERS(TimerFragment.class, R.id.page_timer, R.string.menu_timer), + STOPWATCH(StopwatchFragment.class, R.id.page_stopwatch, R.string.menu_stopwatch); private final String mFragmentClassName; - private final @DrawableRes int mIconResId; + private final @IntegerRes int mPageResId; private final @StringRes int mLabelResId; - Tab(Class fragmentClass, @DrawableRes int iconResId, @StringRes int labelResId) { + Tab(Class fragmentClass, @IntegerRes int pageResId, @StringRes int labelResId) { mFragmentClassName = fragmentClass.getName(); - mIconResId = iconResId; + mPageResId = pageResId; mLabelResId = labelResId; } public String getFragmentClassName() { return mFragmentClassName; } - public @DrawableRes int getIconResId() { return mIconResId; } + public @IntegerRes int getPageResId() { return mPageResId; } public @StringRes int getLabelResId() { return mLabelResId; } } |