Merge "City search keyboard now starts in uppercase" into ub-deskclock-fantasy
diff --git a/res/layout-land/clock_fragment.xml b/res/layout-land/clock_fragment.xml
index 05d79ec..78afea0 100644
--- a/res/layout-land/clock_fragment.xml
+++ b/res/layout-land/clock_fragment.xml
@@ -50,7 +50,7 @@
android:layout_weight="32"
android:clickable="false"
android:clipToPadding="false"
- android:paddingBottom="@dimen/medium_space_top" />
+ android:paddingBottom="@dimen/fab_height" />
<!-- Left gutter. -->
<Space
diff --git a/res/layout-land/stopwatch_fragment.xml b/res/layout-land/stopwatch_fragment.xml
index ca87895..cf9754a 100644
--- a/res/layout-land/stopwatch_fragment.xml
+++ b/res/layout-land/stopwatch_fragment.xml
@@ -34,6 +34,7 @@
android:layout_weight="@integer/guttered_content_width_percent"
android:orientation="horizontal">
+ <!-- No circle in the stopwatch_view implies it should consume all remaining width. -->
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
diff --git a/res/layout-sw320dp-land/stopwatch_fragment.xml b/res/layout-sw320dp-land/stopwatch_fragment.xml
new file mode 100644
index 0000000..a1657af
--- /dev/null
+++ b/res/layout-sw320dp-land/stopwatch_fragment.xml
@@ -0,0 +1,73 @@
+<?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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:baselineAligned="false"
+ android:orientation="horizontal">
+
+ <!-- Left gutter. -->
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="@integer/gutter_width_percent" />
+
+ <!-- Guttered content. -->
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="@integer/guttered_content_width_percent"
+ android:orientation="horizontal">
+
+ <!-- A circle in the stopwatch_view implies it should be sized in the remaining area. -->
+ <android.support.percent.PercentFrameLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:paddingBottom="@dimen/fab_height">
+
+ <com.android.deskclock.TimerCircleFrameLayout
+ app:layout_aspectRatio="100%"
+ app:layout_widthPercent="@fraction/timer_circle_width_percent"
+ app:layout_heightPercent="@fraction/timer_circle_height_percent"
+ android:layout_gravity="center">
+
+ <include layout="@layout/stopwatch_view" />
+
+ </com.android.deskclock.TimerCircleFrameLayout>
+
+ </android.support.percent.PercentFrameLayout>
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/laps_list"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:clipToPadding="false"
+ android:paddingBottom="@dimen/fab_height" />
+
+ </LinearLayout>
+
+ <!-- Right gutter. -->
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="@integer/gutter_width_percent" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-sw320dp/timer_item.xml b/res/layout-sw320dp/timer_item.xml
new file mode 100644
index 0000000..bb35498
--- /dev/null
+++ b/res/layout-sw320dp/timer_item.xml
@@ -0,0 +1,86 @@
+<?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.
+-->
+
+<!-- This TimerItem includes the circle because ample space exists. -->
+<com.android.deskclock.timer.TimerItem
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.percent.PercentFrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:layout_gravity="center">
+
+ <com.android.deskclock.TimerCircleFrameLayout
+ app:layout_aspectRatio="100%"
+ app:layout_widthPercent="@fraction/timer_circle_width_percent"
+ app:layout_heightPercent="@fraction/timer_circle_height_percent"
+ android:layout_gravity="center">
+
+ <com.android.deskclock.CircleButtonsLayout
+ android:id="@+id/timer_circle"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.deskclock.timer.TimerCircleView
+ android:id="@+id/timer_time"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <com.android.deskclock.timer.CountingTimerView
+ android:id="@+id/timer_time_text"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <Button
+ android:id="@+id/timer_label"
+ style="?android:attr/borderlessButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:layout_gravity="top|center_horizontal"
+ android:clickable="false"
+ android:ellipsize="end"
+ android:gravity="center"
+ android:hint="@string/label"
+ android:maxLines="1"
+ android:src="@drawable/ic_label"
+ android:textAppearance="@style/SecondaryLabelTextAppearance" />
+
+ <ImageButton
+ android:id="@+id/reset_add"
+ android:layout_width="@dimen/fab_button_size"
+ android:layout_height="@dimen/fab_button_size"
+ android:layout_gravity="bottom|center_horizontal"
+ android:contentDescription="@string/timer_plus_one"
+ android:gravity="center"
+ android:scaleType="center"
+ android:src="@drawable/ic_plusone" />
+
+ </com.android.deskclock.CircleButtonsLayout>
+
+ </com.android.deskclock.TimerCircleFrameLayout>
+
+ </android.support.percent.PercentFrameLayout>
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/fab_height" />
+
+</com.android.deskclock.timer.TimerItem>
\ No newline at end of file
diff --git a/res/layout/expired_timers_activity.xml b/res/layout/expired_timers_activity.xml
index 0bd487e..34ef57e 100644
--- a/res/layout/expired_timers_activity.xml
+++ b/res/layout/expired_timers_activity.xml
@@ -33,8 +33,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
- android:orientation="vertical"
- android:paddingTop="?attr/actionBarSize" />
+ android:orientation="vertical" />
+
</ScrollView>
<android.support.design.widget.FloatingActionButton
@@ -47,4 +47,5 @@
android:src="@drawable/ic_stop_white_24dp"
app:borderWidth="0dp"
app:elevation="@dimen/fab_elevation" />
+
</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/stopwatch_fragment.xml b/res/layout/stopwatch_fragment.xml
index 0be82f1..59c0b52 100644
--- a/res/layout/stopwatch_fragment.xml
+++ b/res/layout/stopwatch_fragment.xml
@@ -28,14 +28,15 @@
android:layout_height="wrap_content"
android:layout_gravity="center">
- <FrameLayout
- android:layout_gravity="center"
+ <com.android.deskclock.TimerCircleFrameLayout
app:layout_aspectRatio="100%"
- app:layout_widthPercent="60%">
+ app:layout_widthPercent="@fraction/timer_circle_width_percent"
+ app:layout_heightPercent="@fraction/timer_circle_height_percent"
+ android:layout_gravity="center">
<include layout="@layout/stopwatch_view" />
- </FrameLayout>
+ </com.android.deskclock.TimerCircleFrameLayout>
</android.support.percent.PercentFrameLayout>
diff --git a/res/layout/timer_fragment.xml b/res/layout/timer_fragment.xml
index a297dc5..a34d956 100644
--- a/res/layout/timer_fragment.xml
+++ b/res/layout/timer_fragment.xml
@@ -25,42 +25,49 @@
android:layout_height="match_parent">
<LinearLayout
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_gravity="end|center_vertical"
- android:layout_marginEnd="24dp"
- android:gravity="center"
- android:orientation="vertical">
+ android:layout_marginBottom="@dimen/fab_height"
+ android:orientation="horizontal">
- <ImageView
- android:id="@+id/page_indicator0"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null" />
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="96"
+ android:gravity="center_vertical|end"
+ android:orientation="vertical">
- <ImageView
- android:id="@+id/page_indicator1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null" />
+ <ImageView
+ android:id="@+id/page_indicator0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null" />
- <ImageView
- android:id="@+id/page_indicator2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null" />
+ <ImageView
+ android:id="@+id/page_indicator1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null" />
- <ImageView
- android:id="@+id/page_indicator3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null" />
+ <ImageView
+ android:id="@+id/page_indicator2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null" />
+ <ImageView
+ android:id="@+id/page_indicator3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null" />
+
+ </LinearLayout>
+
+ <!-- Right gutter. -->
<Space
- android:layout_width="match_parent"
- android:layout_height="@dimen/footer_button_size"
- android:layout_marginBottom="16dp"
- android:layout_marginTop="16dp" />
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="@integer/gutter_width_percent" />
</LinearLayout>
diff --git a/res/layout/timer_item.xml b/res/layout/timer_item.xml
index 6c0a277..6440f18 100644
--- a/res/layout/timer_item.xml
+++ b/res/layout/timer_item.xml
@@ -14,37 +14,28 @@
limitations under the License.
-->
+<!-- This TimerItem discards the circle because space is limited. -->
<com.android.deskclock.timer.TimerItem
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center_vertical"
- android:orientation="vertical"
- android:paddingBottom="@dimen/timer_list_padding_bottom">
+ android:layout_height="match_parent"
+ android:orientation="vertical">
- <com.android.deskclock.CircleButtonsLayout
- android:id="@+id/timer_circle"
- android:layout_width="@dimen/circle_size"
- android:layout_height="@dimen/circle_size"
- android:layout_gravity="center"
- android:padding="@dimen/timer_padding">
-
- <com.android.deskclock.timer.TimerCircleView
- android:id="@+id/timer_time"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
<com.android.deskclock.timer.CountingTimerView
android:id="@+id/timer_time_text"
android:layout_width="match_parent"
- android:layout_height="match_parent"/>
+ android:layout_height="match_parent" />
<Button
android:id="@+id/timer_label"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
- android:layout_height="56dp"
+ android:layout_height="40dp"
android:layout_gravity="top|center_horizontal"
android:clickable="false"
android:ellipsize="end"
@@ -52,18 +43,22 @@
android:hint="@string/label"
android:maxLines="1"
android:src="@drawable/ic_label"
- android:textAppearance="@style/SecondaryLabelTextAppearance"/>
+ android:textAppearance="@style/SecondaryLabelTextAppearance" />
<ImageButton
android:id="@+id/reset_add"
- android:layout_width="50dp"
- android:layout_height="50dp"
+ android:layout_width="@dimen/fab_button_size"
+ android:layout_height="@dimen/fab_button_size"
android:layout_gravity="bottom|center_horizontal"
android:contentDescription="@string/timer_plus_one"
android:gravity="center"
android:scaleType="center"
- android:src="@drawable/ic_plusone"/>
+ android:src="@drawable/ic_plusone" />
- </com.android.deskclock.CircleButtonsLayout>
+ </FrameLayout>
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/fab_height" />
</com.android.deskclock.timer.TimerItem>
\ No newline at end of file
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index bbec0e7..2533246 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -22,27 +22,18 @@
<dimen name="date_text_size">15sp</dimen>
<dimen name="next_alarm_text_size">15sp</dimen>
<dimen name="time_margin_top">24dip</dimen>
- <dimen name="timer_list_padding_bottom">80dip</dimen>
<dimen name="dialpad_font_size">24sp</dimen>
<dimen name="dialpad_digit_padding">14dip</dimen>
<dimen name="timer_setup_delete_margin">12sp</dimen>
- <dimen name="timer_setup_label_size">16sp</dimen>
<dimen name="actionbar_tab_padding">32dip</dimen>
<!-- Size of margin for circles. -->
- <dimen name="circle_margin">8dp</dimen>
<dimen name="analog_clock_margin">70dp</dimen>
- <dimen name="main_clock_padding">0dp</dimen>
<dimen name="circle_margin_top">0dp</dimen>
- <dimen name="top_text_spacing_digital">-25dp</dimen>
<dimen name="bottom_text_spacing_analog">5dp</dimen>
<dimen name="medium_font_size">48sp</dimen>
- <dimen name="circle_size">190dip</dimen>
-
- <dimen name="alarm_alert_clock_padding_left">32dp</dimen>
-
</resources>
\ No newline at end of file
diff --git a/res/layout/blank_footer_view.xml b/res/values-land/fractions.xml
similarity index 60%
copy from res/layout/blank_footer_view.xml
copy to res/values-land/fractions.xml
index c9460fc..4642e0e 100644
--- a/res/layout/blank_footer_view.xml
+++ b/res/values-land/fractions.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- 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.
@@ -13,7 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:background="@color/transparent"
- android:layout_height="@dimen/button_footer_height" />
\ No newline at end of file
+
+<resources>
+ <!-- In landscape, -100% width implies only height is used to size the timer container. -->
+ <fraction name="timer_circle_width_percent">-100%</fraction>
+
+ <!-- In landscape, timer circles are 90% of the container height; width matches height. -->
+ <fraction name="timer_circle_height_percent">90%</fraction>
+</resources>
\ No newline at end of file
diff --git a/res/layout/blank_footer_view.xml b/res/values-sw320dp/dimens.xml
similarity index 69%
rename from res/layout/blank_footer_view.xml
rename to res/values-sw320dp/dimens.xml
index c9460fc..d64c205 100644
--- a/res/layout/blank_footer_view.xml
+++ b/res/values-sw320dp/dimens.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- 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.
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:background="@color/transparent"
- android:layout_height="@dimen/button_footer_height" />
\ No newline at end of file
+
+<resources>
+ <dimen name="big_font_size">60sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-sw360dp-land/dimens.xml b/res/values-sw360dp-land/dimens.xml
index 0275592..1ff913a 100644
--- a/res/values-sw360dp-land/dimens.xml
+++ b/res/values-sw360dp-land/dimens.xml
@@ -20,6 +20,5 @@
for different hardware and product builds.
-->
<resources>
- <dimen name="circle_size">232dip</dimen>
<dimen name="timer_setup_font_size">48sp</dimen>
</resources>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
index 06650e6..1c26c0f 100644
--- a/res/values-sw600dp-land/dimens.xml
+++ b/res/values-sw600dp-land/dimens.xml
@@ -28,15 +28,11 @@
<dimen name="timer_setup_font_size">78sp</dimen>
<dimen name="timer_setup_button_size">36sp</dimen>
<dimen name="timer_setup_delete_margin">19sp</dimen>
- <dimen name="timer_setup_label_size">24sp</dimen>
<!-- Size of margin for circles. -->
<dimen name="circle_margin_top">0dp</dimen>
- <dimen name="circle_margin">48dp</dimen>
<dimen name="analog_clock_margin">48dp</dimen>
- <dimen name="circle_size">360dip</dimen>
-
<!-- The maximum size of the font for the time in widgets. -->
<dimen name="widget_max_clock_font_size">100dp</dimen>
</resources>
\ No newline at end of file
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index dbe9e1d..67ac240 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -23,7 +23,6 @@
<dimen name="date_text_size">15sp</dimen>
<dimen name="next_alarm_text_size">15sp</dimen>
<dimen name="time_margin_top">48dip</dimen>
- <dimen name="timer_list_padding_bottom">112dip</dimen>
<dimen name="screensaver_margin">20dip</dimen>
<dimen name="alarm_label_padding">64dip</dimen>
<dimen name="bottom_text_size">18sp</dimen>
@@ -47,7 +46,6 @@
<dimen name="small_space">32dp</dimen>
<dimen name="medium_space_top">46dp</dimen>
<dimen name="medium_space_bottom">18dp</dimen>
- <dimen name="main_clock_padding">40dp</dimen>
<dimen name="label_margin_big">8dp</dimen>
<dimen name="label_margin_small">4dp</dimen>
@@ -57,15 +55,11 @@
<dimen name="timer_setup_font_size">86sp</dimen>
<dimen name="timer_setup_button_size">36sp</dimen>
<dimen name="timer_setup_delete_margin">21sp</dimen>
- <dimen name="timer_setup_label_size">28sp</dimen>
<!-- Size of margin for circles. -->
<dimen name="circle_margin_top">48dp</dimen>
- <dimen name="circle_margin">96dp</dimen>
<dimen name="analog_clock_margin">96dp</dimen>
- <dimen name="circle_size">400dp</dimen>
-
<!-- Width of the clock, for use with alarm buttons. -->
<dimen name="alarm_alert_display_width">550dip</dimen>
@@ -85,6 +79,4 @@
<dimen name="city_widget_name_font_size">20dp</dimen>
<!-- The maximum size of the font for the time in widgets. -->
<dimen name="widget_max_clock_font_size">125dp</dimen>
-
- <dimen name="footer_button_size">80dip</dimen>
</resources>
\ No newline at end of file
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
index f2d557f..d3046f2 100644
--- a/res/values-sw720dp-land/dimens.xml
+++ b/res/values-sw720dp-land/dimens.xml
@@ -18,13 +18,10 @@
for different hardware and product builds. -->
<resources>
- <dimen name="alarm_alert_clock_padding_left">128dp</dimen>
-
<dimen name="dialpad_font_size">42sp</dimen>
<dimen name="dialpad_digit_padding">26dip</dimen>
<dimen name="timer_setup_font_size">78sp</dimen>
<dimen name="timer_setup_button_size">36sp</dimen>
<dimen name="timer_setup_delete_margin">19sp</dimen>
- <dimen name="timer_setup_label_size">24sp</dimen>
</resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index bf80208..41864eb 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -21,8 +21,6 @@
<dimen name="label_edittext_padding">21dp</dimen>
<dimen name="time_margin_top">32dip</dimen>
<dimen name="timer_padding">16dp</dimen>
- <dimen name="timer_list_padding_bottom">88dip</dimen>
- <!-- 88dip + 0.5 of footer_button_size -->
<dimen name="screensaver_margin">16dip</dimen>
<dimen name="alarm_label_padding">8dip</dimen>
<dimen name="bottom_text_spacing_digital">-8dp</dimen>
@@ -36,12 +34,11 @@
<dimen name="actionbar_tab_padding">0dip</dimen>
- <dimen name="footer_button_size">56dip</dimen>
-
- <dimen name="alarm_text_font_size">14sp</dimen>
- <dimen name="circletimer_dot_size">12dip</dimen>
- <dimen name="circletimer_circle_size">4dip</dimen>
- <dimen name="circletimer_marker_size">16dip</dimen>
+ <dimen name="alarm_text_font_size">12sp</dimen>
+ <dimen name="circletimer_dot_size">12dp</dimen>
+ <dimen name="circletimer_circle_size">4dp</dimen>
+ <dimen name="circletimer_marker_size">16dp</dimen>
+ <dimen name="max_timer_circle_size">360dp</dimen>
<dimen name="alarm_lockscreen_alarm_horizontal_padding">16dp</dimen>
<dimen name="alarm_lockscreen_alarm_vertical_padding">48dp</dimen>
@@ -49,7 +46,7 @@
<dimen name="alarm_lockscreen_bottom_margin">40dp</dimen>
<dimen name="main_clock_font_size">64sp</dimen>
- <dimen name="big_font_size">60sp</dimen>
+ <dimen name="big_font_size">32sp</dimen>
<dimen name="medium_font_size">56sp</dimen>
<dimen name="small_font_size">32sp</dimen>
<dimen name="label_font_size">16sp</dimen>
@@ -82,7 +79,6 @@
<!--margin should be ~ half timer_setup_font_size -->
<dimen name="timer_setup_delete_margin">14sp</dimen>
<dimen name="timer_setup_delete_padding">12dp</dimen>
- <dimen name="timer_setup_label_size">18sp</dimen>
<dimen name="cities_list_item_height">56dip</dimen>
@@ -90,8 +86,6 @@
<dimen name="circle_margin_top">16dp</dimen>
<dimen name="analog_clock_margin">60dp</dimen>
- <dimen name="circle_size">280dp</dimen>
-
<!-- The width and height of the notification icon -->
<dimen name="notification_icon_size">64dp</dimen>
<!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
@@ -109,10 +103,6 @@
<!-- Size of digital world clock font in landscape. -->
<dimen name="world_clock_digital_font_size">40sp</dimen>
- <!-- Height of the button footers. 56 height and 16 on top and bottom. -->
- <dimen name="button_footer_height">88dip</dimen>
- <!-- Negative value of the height of the button footers, for use with lightsout. -->
-
<dimen name="min_analog_widget_size">110dp</dimen>
<!-- digital widget sizing information -->
diff --git a/res/layout/blank_footer_view.xml b/res/values/fractions.xml
similarity index 60%
copy from res/layout/blank_footer_view.xml
copy to res/values/fractions.xml
index c9460fc..62c866d 100644
--- a/res/layout/blank_footer_view.xml
+++ b/res/values/fractions.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- 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.
@@ -13,7 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:background="@color/transparent"
- android:layout_height="@dimen/button_footer_height" />
\ No newline at end of file
+
+<resources>
+ <!-- In portrait, -100% height implies only width is used to size the timer container. -->
+ <fraction name="timer_circle_height_percent">-100%</fraction>
+
+ <!-- In portrait, timer circles are 60% of the container width; height matches width. -->
+ <fraction name="timer_circle_width_percent">60%</fraction>
+</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f9a140e..dccf10a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -288,13 +288,19 @@
<!-- Title for ringtones that cannot be located by uri. -->
<string name="unknown_ringtone_title">Unknown</string>
- <!-- Text to display when alarm volume is muted. -->
+ <!-- Text to display when alarm volume is muted. [CHAR LIMIT=50] -->
<string name="alarm_volume_muted">Alarm volume muted</string>
- <!-- Text for action that presents a volume control to adjust alarm volume. -->
+ <!-- Text for action that presents a volume control to adjust alarm volume. [CHAR LIMIT=20] -->
<string name="unmute_alarm_volume">Unmute</string>
- <!-- Text to display when do-not-disturb is blocking alarms. -->
+ <!-- Text to display when system default alarm ringtone is silent. [CHAR LIMIT=50] -->
+ <string name="silent_default_alarm_ringtone">Default alarm ringtone is silent</string>
+
+ <!-- Text for action that shows the UI that changes the default alarm ringtone. [CHAR LIMIT=20] -->
+ <string name="change_default_alarm_ringtone">Change</string>
+
+ <!-- Text to display when do-not-disturb is blocking alarms. [CHAR LIMIT=60] -->
<string name="alarms_blocked_by_dnd">Device is set to total silence</string>
<!-- Title of the setting to change hardware button behavior. This string
diff --git a/src/com/android/deskclock/CircleButtonsLayout.java b/src/com/android/deskclock/CircleButtonsLayout.java
index a00d6cb..1830ef8 100644
--- a/src/com/android/deskclock/CircleButtonsLayout.java
+++ b/src/com/android/deskclock/CircleButtonsLayout.java
@@ -16,9 +16,6 @@
*/
public class CircleButtonsLayout extends FrameLayout {
- private int mCircleTimerViewId;
- private int mResetAddButtonId;
- private int mLabelId;
private float mDiamOffset;
private View mCircleView;
private ImageButton mResetAddButton;
@@ -31,12 +28,6 @@
public CircleButtonsLayout(Context context, AttributeSet attrs) {
super(context, attrs);
- }
-
- public void setCircleTimerViewIds(int circleTimerViewId, int stopButtonId, int labelId) {
- mCircleTimerViewId = circleTimerViewId;
- mResetAddButtonId = stopButtonId;
- mLabelId = labelId;
final Resources res = getContext().getResources();
final float strokeSize = res.getDimension(R.dimen.circletimer_circle_size);
@@ -56,13 +47,10 @@
}
protected void remeasureViews() {
- if (mCircleView == null) {
- mCircleView = findViewById(mCircleTimerViewId);
- if (mCircleView == null) {
- return;
- }
- mResetAddButton = (ImageButton) findViewById(mResetAddButtonId);
- mLabel = (TextView) findViewById(mLabelId);
+ if (mLabel == null) {
+ mCircleView = findViewById(R.id.timer_time);
+ mLabel = (TextView) findViewById(R.id.timer_label);
+ mResetAddButton = (ImageButton) findViewById(R.id.reset_add);
}
final int frameWidth = mCircleView.getMeasuredWidth();
diff --git a/src/com/android/deskclock/ClockFragment.java b/src/com/android/deskclock/ClockFragment.java
index 0a5a714..041e951 100644
--- a/src/com/android/deskclock/ClockFragment.java
+++ b/src/com/android/deskclock/ClockFragment.java
@@ -102,7 +102,6 @@
super.onCreateView(inflater, container, icicle);
final OnTouchListener startScreenSaverListener = new StartScreenSaverListener();
- final View footerView = inflater.inflate(R.layout.blank_footer_view, mCityList, false);
final View fragmentView = inflater.inflate(R.layout.clock_fragment, container, false);
mCityAdapter = new SelectedCitiesAdapter(getActivity());
@@ -110,7 +109,6 @@
mCityList = (ListView) fragmentView.findViewById(R.id.cities);
mCityList.setDivider(null);
mCityList.setAdapter(mCityAdapter);
- mCityList.addFooterView(footerView, null, false);
mCityList.setOnTouchListener(startScreenSaverListener);
mCityList.setOnScrollListener(new VerticalScrollPositionUpdater());
diff --git a/src/com/android/deskclock/DeskClock.java b/src/com/android/deskclock/DeskClock.java
index 7e7fa55..dde040e 100644
--- a/src/com/android/deskclock/DeskClock.java
+++ b/src/com/android/deskclock/DeskClock.java
@@ -26,21 +26,24 @@
import android.app.FragmentManager;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.media.AudioManager;
+import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.provider.Settings;
+import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.design.widget.TabLayout.ViewPagerOnTabSelectedListener;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.content.ContextCompat;
-import android.support.v4.os.BuildCompat;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
@@ -70,7 +73,9 @@
import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
import static android.media.AudioManager.FLAG_SHOW_UI;
import static android.media.AudioManager.STREAM_ALARM;
+import static android.media.RingtoneManager.TYPE_ALARM;
import static android.provider.Settings.System.CONTENT_URI;
+import static android.provider.Settings.System.DEFAULT_ALARM_ALERT_URI;
import static android.support.v4.view.ViewPager.SCROLL_STATE_DRAGGING;
import static android.support.v4.view.ViewPager.SCROLL_STATE_IDLE;
import static android.support.v4.view.ViewPager.SCROLL_STATE_SETTLING;
@@ -115,6 +120,12 @@
/** Updates the user interface to reflect the selected tab from the backing model. */
private final TabListener mTabChangeWatcher = new TabChangeWatcher();
+ /** Displays a snackbar explaining that the system default alarm ringtone is silent. */
+ private final Runnable mShowSilentAlarmSnackbarRunnable = new ShowSilentAlarmSnackbarRunnable();
+
+ /** Observes default alarm ringtone changes while the app is in the foreground. */
+ private final ContentObserver mAlarmRingtoneChangeObserver = new AlarmRingtoneChangeObserver();
+
/** Displays a snackbar explaining that the alarm volume is muted. */
private final Runnable mShowMutedVolumeSnackbarRunnable = new ShowMutedVolumeSnackbarRunnable();
@@ -300,24 +311,28 @@
if (mShowSilencedAlarmsSnackbar) {
if (isDoNotDisturbBlockingAlarms()) {
- // Show the alarms blocked snackbar after a brief delay so it is more noticeable.
mSnackbarAnchor.postDelayed(mShowDNDBlockingSnackbarRunnable, SECOND_IN_MILLIS);
} else if (isAlarmStreamMuted()) {
- // Show the volume muted snackbar after a brief delay so it is more noticeable.
mSnackbarAnchor.postDelayed(mShowMutedVolumeSnackbarRunnable, SECOND_IN_MILLIS);
+ } else if (isSystemAlarmRingtoneSilent()) {
+ mSnackbarAnchor.postDelayed(mShowSilentAlarmSnackbarRunnable, SECOND_IN_MILLIS);
}
}
+ // Subsequent starts of this activity should show the snackbar by default.
+ mShowSilencedAlarmsSnackbar = true;
+
+ final ContentResolver cr = getContentResolver();
+ // Watch for system alarm ringtone changes while the app is in the foreground.
+ cr.registerContentObserver(DEFAULT_ALARM_ALERT_URI, false, mAlarmRingtoneChangeObserver);
+
// Watch for alarm volume changes while the app is in the foreground.
- getContentResolver().registerContentObserver(VOLUME_URI, true, mAlarmVolumeChangeObserver);
+ cr.registerContentObserver(VOLUME_URI, false, mAlarmVolumeChangeObserver);
if (Utils.isMOrLater()) {
// Watch for do-not-disturb changes while the app is in the foreground.
registerReceiver(mDoNotDisturbChangeReceiver, DND_CHANGE_FILTER);
}
-
- // Subsequent starts of this activity should show the snackbar by default.
- mShowSilencedAlarmsSnackbar = true;
}
@Override
@@ -363,6 +378,9 @@
@Override
protected void onStop() {
+ // Stop watching for system alarm ringtone changes while the app is in the background.
+ getContentResolver().unregisterContentObserver(mAlarmRingtoneChangeObserver);
+
// Stop watching for alarm volume changes while the app is in the background.
getContentResolver().unregisterContentObserver(mAlarmVolumeChangeObserver);
@@ -372,6 +390,7 @@
}
// Remove any scheduled work to show snackbars; it is no longer relevant.
+ mSnackbarAnchor.removeCallbacks(mShowSilentAlarmSnackbarRunnable);
mSnackbarAnchor.removeCallbacks(mShowDNDBlockingSnackbarRunnable);
mSnackbarAnchor.removeCallbacks(mShowMutedVolumeSnackbarRunnable);
super.onStop();
@@ -476,6 +495,24 @@
return (DeskClockFragment) mFragmentTabPagerAdapter.getItem(index);
}
+ private boolean isSystemAlarmRingtoneSilent() {
+ return RingtoneManager.getActualDefaultRingtoneUri(this, TYPE_ALARM) == null;
+ }
+
+ private void showSilentRingtoneSnackbar() {
+ final OnClickListener changeClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
+ }
+ };
+
+ SnackbarManager.show(
+ createSnackbar(R.string.silent_default_alarm_ringtone)
+ .setAction(R.string.change_default_alarm_ringtone, changeClickListener)
+ );
+ }
+
private boolean isAlarmStreamMuted() {
return mAudioManager.getStreamVolume(STREAM_ALARM) <= 0;
}
@@ -491,7 +528,7 @@
};
SnackbarManager.show(
- Snackbar.make(mSnackbarAnchor, R.string.alarm_volume_muted, 5000)
+ createSnackbar(R.string.alarm_volume_muted)
.setAction(R.string.unmute_alarm_volume, unmuteClickListener)
);
}
@@ -505,13 +542,20 @@
}
private void showDoNotDisturbIsBlockingAlarmsSnackbar() {
- SnackbarManager.show(Snackbar.make(mSnackbarAnchor, R.string.alarms_blocked_by_dnd, 5000));
+ SnackbarManager.show(createSnackbar(R.string.alarms_blocked_by_dnd));
+ }
+
+ /**
+ * @return a Snackbar that displays the message with the given id for 5 seconds
+ */
+ private Snackbar createSnackbar(@StringRes int messageId) {
+ return Snackbar.make(mSnackbarAnchor, messageId, 5000 /* duration */);
}
/**
* As the view pager changes the selected page, update the model to record the new selected tab.
*/
- private class PageChangeWatcher implements OnPageChangeListener {
+ private final class PageChangeWatcher implements OnPageChangeListener {
/** The last reported page scroll state; used to detect exotic state changes. */
private int mPriorState = SCROLL_STATE_IDLE;
@@ -579,7 +623,7 @@
* If this listener is attached to {@link #mHideAnimation} when it ends, the corresponding
* {@link #mShowAnimation} is automatically started.
*/
- private class AutoStartShowListener extends AnimatorListenerAdapter {
+ private final class AutoStartShowListener extends AnimatorListenerAdapter {
@Override
public void onAnimationEnd(Animator animation) {
// Prepare the hide animation for its next use; by default do not auto-show after hide.
@@ -597,6 +641,17 @@
}
/**
+ * Displays a snackbar that indicates the system default alarm ringtone currently silent and
+ * offers an action that displays the system alarm ringtone setting to adjust it.
+ */
+ private final class ShowSilentAlarmSnackbarRunnable implements Runnable {
+ @Override
+ public void run() {
+ showSilentRingtoneSnackbar();
+ }
+ }
+
+ /**
* Displays a snackbar that indicates the alarm volume is currently muted and offers an action
* that displays the system volume control to adjust it.
*/
@@ -618,6 +673,25 @@
}
/**
+ * Observe changes to the system default alarm ringtone while the application is in the
+ * foreground and show/hide the snackbar that warns when the ringtone is silent.
+ */
+ private final class AlarmRingtoneChangeObserver extends ContentObserver {
+ private AlarmRingtoneChangeObserver() {
+ super(new Handler());
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ if (isSystemAlarmRingtoneSilent()) {
+ showSilentRingtoneSnackbar();
+ } else {
+ SnackbarManager.dismiss();
+ }
+ }
+ }
+
+ /**
* Observe changes to the alarm stream volume while the application is in the foreground and
* show/hide the snackbar that warns when the alarm volume is muted.
*/
@@ -640,7 +714,7 @@
* Observe changes to the do-not-disturb setting while the application is in the foreground
* and show/hide the snackbar that warns when the setting is blocking alarms.
*/
- private class DoNotDisturbChangeReceiver extends BroadcastReceiver {
+ private final class DoNotDisturbChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (isDoNotDisturbBlockingAlarms()) {
@@ -654,7 +728,7 @@
/**
* As the model reports changes to the selected tab, update the user interface.
*/
- private class TabChangeWatcher implements TabListener {
+ private final class TabChangeWatcher implements TabListener {
@Override
public void selectedTabChanged(Tab oldSelectedTab, Tab newSelectedTab) {
final int index = newSelectedTab.ordinal();
@@ -692,7 +766,7 @@
/**
* This adapter produces the DeskClockFragments that are the contents of the tabs.
*/
- private static class TabFragmentAdapter extends FragmentPagerAdapter {
+ private static final class TabFragmentAdapter extends FragmentPagerAdapter {
private final FragmentManager mFragmentManager;
private final Context mContext;
diff --git a/src/com/android/deskclock/TimerCircleFrameLayout.java b/src/com/android/deskclock/TimerCircleFrameLayout.java
new file mode 100644
index 0000000..45bd546
--- /dev/null
+++ b/src/com/android/deskclock/TimerCircleFrameLayout.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package com.android.deskclock;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * A container that frames a timer circle of some sort. The circle is allowed to grow naturally
+ * according to its layout constraints up to the {@link R.dimen#max_timer_circle_size largest}
+ * allowable size.
+ */
+public class TimerCircleFrameLayout extends FrameLayout {
+
+ public TimerCircleFrameLayout(Context context) {
+ super(context);
+ }
+
+ public TimerCircleFrameLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public TimerCircleFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ /**
+ * Note: this method assumes the parent container will specify {@link MeasureSpec#EXACTLY exact}
+ * width and height values.
+ *
+ * @param widthMeasureSpec horizontal space requirements as imposed by the parent
+ * @param heightMeasureSpec vertical space requirements as imposed by the parent
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Fetch the exact sizes imposed by the parent container.
+ final int width = MeasureSpec.getSize(widthMeasureSpec);
+ final int height = MeasureSpec.getSize(heightMeasureSpec);
+ final int smallestDimension = Math.min(width, height);
+
+ // Fetch the absolute maximum circle size allowed.
+ final int maxSize = getResources().getDimensionPixelSize(R.dimen.max_timer_circle_size);
+ final int size = Math.min(smallestDimension, maxSize);
+
+ // Set the size of this container.
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
+
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/deskclock/timer/TimerItem.java b/src/com/android/deskclock/timer/TimerItem.java
index 3f5267e..9bf03c8 100644
--- a/src/com/android/deskclock/timer/TimerItem.java
+++ b/src/com/android/deskclock/timer/TimerItem.java
@@ -24,7 +24,6 @@
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.deskclock.CircleButtonsLayout;
import com.android.deskclock.R;
import com.android.deskclock.data.Timer;
@@ -63,10 +62,7 @@
mResetAddButton = (ImageView) findViewById(R.id.reset_add);
mCircleView = (TimerCircleView) findViewById(R.id.timer_time);
mTimerText = (CountingTimerView) findViewById(R.id.timer_time_text);
-
- // This layout dynamically positions the label and reset buttons.
- final CircleButtonsLayout cbl = (CircleButtonsLayout) findViewById(R.id.timer_circle);
- cbl.setCircleTimerViewIds(R.id.timer_time, R.id.reset_add, R.id.timer_label);
+ mTimerText.setShowBoundingCircle(mCircleView != null);
}
/**
@@ -76,9 +72,6 @@
// Update the time.
mTimerText.setTime(timer.getRemainingTime(), false);
- // Update the progress of the circle.
- mCircleView.update(timer);
-
// Update the label if it changed.
final String label = timer.getLabel();
if (!TextUtils.equals(label, mLabelView.getText())) {
@@ -87,7 +80,15 @@
// Update visibility of things that may blink.
final boolean blinkOff = SystemClock.elapsedRealtime() % 1000 < 500;
- mCircleView.setVisibility(timer.isExpired() && blinkOff ? INVISIBLE : VISIBLE);
+ if (mCircleView != null) {
+ final boolean hideCircle = timer.isExpired() && blinkOff;
+ mCircleView.setVisibility(hideCircle ? INVISIBLE : VISIBLE);
+
+ if (!hideCircle) {
+ // Update the progress of the circle.
+ mCircleView.update(timer);
+ }
+ }
mTimerText.showTime(!timer.isPaused() || !blinkOff);
// Update some potentially expensive areas of the user interface only on state changes.
@@ -125,4 +126,4 @@
}
}
}
-}
+}
\ No newline at end of file