summaryrefslogtreecommitdiffstats
path: root/v17
diff options
context:
space:
mode:
Diffstat (limited to 'v17')
-rw-r--r--v17/leanback/.classpath9
-rw-r--r--v17/leanback/Android.mk25
-rw-r--r--v17/leanback/api/23.0.0.txt (renamed from v17/leanback/api/23.txt)0
-rw-r--r--v17/leanback/api/23.1.0.txt1796
-rw-r--r--v17/leanback/api/current.txt370
-rw-r--r--v17/leanback/api21/android/support/v17/leanback/transition/FadeAndShortSlide.java211
-rw-r--r--v17/leanback/api21/android/support/v17/leanback/transition/TransitionHelperApi21.java30
-rw-r--r--v17/leanback/api21/android/support/v17/leanback/transition/TranslationAnimationCreator.java128
-rw-r--r--v17/leanback/api21/android/support/v17/leanback/widget/RoundedRectHelperApi21.java40
-rw-r--r--v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java19
-rw-r--r--v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java35
-rw-r--r--v17/leanback/build.gradle4
-rw-r--r--v17/leanback/common/android/support/v17/leanback/transition/TransitionListener.java10
-rwxr-xr-xv17/leanback/generatev4.py16
-rw-r--r--v17/leanback/kitkat/android/support/v17/leanback/transition/TransitionHelperKitkat.java22
-rw-r--r--v17/leanback/project.properties2
-rw-r--r--v17/leanback/res/animator/lb_guidance_entry.xml54
-rw-r--r--v17/leanback/res/animator/lb_guidedactions_entry.xml53
-rw-r--r--v17/leanback/res/animator/lb_guidedactions_selector_hide.xml1
-rw-r--r--v17/leanback/res/animator/lb_guidedactions_selector_show.xml1
-rw-r--r--v17/leanback/res/animator/lb_guidedstep_slide_down.xml (renamed from v17/leanback/res/animator/lb_guidedactions_item_unchecked.xml)6
-rw-r--r--v17/leanback/res/animator/lb_guidedstep_slide_in_from_end.xml34
-rw-r--r--v17/leanback/res/animator/lb_guidedstep_slide_in_from_start.xml34
-rw-r--r--v17/leanback/res/animator/lb_guidedstep_slide_out_to_end.xml34
-rw-r--r--v17/leanback/res/animator/lb_guidedstep_slide_out_to_start.xml34
-rw-r--r--v17/leanback/res/animator/lb_guidedstep_slide_up.xml (renamed from v17/leanback/res/animator/lb_guidedactions_item_checked.xml)6
-rw-r--r--v17/leanback/res/drawable/lb_headers_right_fading.xml2
-rw-r--r--v17/leanback/res/layout/lb_fullwidth_details_overview.xml3
-rw-r--r--v17/leanback/res/layout/lb_guidedactions.xml38
-rw-r--r--v17/leanback/res/layout/lb_guidedactions_item.xml7
-rw-r--r--v17/leanback/res/layout/lb_guidedstep_background.xml24
-rw-r--r--v17/leanback/res/layout/lb_guidedstep_fragment.xml62
-rw-r--r--v17/leanback/res/layout/lb_image_card_view.xml63
-rw-r--r--v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml23
-rw-r--r--v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml23
-rw-r--r--v17/leanback/res/layout/lb_image_card_view_themed_content.xml (renamed from v17/leanback/res/layout/lb_card_color_overlay.xml)7
-rw-r--r--v17/leanback/res/layout/lb_image_card_view_themed_title.xml20
-rw-r--r--v17/leanback/res/layout/lb_search_fragment.xml3
-rw-r--r--v17/leanback/res/transition-v21/lb_browse_entrance_transition.xml2
-rw-r--r--v17/leanback/res/transition-v21/lb_browse_return_transition.xml4
-rw-r--r--v17/leanback/res/transition-v21/lb_guidedstep_activity_enter.xml53
-rw-r--r--v17/leanback/res/transition-v21/lb_vertical_grid_enter_transition.xml22
-rw-r--r--v17/leanback/res/transition-v21/lb_vertical_grid_entrance_transition.xml (renamed from v17/leanback/res/transition-v22/lb_browse_entrance_transition.xml)8
-rw-r--r--v17/leanback/res/transition-v21/lb_vertical_grid_return_transition.xml (renamed from v17/leanback/res/transition-v22/lb_browse_return_transition.xml)19
-rw-r--r--v17/leanback/res/values-af/strings.xml2
-rw-r--r--v17/leanback/res/values-am/strings.xml2
-rw-r--r--v17/leanback/res/values-ar/strings.xml2
-rw-r--r--v17/leanback/res/values-az-rAZ/strings.xml2
-rw-r--r--v17/leanback/res/values-bg/strings.xml2
-rw-r--r--v17/leanback/res/values-bn-rBD/strings.xml2
-rw-r--r--v17/leanback/res/values-ca/strings.xml2
-rw-r--r--v17/leanback/res/values-cs/strings.xml2
-rw-r--r--v17/leanback/res/values-da/strings.xml2
-rw-r--r--v17/leanback/res/values-de/strings.xml2
-rw-r--r--v17/leanback/res/values-el/strings.xml2
-rw-r--r--v17/leanback/res/values-en-rAU/strings.xml2
-rw-r--r--v17/leanback/res/values-en-rGB/strings.xml2
-rw-r--r--v17/leanback/res/values-en-rIN/strings.xml2
-rw-r--r--v17/leanback/res/values-es-rUS/strings.xml2
-rw-r--r--v17/leanback/res/values-es/strings.xml2
-rw-r--r--v17/leanback/res/values-et-rEE/strings.xml2
-rw-r--r--v17/leanback/res/values-eu-rES/strings.xml2
-rw-r--r--v17/leanback/res/values-fa/strings.xml2
-rw-r--r--v17/leanback/res/values-fi/strings.xml2
-rw-r--r--v17/leanback/res/values-fr-rCA/strings.xml2
-rw-r--r--v17/leanback/res/values-fr/strings.xml2
-rw-r--r--v17/leanback/res/values-gl-rES/strings.xml2
-rw-r--r--v17/leanback/res/values-gu-rIN/strings.xml2
-rw-r--r--v17/leanback/res/values-hi/strings.xml2
-rw-r--r--v17/leanback/res/values-hr/strings.xml2
-rw-r--r--v17/leanback/res/values-hu/strings.xml2
-rw-r--r--v17/leanback/res/values-hy-rAM/strings.xml2
-rw-r--r--v17/leanback/res/values-in/strings.xml2
-rw-r--r--v17/leanback/res/values-is-rIS/strings.xml2
-rw-r--r--v17/leanback/res/values-it/strings.xml2
-rw-r--r--v17/leanback/res/values-iw/strings.xml2
-rw-r--r--v17/leanback/res/values-ja/strings.xml2
-rw-r--r--v17/leanback/res/values-ka-rGE/strings.xml2
-rw-r--r--v17/leanback/res/values-kk-rKZ/strings.xml2
-rw-r--r--v17/leanback/res/values-km-rKH/strings.xml2
-rw-r--r--v17/leanback/res/values-kn-rIN/strings.xml2
-rw-r--r--v17/leanback/res/values-ko/strings.xml2
-rw-r--r--v17/leanback/res/values-ky-rKG/strings.xml2
-rw-r--r--v17/leanback/res/values-ldrtl/integers.xml (renamed from v17/leanback/res/drawable/lb_guidedactions_item_checkmark.xml)14
-rw-r--r--v17/leanback/res/values-lo-rLA/strings.xml2
-rw-r--r--v17/leanback/res/values-lt/strings.xml2
-rw-r--r--v17/leanback/res/values-lv/strings.xml2
-rw-r--r--v17/leanback/res/values-mk-rMK/strings.xml2
-rw-r--r--v17/leanback/res/values-ml-rIN/strings.xml2
-rw-r--r--v17/leanback/res/values-mn-rMN/strings.xml2
-rw-r--r--v17/leanback/res/values-mr-rIN/strings.xml2
-rw-r--r--v17/leanback/res/values-ms-rMY/strings.xml2
-rw-r--r--v17/leanback/res/values-my-rMM/strings.xml2
-rw-r--r--v17/leanback/res/values-nb/strings.xml2
-rw-r--r--v17/leanback/res/values-ne-rNP/strings.xml2
-rw-r--r--v17/leanback/res/values-nl/strings.xml2
-rw-r--r--v17/leanback/res/values-pa-rIN/strings.xml2
-rw-r--r--v17/leanback/res/values-pl/strings.xml2
-rw-r--r--v17/leanback/res/values-pt-rBR/strings.xml2
-rw-r--r--v17/leanback/res/values-pt-rPT/strings.xml2
-rw-r--r--v17/leanback/res/values-pt/strings.xml2
-rw-r--r--v17/leanback/res/values-ro/strings.xml2
-rw-r--r--v17/leanback/res/values-ru/strings.xml2
-rw-r--r--v17/leanback/res/values-si-rLK/strings.xml2
-rw-r--r--v17/leanback/res/values-sk/strings.xml2
-rw-r--r--v17/leanback/res/values-sl/strings.xml2
-rw-r--r--v17/leanback/res/values-sq-rAL/strings.xml2
-rw-r--r--v17/leanback/res/values-sr/strings.xml2
-rw-r--r--v17/leanback/res/values-sv/strings.xml2
-rw-r--r--v17/leanback/res/values-sw/strings.xml2
-rw-r--r--v17/leanback/res/values-ta-rIN/strings.xml4
-rw-r--r--v17/leanback/res/values-te-rIN/strings.xml2
-rw-r--r--v17/leanback/res/values-th/strings.xml2
-rw-r--r--v17/leanback/res/values-tl/strings.xml2
-rw-r--r--v17/leanback/res/values-tr/strings.xml2
-rw-r--r--v17/leanback/res/values-uk/strings.xml2
-rw-r--r--v17/leanback/res/values-ur-rPK/strings.xml2
-rw-r--r--v17/leanback/res/values-uz-rUZ/strings.xml2
-rw-r--r--v17/leanback/res/values-v19/themes.xml1
-rw-r--r--v17/leanback/res/values-v21/themes.xml2
-rw-r--r--v17/leanback/res/values-v22/integers.xml24
-rw-r--r--v17/leanback/res/values-vi/strings.xml2
-rw-r--r--v17/leanback/res/values-zh-rCN/strings.xml2
-rw-r--r--v17/leanback/res/values-zh-rHK/strings.xml2
-rw-r--r--v17/leanback/res/values-zh-rTW/strings.xml2
-rw-r--r--v17/leanback/res/values-zu/strings.xml2
-rw-r--r--v17/leanback/res/values/attrs.xml103
-rw-r--r--v17/leanback/res/values/colors.xml2
-rw-r--r--v17/leanback/res/values/dimens.xml16
-rw-r--r--v17/leanback/res/values/ids.xml12
-rw-r--r--v17/leanback/res/values/integers.xml7
-rw-r--r--v17/leanback/res/values/strings.xml4
-rw-r--r--v17/leanback/res/values/styles.xml105
-rw-r--r--v17/leanback/res/values/themes.xml36
-rw-r--r--v17/leanback/src/android/support/v17/leanback/animation/UntargetableAnimatorSet.java131
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/BaseFragment.java4
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java4
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java17
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java17
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java21
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java21
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java266
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapterGroup.java188
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java857
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java1110
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/HeadersFragment.java22
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java22
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java2
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/PlaybackControlSupportGlue.java858
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/RowsFragment.java4
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java4
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/SearchFragment.java12
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/SearchSupportFragment.java12
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java30
-rw-r--r--v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java30
-rw-r--r--v17/leanback/src/android/support/v17/leanback/transition/LeanbackTransitionHelper.java24
-rw-r--r--v17/leanback/src/android/support/v17/leanback/transition/TransitionHelper.java360
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java9
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/BaseGridView.java3
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/CheckableImageView.java69
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper.java7
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java15
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java78
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java40
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter.java27
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper.java10
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java150
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java76
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java422
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/GuidedActionEditText.java58
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java607
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java289
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java47
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/ItemBridgeAdapter.java7
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/ItemBridgeAdapterShadowOverlayWrapper.java44
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java119
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsPresenter.java2
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java29
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/RowPresenter.java17
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/SearchBar.java14
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java13
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java215
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java467
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java11
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/TitleHelper.java14
-rw-r--r--v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java106
-rw-r--r--v17/preference-leanback/Android.mk10
-rw-r--r--v17/preference-leanback/api/23.0.0.txt (renamed from v17/preference-leanback/api/23.txt)0
-rw-r--r--v17/preference-leanback/api/23.1.0.txt61
-rw-r--r--v17/preference-leanback/api21/android/support/v17/preference/LeanbackPreferenceFragmentTransitionHelperApi21.java285
-rw-r--r--v17/preference-leanback/build.gradle34
-rw-r--r--v17/preference-leanback/res/color/lb_preference_item_primary_text_color.xml (renamed from v17/preference-leanback/res/values/ids.xml)7
-rw-r--r--v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml21
-rw-r--r--v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml9
-rw-r--r--v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml35
-rw-r--r--v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml35
-rw-r--r--v17/preference-leanback/res/layout/leanback_preference.xml74
-rw-r--r--v17/preference-leanback/res/layout/leanback_preference_category.xml33
-rw-r--r--v17/preference-leanback/res/layout/leanback_preference_fragment.xml8
-rw-r--r--v17/preference-leanback/res/layout/leanback_preference_information.xml61
-rw-r--r--v17/preference-leanback/res/layout/leanback_preferences_list.xml3
-rw-r--r--v17/preference-leanback/res/values/colors.xml7
-rw-r--r--v17/preference-leanback/res/values/dimens.xml28
-rw-r--r--v17/preference-leanback/res/values/styles.xml74
-rw-r--r--v17/preference-leanback/res/values/themes.xml33
-rw-r--r--v17/preference-leanback/src/android/support/v17/preference/LeanbackListPreferenceDialogFragment.java26
-rw-r--r--v17/tests/AndroidManifest.xml12
-rwxr-xr-xv17/tests/generatev4.py78
-rw-r--r--v17/tests/res/layout/browse.xml28
-rw-r--r--v17/tests/src/android/support/v17/leanback/app/BrowseFragmentTest.java93
-rw-r--r--v17/tests/src/android/support/v17/leanback/app/BrowseFragmentTestActivity.java58
-rw-r--r--v17/tests/src/android/support/v17/leanback/app/BrowseSupportFragmentTest.java95
-rw-r--r--v17/tests/src/android/support/v17/leanback/app/BrowseSupportFragmentTestActivity.java60
-rw-r--r--v17/tests/src/android/support/v17/leanback/app/BrowseTestFragment.java126
-rw-r--r--v17/tests/src/android/support/v17/leanback/app/BrowseTestSupportFragment.java128
-rw-r--r--v17/tests/src/android/support/v17/leanback/app/StringPresenter.java51
-rw-r--r--v17/tests/src/android/support/v17/leanback/widget/GridActivity.java7
-rw-r--r--v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java110
-rw-r--r--v17/tests/src/android/support/v17/leanback/widget/ShadowOverlayContainerTest.java106
219 files changed, 10556 insertions, 2062 deletions
diff --git a/v17/leanback/.classpath b/v17/leanback/.classpath
index 7bc01d9a9c..f568681311 100644
--- a/v17/leanback/.classpath
+++ b/v17/leanback/.classpath
@@ -1,9 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="api21"/>
+ <classpathentry kind="src" path="api23"/>
+ <classpathentry kind="src" path="jbmr2"/>
+ <classpathentry kind="src" path="common"/>
+ <classpathentry kind="src" path="kitkat"/>
+ <classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
diff --git a/v17/leanback/Android.mk b/v17/leanback/Android.mk
index dd03d6a3f0..2dc78a74c3 100644
--- a/v17/leanback/Android.mk
+++ b/v17/leanback/Android.mk
@@ -28,6 +28,8 @@ LOCAL_AAPT_FLAGS := \
LOCAL_JAR_EXCLUDE_FILES := none
include $(BUILD_STATIC_JAVA_LIBRARY)
+support_module_src_files := $(LOCAL_SRC_FILES)
+
# -----------------------------------------------------------------------
# Base sub-library contains classes both needed by api-level specific libraries
@@ -38,6 +40,20 @@ LOCAL_SDK_VERSION := 17
LOCAL_SRC_FILES := $(call all-java-files-under, common)
include $(BUILD_STATIC_JAVA_LIBRARY)
+support_module_src_files += $(LOCAL_SRC_FILES)
+
+# -----------------------------------------------------------------------
+
+# A helper sub-library that makes direct use of API 23.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v17-leanback-api23
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, api23)
+LOCAL_JAVA_LIBRARIES := android-support-v17-leanback-res android-support-v17-leanback-common
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+support_module_src_files += $(LOCAL_SRC_FILES)
+
# -----------------------------------------------------------------------
# A helper sub-library that makes direct use of API 21.
@@ -48,6 +64,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, api21)
LOCAL_JAVA_LIBRARIES := android-support-v17-leanback-res android-support-v17-leanback-common
include $(BUILD_STATIC_JAVA_LIBRARY)
+support_module_src_files += $(LOCAL_SRC_FILES)
+
# -----------------------------------------------------------------------
# A helper sub-library that makes direct use of KitKat APIs.
@@ -58,6 +76,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, kitkat)
LOCAL_JAVA_LIBRARIES := android-support-v17-leanback-res android-support-v17-leanback-common
include $(BUILD_STATIC_JAVA_LIBRARY)
+support_module_src_files += $(LOCAL_SRC_FILES)
+
# -----------------------------------------------------------------------
# A helper sub-library that makes direct use of JBMR2 APIs.
@@ -68,6 +88,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, jbmr2)
LOCAL_JAVA_LIBRARIES := android-support-v17-leanback-res android-support-v17-leanback-common
include $(BUILD_STATIC_JAVA_LIBRARY)
+support_module_src_files += $(LOCAL_SRC_FILES)
+
# -----------------------------------------------------------------------
# Here is the final static library that apps can link against.
@@ -79,6 +101,7 @@ LOCAL_MODULE := android-support-v17-leanback
LOCAL_SDK_VERSION := 17
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v17-leanback-kitkat android-support-v17-leanback-jbmr2 \
+ android-support-v17-leanback-api23 \
android-support-v17-leanback-api21 android-support-v17-leanback-common
LOCAL_JAVA_LIBRARIES := \
android-support-v4 \
@@ -86,6 +109,7 @@ LOCAL_JAVA_LIBRARIES := \
android-support-v17-leanback-res
include $(BUILD_STATIC_JAVA_LIBRARY)
+support_module_src_files += $(LOCAL_SRC_FILES)
# ===========================================================
# Common Droiddoc vars
@@ -131,7 +155,6 @@ include $(BUILD_DROIDDOC)
# ---------------------------------------------
support_module := $(LOCAL_MODULE)
support_module_api_dir := $(LOCAL_PATH)/api
-support_module_src_files := $(leanback.docs.src_files)
support_module_java_libraries := $(leanback.docs.java_libraries)
support_module_java_packages := android.support.v17.leanback*
include $(SUPPORT_API_CHECK)
diff --git a/v17/leanback/api/23.txt b/v17/leanback/api/23.0.0.txt
index fb2832d820..fb2832d820 100644
--- a/v17/leanback/api/23.txt
+++ b/v17/leanback/api/23.0.0.txt
diff --git a/v17/leanback/api/23.1.0.txt b/v17/leanback/api/23.1.0.txt
new file mode 100644
index 0000000000..962367d3f2
--- /dev/null
+++ b/v17/leanback/api/23.1.0.txt
@@ -0,0 +1,1796 @@
+package android.support.v17.leanback.app {
+
+ public final class BackgroundManager {
+ method public void attach(android.view.Window);
+ method public final int getColor();
+ method public android.graphics.drawable.Drawable getDefaultDimLayer();
+ method public android.graphics.drawable.Drawable getDimLayer();
+ method public android.graphics.drawable.Drawable getDrawable();
+ method public static android.support.v17.leanback.app.BackgroundManager getInstance(android.app.Activity);
+ method public boolean isAttached();
+ method public void release();
+ method public void setBitmap(android.graphics.Bitmap);
+ method public void setColor(int);
+ method public void setDimLayer(android.graphics.drawable.Drawable);
+ method public void setDrawable(android.graphics.drawable.Drawable);
+ method public void setThemeDrawableResourceId(int);
+ }
+
+ abstract class BaseRowFragment extends android.app.Fragment {
+ method public final android.support.v17.leanback.widget.ObjectAdapter getAdapter();
+ method public final android.support.v17.leanback.widget.PresenterSelector getPresenterSelector();
+ method public final void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public final void setPresenterSelector(android.support.v17.leanback.widget.PresenterSelector);
+ method public void setSelectedPosition(int);
+ method public void setSelectedPosition(int, boolean);
+ }
+
+ abstract class BaseRowSupportFragment extends android.support.v4.app.Fragment {
+ method public final android.support.v17.leanback.widget.ObjectAdapter getAdapter();
+ method public final android.support.v17.leanback.widget.PresenterSelector getPresenterSelector();
+ method public final void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public final void setPresenterSelector(android.support.v17.leanback.widget.PresenterSelector);
+ method public void setSelectedPosition(int);
+ method public void setSelectedPosition(int, boolean);
+ }
+
+ public class BrowseFragment extends android.support.v17.leanback.app.BrandedFragment {
+ ctor public BrowseFragment();
+ method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String, int);
+ method protected java.lang.Object createEntranceTransition();
+ method public void enableRowScaling(boolean);
+ method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
+ method public int getBrandColor();
+ method public int getHeadersState();
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public android.support.v17.leanback.widget.OnItemViewSelectedListener getOnItemViewSelectedListener();
+ method public final boolean isHeadersTransitionOnBackEnabled();
+ method public boolean isInHeadersTransition();
+ method public boolean isShowingHeaders();
+ method protected void onEntranceTransitionEnd();
+ method protected void onEntranceTransitionPrepare();
+ method protected void onEntranceTransitionStart();
+ method public void onSaveInstanceState(android.os.Bundle);
+ method public void onStart();
+ method protected void runEntranceTransition(java.lang.Object);
+ method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public void setBrandColor(int);
+ method public void setBrowseTransitionListener(android.support.v17.leanback.app.BrowseFragment.BrowseTransitionListener);
+ method public void setHeaderPresenterSelector(android.support.v17.leanback.widget.PresenterSelector);
+ method public void setHeadersState(int);
+ method public final void setHeadersTransitionOnBackEnabled(boolean);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public void setSelectedPosition(int);
+ method public void setSelectedPosition(int, boolean);
+ method public void startHeadersTransition(boolean);
+ field public static final int HEADERS_DISABLED = 3; // 0x3
+ field public static final int HEADERS_ENABLED = 1; // 0x1
+ field public static final int HEADERS_HIDDEN = 2; // 0x2
+ }
+
+ public static class BrowseFragment.BrowseTransitionListener {
+ ctor public BrowseFragment.BrowseTransitionListener();
+ method public void onHeadersTransitionStart(boolean);
+ method public void onHeadersTransitionStop(boolean);
+ }
+
+ public class BrowseSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
+ ctor public BrowseSupportFragment();
+ method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String, int);
+ method protected java.lang.Object createEntranceTransition();
+ method public void enableRowScaling(boolean);
+ method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
+ method public int getBrandColor();
+ method public int getHeadersState();
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public android.support.v17.leanback.widget.OnItemViewSelectedListener getOnItemViewSelectedListener();
+ method public final boolean isHeadersTransitionOnBackEnabled();
+ method public boolean isInHeadersTransition();
+ method public boolean isShowingHeaders();
+ method protected void onEntranceTransitionEnd();
+ method protected void onEntranceTransitionPrepare();
+ method protected void onEntranceTransitionStart();
+ method public void onSaveInstanceState(android.os.Bundle);
+ method public void onStart();
+ method protected void runEntranceTransition(java.lang.Object);
+ method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public void setBrandColor(int);
+ method public void setBrowseTransitionListener(android.support.v17.leanback.app.BrowseSupportFragment.BrowseTransitionListener);
+ method public void setHeaderPresenterSelector(android.support.v17.leanback.widget.PresenterSelector);
+ method public void setHeadersState(int);
+ method public final void setHeadersTransitionOnBackEnabled(boolean);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public void setSelectedPosition(int);
+ method public void setSelectedPosition(int, boolean);
+ method public void startHeadersTransition(boolean);
+ field public static final int HEADERS_DISABLED = 3; // 0x3
+ field public static final int HEADERS_ENABLED = 1; // 0x1
+ field public static final int HEADERS_HIDDEN = 2; // 0x2
+ }
+
+ public static class BrowseSupportFragment.BrowseTransitionListener {
+ ctor public BrowseSupportFragment.BrowseTransitionListener();
+ method public void onHeadersTransitionStart(boolean);
+ method public void onHeadersTransitionStop(boolean);
+ }
+
+ public class DetailsFragment extends android.support.v17.leanback.app.BrandedFragment {
+ ctor public DetailsFragment();
+ method protected java.lang.Object createEntranceTransition();
+ method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method protected android.view.View inflateTitle(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+ method protected void onEntranceTransitionEnd();
+ method protected void onEntranceTransitionPrepare();
+ method protected void onEntranceTransitionStart();
+ method protected void onSetDetailsOverviewRowStatus(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter, android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder, int, int, int);
+ method protected void onSetRowStatus(android.support.v17.leanback.widget.RowPresenter, android.support.v17.leanback.widget.RowPresenter.ViewHolder, int, int, int);
+ method public void onStart();
+ method protected void runEntranceTransition(java.lang.Object);
+ method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public void setSelectedPosition(int);
+ method public void setSelectedPosition(int, boolean);
+ method protected void setupDetailsOverviewRowPresenter(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter);
+ method protected void setupPresenter(android.support.v17.leanback.widget.Presenter);
+ }
+
+ public class DetailsSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
+ ctor public DetailsSupportFragment();
+ method protected java.lang.Object createEntranceTransition();
+ method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method protected android.view.View inflateTitle(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+ method protected void onEntranceTransitionEnd();
+ method protected void onEntranceTransitionPrepare();
+ method protected void onEntranceTransitionStart();
+ method protected void onSetDetailsOverviewRowStatus(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter, android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder, int, int, int);
+ method protected void onSetRowStatus(android.support.v17.leanback.widget.RowPresenter, android.support.v17.leanback.widget.RowPresenter.ViewHolder, int, int, int);
+ method public void onStart();
+ method protected void runEntranceTransition(java.lang.Object);
+ method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public void setSelectedPosition(int);
+ method public void setSelectedPosition(int, boolean);
+ method protected void setupDetailsOverviewRowPresenter(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter);
+ method protected void setupPresenter(android.support.v17.leanback.widget.Presenter);
+ }
+
+ public class ErrorFragment extends android.app.Fragment {
+ ctor public ErrorFragment();
+ method public android.graphics.drawable.Drawable getBackgroundDrawable();
+ method public android.graphics.drawable.Drawable getBadgeDrawable();
+ method public android.view.View.OnClickListener getButtonClickListener();
+ method public java.lang.String getButtonText();
+ method public android.graphics.drawable.Drawable getImageDrawable();
+ method public java.lang.CharSequence getMessage();
+ method public java.lang.String getTitle();
+ method public boolean isBackgroundTranslucent();
+ method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+ method public void setBadgeDrawable(android.graphics.drawable.Drawable);
+ method public void setButtonClickListener(android.view.View.OnClickListener);
+ method public void setButtonText(java.lang.String);
+ method public void setDefaultBackground(boolean);
+ method public void setImageDrawable(android.graphics.drawable.Drawable);
+ method public void setMessage(java.lang.CharSequence);
+ method public void setTitle(java.lang.String);
+ }
+
+ public class ErrorSupportFragment extends android.support.v4.app.Fragment {
+ ctor public ErrorSupportFragment();
+ method public android.graphics.drawable.Drawable getBackgroundDrawable();
+ method public android.graphics.drawable.Drawable getBadgeDrawable();
+ method public android.view.View.OnClickListener getButtonClickListener();
+ method public java.lang.String getButtonText();
+ method public android.graphics.drawable.Drawable getImageDrawable();
+ method public java.lang.CharSequence getMessage();
+ method public java.lang.String getTitle();
+ method public boolean isBackgroundTranslucent();
+ method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+ method public void setBadgeDrawable(android.graphics.drawable.Drawable);
+ method public void setButtonClickListener(android.view.View.OnClickListener);
+ method public void setButtonText(java.lang.String);
+ method public void setDefaultBackground(boolean);
+ method public void setImageDrawable(android.graphics.drawable.Drawable);
+ method public void setMessage(java.lang.CharSequence);
+ method public void setTitle(java.lang.String);
+ }
+
+ public class GuidedStepFragment extends android.app.Fragment {
+ ctor public GuidedStepFragment();
+ method public static int add(android.app.FragmentManager, android.support.v17.leanback.app.GuidedStepFragment);
+ method public static int add(android.app.FragmentManager, android.support.v17.leanback.app.GuidedStepFragment, int);
+ method public static int addAsRoot(android.app.Activity, android.support.v17.leanback.app.GuidedStepFragment, int);
+ method public android.view.View getActionItemView(int);
+ method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getActions();
+ method protected int getContainerIdForBackground();
+ method public static android.support.v17.leanback.app.GuidedStepFragment getCurrentGuidedStepFragment(android.app.FragmentManager);
+ method public android.support.v17.leanback.widget.GuidanceStylist getGuidanceStylist();
+ method public android.support.v17.leanback.widget.GuidedActionsStylist getGuidedActionsStylist();
+ method public int getSelectedActionPosition();
+ method public int getUiStyle();
+ method public void onCreateActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
+ method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateActionsStylist();
+ method public android.support.v17.leanback.widget.GuidanceStylist.Guidance onCreateGuidance(android.os.Bundle);
+ method public android.support.v17.leanback.widget.GuidanceStylist onCreateGuidanceStylist();
+ method public void onGuidedActionClicked(android.support.v17.leanback.widget.GuidedAction);
+ method public void onGuidedActionEdited(android.support.v17.leanback.widget.GuidedAction);
+ method public void onGuidedActionFocused(android.support.v17.leanback.widget.GuidedAction);
+ method protected android.app.Fragment onProvideBackgroundFragment();
+ method protected void onProvideFragmentTransitions();
+ method public int onProvideTheme();
+ method public void setActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
+ method public void setSelectedActionPosition(int);
+ method public void setUiStyle(int);
+ field public static final java.lang.String EXTRA_UI_STYLE = "uiStyle";
+ field public static final int UI_STYLE_ACTIVITY_ROOT = 2; // 0x2
+ field public static final int UI_STYLE_DEFAULT = 0; // 0x0
+ field public static final int UI_STYLE_ENTRANCE = 1; // 0x1
+ }
+
+ public static class GuidedStepFragment.GuidedStepBackgroundFragment extends android.app.Fragment {
+ ctor public GuidedStepFragment.GuidedStepBackgroundFragment();
+ method protected void onProvideFragmentTransitions();
+ }
+
+ public class GuidedStepSupportFragment extends android.support.v4.app.Fragment {
+ ctor public GuidedStepSupportFragment();
+ method public static int add(android.support.v4.app.FragmentManager, android.support.v17.leanback.app.GuidedStepSupportFragment);
+ method public static int add(android.support.v4.app.FragmentManager, android.support.v17.leanback.app.GuidedStepSupportFragment, int);
+ method public static int addAsRoot(android.support.v4.app.FragmentActivity, android.support.v17.leanback.app.GuidedStepSupportFragment, int);
+ method public android.view.View getActionItemView(int);
+ method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getActions();
+ method protected int getContainerIdForBackground();
+ method public static android.support.v17.leanback.app.GuidedStepSupportFragment getCurrentGuidedStepSupportFragment(android.support.v4.app.FragmentManager);
+ method public android.support.v17.leanback.widget.GuidanceStylist getGuidanceStylist();
+ method public android.support.v17.leanback.widget.GuidedActionsStylist getGuidedActionsStylist();
+ method public int getSelectedActionPosition();
+ method public int getUiStyle();
+ method public void onCreateActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
+ method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateActionsStylist();
+ method public android.support.v17.leanback.widget.GuidanceStylist.Guidance onCreateGuidance(android.os.Bundle);
+ method public android.support.v17.leanback.widget.GuidanceStylist onCreateGuidanceStylist();
+ method public void onGuidedActionClicked(android.support.v17.leanback.widget.GuidedAction);
+ method public void onGuidedActionEdited(android.support.v17.leanback.widget.GuidedAction);
+ method public void onGuidedActionFocused(android.support.v17.leanback.widget.GuidedAction);
+ method protected android.support.v4.app.Fragment onProvideBackgroundSupportFragment();
+ method protected void onProvideFragmentTransitions();
+ method public int onProvideTheme();
+ method public void setActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
+ method public void setSelectedActionPosition(int);
+ method public void setUiStyle(int);
+ field public static final java.lang.String EXTRA_UI_STYLE = "uiStyle";
+ field public static final int UI_STYLE_ACTIVITY_ROOT = 2; // 0x2
+ field public static final int UI_STYLE_DEFAULT = 0; // 0x0
+ field public static final int UI_STYLE_ENTRANCE = 1; // 0x1
+ }
+
+ public static class GuidedStepSupportFragment.GuidedStepBackgroundSupportFragment extends android.support.v4.app.Fragment {
+ ctor public GuidedStepSupportFragment.GuidedStepBackgroundSupportFragment();
+ method protected void onProvideFragmentTransitions();
+ }
+
+ public class HeadersFragment extends android.support.v17.leanback.app.BaseRowFragment {
+ ctor public HeadersFragment();
+ method public void setOnHeaderClickedListener(android.support.v17.leanback.app.HeadersFragment.OnHeaderClickedListener);
+ method public void setOnHeaderViewSelectedListener(android.support.v17.leanback.app.HeadersFragment.OnHeaderViewSelectedListener);
+ }
+
+ static abstract interface HeadersFragment.OnHeaderClickedListener {
+ method public abstract void onHeaderClicked();
+ }
+
+ static abstract interface HeadersFragment.OnHeaderViewSelectedListener {
+ method public abstract void onHeaderSelected(android.support.v17.leanback.widget.RowHeaderPresenter.ViewHolder, android.support.v17.leanback.widget.Row);
+ }
+
+ public class HeadersSupportFragment extends android.support.v17.leanback.app.BaseRowSupportFragment {
+ ctor public HeadersSupportFragment();
+ method public void setOnHeaderClickedListener(android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderClickedListener);
+ method public void setOnHeaderViewSelectedListener(android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderViewSelectedListener);
+ }
+
+ static abstract interface HeadersSupportFragment.OnHeaderClickedListener {
+ method public abstract void onHeaderClicked();
+ }
+
+ static abstract interface HeadersSupportFragment.OnHeaderViewSelectedListener {
+ method public abstract void onHeaderSelected(android.support.v17.leanback.widget.RowHeaderPresenter.ViewHolder, android.support.v17.leanback.widget.Row);
+ }
+
+ public abstract class MediaControllerGlue extends android.support.v17.leanback.app.PlaybackControlGlue {
+ ctor public MediaControllerGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[]);
+ ctor public MediaControllerGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[]);
+ method public void attachToMediaController(android.support.v4.media.session.MediaControllerCompat);
+ method public void detach();
+ method public int getCurrentPosition();
+ method public int getCurrentSpeedId();
+ method public android.graphics.drawable.Drawable getMediaArt();
+ method public final android.support.v4.media.session.MediaControllerCompat getMediaController();
+ method public int getMediaDuration();
+ method public java.lang.CharSequence getMediaSubtitle();
+ method public java.lang.CharSequence getMediaTitle();
+ method public long getSupportedActions();
+ method public boolean hasValidMedia();
+ method public boolean isMediaPlaying();
+ method protected void pausePlayback();
+ method protected void skipToNext();
+ method protected void skipToPrevious();
+ method protected void startPlayback(int);
+ }
+
+ public abstract class PlaybackControlGlue implements android.support.v17.leanback.widget.OnActionClickedListener android.view.View.OnKeyListener {
+ ctor public PlaybackControlGlue(android.content.Context, int[]);
+ ctor public PlaybackControlGlue(android.content.Context, int[], int[]);
+ ctor public PlaybackControlGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[]);
+ ctor public PlaybackControlGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[]);
+ method public android.support.v17.leanback.widget.PlaybackControlsRowPresenter createControlsRowAndPresenter();
+ method protected android.support.v17.leanback.widget.SparseArrayObjectAdapter createPrimaryActionsAdapter(android.support.v17.leanback.widget.PresenterSelector);
+ method public void enableProgressUpdating(boolean);
+ method public android.content.Context getContext();
+ method public android.support.v17.leanback.widget.PlaybackControlsRow getControlsRow();
+ method public abstract int getCurrentPosition();
+ method public abstract int getCurrentSpeedId();
+ method public int[] getFastForwardSpeeds();
+ method public android.support.v17.leanback.app.PlaybackOverlayFragment getFragment();
+ method public abstract android.graphics.drawable.Drawable getMediaArt();
+ method public abstract int getMediaDuration();
+ method public abstract java.lang.CharSequence getMediaSubtitle();
+ method public abstract java.lang.CharSequence getMediaTitle();
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public int[] getRewindSpeeds();
+ method public abstract long getSupportedActions();
+ method public int getUpdatePeriod();
+ method public abstract boolean hasValidMedia();
+ method public boolean isFadingEnabled();
+ method public abstract boolean isMediaPlaying();
+ method public void onActionClicked(android.support.v17.leanback.widget.Action);
+ method public boolean onKey(android.view.View, int, android.view.KeyEvent);
+ method protected void onMetadataChanged();
+ method protected abstract void onRowChanged(android.support.v17.leanback.widget.PlaybackControlsRow);
+ method protected void onStateChanged();
+ method protected abstract void pausePlayback();
+ method public void setControlsRow(android.support.v17.leanback.widget.PlaybackControlsRow);
+ method public void setFadingEnabled(boolean);
+ method public deprecated void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method protected abstract void skipToNext();
+ method protected abstract void skipToPrevious();
+ method protected abstract void startPlayback(int);
+ method public void updateProgress();
+ field public static final int ACTION_CUSTOM_LEFT_FIRST = 1; // 0x1
+ field public static final int ACTION_CUSTOM_RIGHT_FIRST = 4096; // 0x1000
+ field public static final int ACTION_FAST_FORWARD = 128; // 0x80
+ field public static final int ACTION_PLAY_PAUSE = 64; // 0x40
+ field public static final int ACTION_REWIND = 32; // 0x20
+ field public static final int ACTION_SKIP_TO_NEXT = 256; // 0x100
+ field public static final int ACTION_SKIP_TO_PREVIOUS = 16; // 0x10
+ field public static final int PLAYBACK_SPEED_FAST_L0 = 10; // 0xa
+ field public static final int PLAYBACK_SPEED_FAST_L1 = 11; // 0xb
+ field public static final int PLAYBACK_SPEED_FAST_L2 = 12; // 0xc
+ field public static final int PLAYBACK_SPEED_FAST_L3 = 13; // 0xd
+ field public static final int PLAYBACK_SPEED_FAST_L4 = 14; // 0xe
+ field public static final int PLAYBACK_SPEED_INVALID = -1; // 0xffffffff
+ field public static final int PLAYBACK_SPEED_NORMAL = 1; // 0x1
+ field public static final int PLAYBACK_SPEED_PAUSED = 0; // 0x0
+ }
+
+ public abstract class PlaybackControlSupportGlue implements android.support.v17.leanback.widget.OnActionClickedListener android.view.View.OnKeyListener {
+ ctor public PlaybackControlSupportGlue(android.content.Context, int[]);
+ ctor public PlaybackControlSupportGlue(android.content.Context, int[], int[]);
+ ctor public PlaybackControlSupportGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlaySupportFragment, int[]);
+ ctor public PlaybackControlSupportGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlaySupportFragment, int[], int[]);
+ method public android.support.v17.leanback.widget.PlaybackControlsRowPresenter createControlsRowAndPresenter();
+ method protected android.support.v17.leanback.widget.SparseArrayObjectAdapter createPrimaryActionsAdapter(android.support.v17.leanback.widget.PresenterSelector);
+ method public void enableProgressUpdating(boolean);
+ method public android.content.Context getContext();
+ method public android.support.v17.leanback.widget.PlaybackControlsRow getControlsRow();
+ method public abstract int getCurrentPosition();
+ method public abstract int getCurrentSpeedId();
+ method public int[] getFastForwardSpeeds();
+ method public android.support.v17.leanback.app.PlaybackOverlaySupportFragment getFragment();
+ method public abstract android.graphics.drawable.Drawable getMediaArt();
+ method public abstract int getMediaDuration();
+ method public abstract java.lang.CharSequence getMediaSubtitle();
+ method public abstract java.lang.CharSequence getMediaTitle();
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public int[] getRewindSpeeds();
+ method public abstract long getSupportedActions();
+ method public int getUpdatePeriod();
+ method public abstract boolean hasValidMedia();
+ method public boolean isFadingEnabled();
+ method public abstract boolean isMediaPlaying();
+ method public void onActionClicked(android.support.v17.leanback.widget.Action);
+ method public boolean onKey(android.view.View, int, android.view.KeyEvent);
+ method protected void onMetadataChanged();
+ method protected abstract void onRowChanged(android.support.v17.leanback.widget.PlaybackControlsRow);
+ method protected void onStateChanged();
+ method protected abstract void pausePlayback();
+ method public void setControlsRow(android.support.v17.leanback.widget.PlaybackControlsRow);
+ method public void setFadingEnabled(boolean);
+ method public deprecated void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method protected abstract void skipToNext();
+ method protected abstract void skipToPrevious();
+ method protected abstract void startPlayback(int);
+ method public void updateProgress();
+ field public static final int ACTION_CUSTOM_LEFT_FIRST = 1; // 0x1
+ field public static final int ACTION_CUSTOM_RIGHT_FIRST = 4096; // 0x1000
+ field public static final int ACTION_FAST_FORWARD = 128; // 0x80
+ field public static final int ACTION_PLAY_PAUSE = 64; // 0x40
+ field public static final int ACTION_REWIND = 32; // 0x20
+ field public static final int ACTION_SKIP_TO_NEXT = 256; // 0x100
+ field public static final int ACTION_SKIP_TO_PREVIOUS = 16; // 0x10
+ field public static final int PLAYBACK_SPEED_FAST_L0 = 10; // 0xa
+ field public static final int PLAYBACK_SPEED_FAST_L1 = 11; // 0xb
+ field public static final int PLAYBACK_SPEED_FAST_L2 = 12; // 0xc
+ field public static final int PLAYBACK_SPEED_FAST_L3 = 13; // 0xd
+ field public static final int PLAYBACK_SPEED_FAST_L4 = 14; // 0xe
+ field public static final int PLAYBACK_SPEED_INVALID = -1; // 0xffffffff
+ field public static final int PLAYBACK_SPEED_NORMAL = 1; // 0x1
+ field public static final int PLAYBACK_SPEED_PAUSED = 0; // 0x0
+ }
+
+ public class PlaybackOverlayFragment extends android.support.v17.leanback.app.DetailsFragment {
+ ctor public PlaybackOverlayFragment();
+ method public int getBackgroundType();
+ method public android.support.v17.leanback.app.PlaybackOverlayFragment.OnFadeCompleteListener getFadeCompleteListener();
+ method public final android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler getInputEventHandler();
+ method public boolean isFadingEnabled();
+ method public void onDestroyView();
+ method public void onResume();
+ method public void setBackgroundType(int);
+ method public void setFadeCompleteListener(android.support.v17.leanback.app.PlaybackOverlayFragment.OnFadeCompleteListener);
+ method public void setFadingEnabled(boolean);
+ method public final void setInputEventHandler(android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler);
+ method public void tickle();
+ field public static final int BG_DARK = 1; // 0x1
+ field public static final int BG_LIGHT = 2; // 0x2
+ field public static final int BG_NONE = 0; // 0x0
+ }
+
+ public static abstract interface PlaybackOverlayFragment.InputEventHandler {
+ method public abstract boolean handleInputEvent(android.view.InputEvent);
+ }
+
+ public static class PlaybackOverlayFragment.OnFadeCompleteListener {
+ ctor public PlaybackOverlayFragment.OnFadeCompleteListener();
+ method public void onFadeInComplete();
+ method public void onFadeOutComplete();
+ }
+
+ public class PlaybackOverlaySupportFragment extends android.support.v17.leanback.app.DetailsSupportFragment {
+ ctor public PlaybackOverlaySupportFragment();
+ method public int getBackgroundType();
+ method public android.support.v17.leanback.app.PlaybackOverlaySupportFragment.OnFadeCompleteListener getFadeCompleteListener();
+ method public final android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler getInputEventHandler();
+ method public boolean isFadingEnabled();
+ method public void onDestroyView();
+ method public void onResume();
+ method public void setBackgroundType(int);
+ method public void setFadeCompleteListener(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.OnFadeCompleteListener);
+ method public void setFadingEnabled(boolean);
+ method public final void setInputEventHandler(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler);
+ method public void tickle();
+ field public static final int BG_DARK = 1; // 0x1
+ field public static final int BG_LIGHT = 2; // 0x2
+ field public static final int BG_NONE = 0; // 0x0
+ }
+
+ public static abstract interface PlaybackOverlaySupportFragment.InputEventHandler {
+ method public abstract boolean handleInputEvent(android.view.InputEvent);
+ }
+
+ public static class PlaybackOverlaySupportFragment.OnFadeCompleteListener {
+ ctor public PlaybackOverlaySupportFragment.OnFadeCompleteListener();
+ method public void onFadeInComplete();
+ method public void onFadeOutComplete();
+ }
+
+ public class RowsFragment extends android.support.v17.leanback.app.BaseRowFragment {
+ ctor public RowsFragment();
+ method public void enableRowScaling(boolean);
+ method protected android.support.v17.leanback.widget.VerticalGridView findGridViewFromRoot(android.view.View);
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public android.support.v17.leanback.widget.OnItemViewSelectedListener getOnItemViewSelectedListener();
+ method public void setExpand(boolean);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ }
+
+ public class RowsSupportFragment extends android.support.v17.leanback.app.BaseRowSupportFragment {
+ ctor public RowsSupportFragment();
+ method public void enableRowScaling(boolean);
+ method protected android.support.v17.leanback.widget.VerticalGridView findGridViewFromRoot(android.view.View);
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public android.support.v17.leanback.widget.OnItemViewSelectedListener getOnItemViewSelectedListener();
+ method public void setExpand(boolean);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ }
+
+ public class SearchFragment extends android.app.Fragment {
+ ctor public SearchFragment();
+ method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String);
+ method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String, java.lang.String);
+ method public void displayCompletions(java.util.List<java.lang.String>);
+ method public void displayCompletions(android.view.inputmethod.CompletionInfo[]);
+ method public android.graphics.drawable.Drawable getBadgeDrawable();
+ method public android.content.Intent getRecognizerIntent();
+ method public java.lang.String getTitle();
+ method public static android.support.v17.leanback.app.SearchFragment newInstance(java.lang.String);
+ method public void setBadgeDrawable(android.graphics.drawable.Drawable);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public void setSearchQuery(java.lang.String, boolean);
+ method public void setSearchQuery(android.content.Intent, boolean);
+ method public void setSearchResultProvider(android.support.v17.leanback.app.SearchFragment.SearchResultProvider);
+ method public void setSpeechRecognitionCallback(android.support.v17.leanback.widget.SpeechRecognitionCallback);
+ method public void setTitle(java.lang.String);
+ method public void startRecognition();
+ }
+
+ public static abstract interface SearchFragment.SearchResultProvider {
+ method public abstract android.support.v17.leanback.widget.ObjectAdapter getResultsAdapter();
+ method public abstract boolean onQueryTextChange(java.lang.String);
+ method public abstract boolean onQueryTextSubmit(java.lang.String);
+ }
+
+ public class SearchSupportFragment extends android.support.v4.app.Fragment {
+ ctor public SearchSupportFragment();
+ method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String);
+ method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String, java.lang.String);
+ method public void displayCompletions(java.util.List<java.lang.String>);
+ method public void displayCompletions(android.view.inputmethod.CompletionInfo[]);
+ method public android.graphics.drawable.Drawable getBadgeDrawable();
+ method public android.content.Intent getRecognizerIntent();
+ method public java.lang.String getTitle();
+ method public static android.support.v17.leanback.app.SearchSupportFragment newInstance(java.lang.String);
+ method public void setBadgeDrawable(android.graphics.drawable.Drawable);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public void setSearchQuery(java.lang.String, boolean);
+ method public void setSearchQuery(android.content.Intent, boolean);
+ method public void setSearchResultProvider(android.support.v17.leanback.app.SearchSupportFragment.SearchResultProvider);
+ method public void setSpeechRecognitionCallback(android.support.v17.leanback.widget.SpeechRecognitionCallback);
+ method public void setTitle(java.lang.String);
+ method public void startRecognition();
+ }
+
+ public static abstract interface SearchSupportFragment.SearchResultProvider {
+ method public abstract android.support.v17.leanback.widget.ObjectAdapter getResultsAdapter();
+ method public abstract boolean onQueryTextChange(java.lang.String);
+ method public abstract boolean onQueryTextSubmit(java.lang.String);
+ }
+
+ public class VerticalGridFragment extends android.support.v17.leanback.app.BrandedFragment {
+ ctor public VerticalGridFragment();
+ method protected java.lang.Object createEntranceTransition();
+ method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
+ method public android.support.v17.leanback.widget.VerticalGridPresenter getGridPresenter();
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public void onDestroyView();
+ method public void onStart();
+ method public void onViewCreated(android.view.View, android.os.Bundle);
+ method protected void runEntranceTransition(java.lang.Object);
+ method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public void setGridPresenter(android.support.v17.leanback.widget.VerticalGridPresenter);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public void setSelectedPosition(int);
+ }
+
+ public class VerticalGridSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
+ ctor public VerticalGridSupportFragment();
+ method protected java.lang.Object createEntranceTransition();
+ method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
+ method public android.support.v17.leanback.widget.VerticalGridPresenter getGridPresenter();
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public void onDestroyView();
+ method public void onStart();
+ method public void onViewCreated(android.view.View, android.os.Bundle);
+ method protected void runEntranceTransition(java.lang.Object);
+ method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public void setGridPresenter(android.support.v17.leanback.widget.VerticalGridPresenter);
+ method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public void setSelectedPosition(int);
+ }
+
+}
+
+package android.support.v17.leanback.database {
+
+ public abstract class CursorMapper {
+ ctor public CursorMapper();
+ method protected abstract java.lang.Object bind(android.database.Cursor);
+ method protected abstract void bindColumns(android.database.Cursor);
+ method public java.lang.Object convert(android.database.Cursor);
+ }
+
+}
+
+package android.support.v17.leanback.graphics {
+
+ public final class ColorFilterCache {
+ method public static android.support.v17.leanback.graphics.ColorFilterCache getColorFilterCache(int);
+ method public android.graphics.ColorFilter getFilterForLevel(float);
+ }
+
+ public final class ColorFilterDimmer {
+ method public void applyFilterToView(android.view.View);
+ method public static android.support.v17.leanback.graphics.ColorFilterDimmer create(android.support.v17.leanback.graphics.ColorFilterCache, float, float);
+ method public static android.support.v17.leanback.graphics.ColorFilterDimmer createDefault(android.content.Context);
+ method public android.graphics.ColorFilter getColorFilter();
+ method public android.graphics.Paint getPaint();
+ method public void setActiveLevel(float);
+ }
+
+ public final class ColorOverlayDimmer {
+ method public int applyToColor(int);
+ method public static android.support.v17.leanback.graphics.ColorOverlayDimmer createColorOverlayDimmer(int, float, float);
+ method public static android.support.v17.leanback.graphics.ColorOverlayDimmer createDefault(android.content.Context);
+ method public void drawColorOverlay(android.graphics.Canvas, android.view.View, boolean);
+ method public int getAlpha();
+ method public float getAlphaFloat();
+ method public android.graphics.Paint getPaint();
+ method public boolean needsDraw();
+ method public void setActiveLevel(float);
+ }
+
+}
+
+package android.support.v17.leanback.system {
+
+ public class Settings {
+ method public boolean getBoolean(java.lang.String);
+ method public static android.support.v17.leanback.system.Settings getInstance(android.content.Context);
+ method public void setBoolean(java.lang.String, boolean);
+ field public static final java.lang.String PREFER_STATIC_SHADOWS = "PREFER_STATIC_SHADOWS";
+ }
+
+}
+
+package android.support.v17.leanback.widget {
+
+ public abstract class AbstractDetailsDescriptionPresenter extends android.support.v17.leanback.widget.Presenter {
+ ctor public AbstractDetailsDescriptionPresenter();
+ method protected abstract void onBindDescription(android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter.ViewHolder, java.lang.Object);
+ method public final void onBindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object);
+ method public final android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter.ViewHolder onCreateViewHolder(android.view.ViewGroup);
+ method public void onUnbindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ }
+
+ public static class AbstractDetailsDescriptionPresenter.ViewHolder extends android.support.v17.leanback.widget.Presenter.ViewHolder {
+ ctor public AbstractDetailsDescriptionPresenter.ViewHolder(android.view.View);
+ method public android.widget.TextView getBody();
+ method public android.widget.TextView getSubtitle();
+ method public android.widget.TextView getTitle();
+ }
+
+ public class Action {
+ ctor public Action(long);
+ ctor public Action(long, java.lang.CharSequence);
+ ctor public Action(long, java.lang.CharSequence, java.lang.CharSequence);
+ ctor public Action(long, java.lang.CharSequence, java.lang.CharSequence, android.graphics.drawable.Drawable);
+ method public final void addKeyCode(int);
+ method public final android.graphics.drawable.Drawable getIcon();
+ method public final long getId();
+ method public final java.lang.CharSequence getLabel1();
+ method public final java.lang.CharSequence getLabel2();
+ method public final void removeKeyCode(int);
+ method public final boolean respondsToKeyCode(int);
+ method public final void setIcon(android.graphics.drawable.Drawable);
+ method public final void setId(long);
+ method public final void setLabel1(java.lang.CharSequence);
+ method public final void setLabel2(java.lang.CharSequence);
+ }
+
+ public class ArrayObjectAdapter extends android.support.v17.leanback.widget.ObjectAdapter {
+ ctor public ArrayObjectAdapter(android.support.v17.leanback.widget.PresenterSelector);
+ ctor public ArrayObjectAdapter(android.support.v17.leanback.widget.Presenter);
+ ctor public ArrayObjectAdapter();
+ method public void add(java.lang.Object);
+ method public void add(int, java.lang.Object);
+ method public void addAll(int, java.util.Collection);
+ method public void clear();
+ method public java.lang.Object get(int);
+ method public int indexOf(java.lang.Object);
+ method public void notifyArrayItemRangeChanged(int, int);
+ method public boolean remove(java.lang.Object);
+ method public int removeItems(int, int);
+ method public void replace(int, java.lang.Object);
+ method public int size();
+ method public java.util.List<E> unmodifiableList();
+ }
+
+ public class BaseCardView extends android.widget.FrameLayout {
+ ctor public BaseCardView(android.content.Context);
+ ctor public BaseCardView(android.content.Context, android.util.AttributeSet);
+ ctor public BaseCardView(android.content.Context, android.util.AttributeSet, int);
+ method public int getCardType();
+ method public int getExtraVisibility();
+ method public int getInfoVisibility();
+ method public boolean isSelectedAnimationDelayed();
+ method public void setCardType(int);
+ method public void setExtraVisibility(int);
+ method public void setInfoVisibility(int);
+ method public void setSelectedAnimationDelayed(boolean);
+ field public static final int CARD_REGION_VISIBLE_ACTIVATED = 1; // 0x1
+ field public static final int CARD_REGION_VISIBLE_ALWAYS = 0; // 0x0
+ field public static final int CARD_REGION_VISIBLE_SELECTED = 2; // 0x2
+ field public static final int CARD_TYPE_INFO_OVER = 1; // 0x1
+ field public static final int CARD_TYPE_INFO_UNDER = 2; // 0x2
+ field public static final int CARD_TYPE_INFO_UNDER_WITH_EXTRA = 3; // 0x3
+ field public static final int CARD_TYPE_MAIN_ONLY = 0; // 0x0
+ }
+
+ public static class BaseCardView.LayoutParams extends android.widget.FrameLayout.LayoutParams {
+ ctor public BaseCardView.LayoutParams(android.content.Context, android.util.AttributeSet);
+ ctor public BaseCardView.LayoutParams(int, int);
+ ctor public BaseCardView.LayoutParams(android.view.ViewGroup.LayoutParams);
+ ctor public BaseCardView.LayoutParams(android.support.v17.leanback.widget.BaseCardView.LayoutParams);
+ field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
+ field public static final int VIEW_TYPE_INFO = 1; // 0x1
+ field public static final int VIEW_TYPE_MAIN = 0; // 0x0
+ field public int viewType;
+ }
+
+ public class BrowseFrameLayout extends android.widget.FrameLayout {
+ ctor public BrowseFrameLayout(android.content.Context);
+ ctor public BrowseFrameLayout(android.content.Context, android.util.AttributeSet);
+ ctor public BrowseFrameLayout(android.content.Context, android.util.AttributeSet, int);
+ method public android.support.v17.leanback.widget.BrowseFrameLayout.OnChildFocusListener getOnChildFocusListener();
+ method public android.support.v17.leanback.widget.BrowseFrameLayout.OnFocusSearchListener getOnFocusSearchListener();
+ method public void setOnChildFocusListener(android.support.v17.leanback.widget.BrowseFrameLayout.OnChildFocusListener);
+ method public void setOnFocusSearchListener(android.support.v17.leanback.widget.BrowseFrameLayout.OnFocusSearchListener);
+ }
+
+ public static abstract interface BrowseFrameLayout.OnChildFocusListener {
+ method public abstract void onRequestChildFocus(android.view.View, android.view.View);
+ method public abstract boolean onRequestFocusInDescendants(int, android.graphics.Rect);
+ }
+
+ public static abstract interface BrowseFrameLayout.OnFocusSearchListener {
+ method public abstract android.view.View onFocusSearch(android.view.View, int);
+ }
+
+ public final class ClassPresenterSelector extends android.support.v17.leanback.widget.PresenterSelector {
+ ctor public ClassPresenterSelector();
+ method public void addClassPresenter(java.lang.Class<?>, android.support.v17.leanback.widget.Presenter);
+ method public android.support.v17.leanback.widget.Presenter getPresenter(java.lang.Object);
+ }
+
+ public class ControlButtonPresenterSelector extends android.support.v17.leanback.widget.PresenterSelector {
+ ctor public ControlButtonPresenterSelector();
+ method public android.support.v17.leanback.widget.Presenter getPresenter(java.lang.Object);
+ method public android.support.v17.leanback.widget.Presenter getPrimaryPresenter();
+ method public android.support.v17.leanback.widget.Presenter getSecondaryPresenter();
+ }
+
+ public class CursorObjectAdapter extends android.support.v17.leanback.widget.ObjectAdapter {
+ ctor public CursorObjectAdapter(android.support.v17.leanback.widget.PresenterSelector);
+ ctor public CursorObjectAdapter(android.support.v17.leanback.widget.Presenter);
+ ctor public CursorObjectAdapter();
+ method public void changeCursor(android.database.Cursor);
+ method public void close();
+ method public java.lang.Object get(int);
+ method public final android.database.Cursor getCursor();
+ method public final android.support.v17.leanback.database.CursorMapper getMapper();
+ method protected final void invalidateCache(int);
+ method protected final void invalidateCache(int, int);
+ method public boolean isClosed();
+ method protected void onCursorChanged();
+ method protected void onMapperChanged();
+ method public final void setMapper(android.support.v17.leanback.database.CursorMapper);
+ method public int size();
+ method public android.database.Cursor swapCursor(android.database.Cursor);
+ }
+
+ public class DetailsOverviewLogoPresenter extends android.support.v17.leanback.widget.Presenter {
+ ctor public DetailsOverviewLogoPresenter();
+ method public boolean isBoundToImage(android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.ViewHolder, android.support.v17.leanback.widget.DetailsOverviewRow);
+ method public void onBindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object);
+ method public android.support.v17.leanback.widget.Presenter.ViewHolder onCreateViewHolder(android.view.ViewGroup);
+ method public void onUnbindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public void setContext(android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.ViewHolder, android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder, android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter);
+ }
+
+ public static class DetailsOverviewLogoPresenter.ViewHolder extends android.support.v17.leanback.widget.Presenter.ViewHolder {
+ ctor public DetailsOverviewLogoPresenter.ViewHolder(android.view.View);
+ field protected android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter mParentPresenter;
+ field protected android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder mParentViewHolder;
+ }
+
+ public class DetailsOverviewRow extends android.support.v17.leanback.widget.Row {
+ ctor public DetailsOverviewRow(java.lang.Object);
+ method public final deprecated void addAction(android.support.v17.leanback.widget.Action);
+ method public final deprecated void addAction(int, android.support.v17.leanback.widget.Action);
+ method public android.support.v17.leanback.widget.Action getActionForKeyCode(int);
+ method public final deprecated java.util.List<android.support.v17.leanback.widget.Action> getActions();
+ method public final android.support.v17.leanback.widget.ObjectAdapter getActionsAdapter();
+ method public final android.graphics.drawable.Drawable getImageDrawable();
+ method public final java.lang.Object getItem();
+ method public boolean isImageScaleUpAllowed();
+ method public final deprecated boolean removeAction(android.support.v17.leanback.widget.Action);
+ method public final void setActionsAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public final void setImageBitmap(android.content.Context, android.graphics.Bitmap);
+ method public final void setImageDrawable(android.graphics.drawable.Drawable);
+ method public void setImageScaleUpAllowed(boolean);
+ method public final void setItem(java.lang.Object);
+ }
+
+ public static class DetailsOverviewRow.Listener {
+ ctor public DetailsOverviewRow.Listener();
+ method public void onActionsAdapterChanged(android.support.v17.leanback.widget.DetailsOverviewRow);
+ method public void onImageDrawableChanged(android.support.v17.leanback.widget.DetailsOverviewRow);
+ method public void onItemChanged(android.support.v17.leanback.widget.DetailsOverviewRow);
+ }
+
+ public deprecated class DetailsOverviewRowPresenter extends android.support.v17.leanback.widget.RowPresenter {
+ ctor public DetailsOverviewRowPresenter(android.support.v17.leanback.widget.Presenter);
+ method protected android.support.v17.leanback.widget.RowPresenter.ViewHolder createRowViewHolder(android.view.ViewGroup);
+ method public int getBackgroundColor();
+ method public android.support.v17.leanback.widget.OnActionClickedListener getOnActionClickedListener();
+ method public boolean isStyleLarge();
+ method public final boolean isUsingDefaultSelectEffect();
+ method public void setBackgroundColor(int);
+ method public void setOnActionClickedListener(android.support.v17.leanback.widget.OnActionClickedListener);
+ method public final void setSharedElementEnterTransition(android.app.Activity, java.lang.String, long);
+ method public final void setSharedElementEnterTransition(android.app.Activity, java.lang.String);
+ method public void setStyleLarge(boolean);
+ }
+
+ public final class DetailsOverviewRowPresenter.ViewHolder extends android.support.v17.leanback.widget.RowPresenter.ViewHolder {
+ ctor public DetailsOverviewRowPresenter.ViewHolder(android.view.View, android.support.v17.leanback.widget.Presenter);
+ field public final android.support.v17.leanback.widget.Presenter.ViewHolder mDetailsDescriptionViewHolder;
+ }
+
+ public abstract interface FacetProvider {
+ method public abstract java.lang.Object getFacet(java.lang.Class<?>);
+ }
+
+ public abstract interface FacetProviderAdapter {
+ method public abstract android.support.v17.leanback.widget.FacetProvider getFacetProvider(int);
+ }
+
+ public abstract interface FocusHighlight {
+ field public static final int ZOOM_FACTOR_LARGE = 3; // 0x3
+ field public static final int ZOOM_FACTOR_MEDIUM = 2; // 0x2
+ field public static final int ZOOM_FACTOR_NONE = 0; // 0x0
+ field public static final int ZOOM_FACTOR_SMALL = 1; // 0x1
+ field public static final int ZOOM_FACTOR_XSMALL = 4; // 0x4
+ }
+
+ public class FocusHighlightHelper {
+ ctor public FocusHighlightHelper();
+ method public static void setupBrowseItemFocusHighlight(android.support.v17.leanback.widget.ItemBridgeAdapter, int, boolean);
+ method public static void setupHeaderItemFocusHighlight(android.support.v17.leanback.widget.VerticalGridView);
+ }
+
+ public abstract interface FragmentAnimationProvider {
+ method public abstract void onImeAppearing(java.util.List<android.animation.Animator>);
+ method public abstract void onImeDisappearing(java.util.List<android.animation.Animator>);
+ }
+
+ public class FullWidthDetailsOverviewRowPresenter extends android.support.v17.leanback.widget.RowPresenter {
+ ctor public FullWidthDetailsOverviewRowPresenter(android.support.v17.leanback.widget.Presenter);
+ ctor public FullWidthDetailsOverviewRowPresenter(android.support.v17.leanback.widget.Presenter, android.support.v17.leanback.widget.DetailsOverviewLogoPresenter);
+ method protected android.support.v17.leanback.widget.RowPresenter.ViewHolder createRowViewHolder(android.view.ViewGroup);
+ method public final int getActionsBackgroundColor();
+ method public final int getAlignmentMode();
+ method public final int getBackgroundColor();
+ method public final int getInitialState();
+ method protected int getLayoutResourceId();
+ method public android.support.v17.leanback.widget.OnActionClickedListener getOnActionClickedListener();
+ method public final boolean isParticipatingEntranceTransition();
+ method public final boolean isUsingDefaultSelectEffect();
+ method public final void notifyOnBindLogo(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder);
+ method protected void onLayoutLogo(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder, int, boolean);
+ method protected void onLayoutOverviewFrame(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder, int, boolean);
+ method protected void onStateChanged(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder, int);
+ method public final void setActionsBackgroundColor(int);
+ method public final void setAlignmentMode(int);
+ method public final void setBackgroundColor(int);
+ method public final void setInitialState(int);
+ method public final void setListener(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.Listener);
+ method public void setOnActionClickedListener(android.support.v17.leanback.widget.OnActionClickedListener);
+ method public final void setParticipatingEntranceTransition(boolean);
+ method public final void setState(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder, int);
+ field public static final int ALIGN_MODE_MIDDLE = 1; // 0x1
+ field public static final int ALIGN_MODE_START = 0; // 0x0
+ field public static final int STATE_FULL = 1; // 0x1
+ field public static final int STATE_HALF = 0; // 0x0
+ field public static final int STATE_SMALL = 2; // 0x2
+ field protected int mInitialState;
+ }
+
+ public static abstract class FullWidthDetailsOverviewRowPresenter.Listener {
+ ctor public FullWidthDetailsOverviewRowPresenter.Listener();
+ method public void onBindLogo(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder);
+ }
+
+ public class FullWidthDetailsOverviewRowPresenter.ViewHolder extends android.support.v17.leanback.widget.RowPresenter.ViewHolder {
+ ctor public FullWidthDetailsOverviewRowPresenter.ViewHolder(android.view.View, android.support.v17.leanback.widget.Presenter, android.support.v17.leanback.widget.DetailsOverviewLogoPresenter);
+ method protected android.support.v17.leanback.widget.DetailsOverviewRow.Listener createRowListener();
+ method public final android.view.ViewGroup getActionsRow();
+ method public final android.view.ViewGroup getDetailsDescriptionFrame();
+ method public final android.support.v17.leanback.widget.Presenter.ViewHolder getDetailsDescriptionViewHolder();
+ method public final android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.ViewHolder getLogoViewHolder();
+ method public final android.view.ViewGroup getOverviewView();
+ method public final int getState();
+ field protected final android.support.v17.leanback.widget.DetailsOverviewRow.Listener mRowListener;
+ }
+
+ public class FullWidthDetailsOverviewRowPresenter.ViewHolder.DetailsOverviewRowListener extends android.support.v17.leanback.widget.DetailsOverviewRow.Listener {
+ ctor public FullWidthDetailsOverviewRowPresenter.ViewHolder.DetailsOverviewRowListener();
+ }
+
+ public class FullWidthDetailsOverviewSharedElementHelper extends android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.Listener {
+ ctor public FullWidthDetailsOverviewSharedElementHelper();
+ method public boolean getAutoStartSharedElementTransition();
+ method public void setAutoStartSharedElementTransition(boolean);
+ method public void setSharedElementEnterTransition(android.app.Activity, java.lang.String);
+ method public void setSharedElementEnterTransition(android.app.Activity, java.lang.String, long);
+ method public void startPostponedEnterTransition();
+ }
+
+ public class GuidanceStylist implements android.support.v17.leanback.widget.FragmentAnimationProvider {
+ ctor public GuidanceStylist();
+ method public android.widget.TextView getBreadcrumbView();
+ method public android.widget.TextView getDescriptionView();
+ method public android.widget.ImageView getIconView();
+ method public android.widget.TextView getTitleView();
+ method public android.view.View onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.support.v17.leanback.widget.GuidanceStylist.Guidance);
+ method public void onImeAppearing(java.util.List<android.animation.Animator>);
+ method public void onImeDisappearing(java.util.List<android.animation.Animator>);
+ method public int onProvideLayoutId();
+ }
+
+ public static class GuidanceStylist.Guidance {
+ ctor public GuidanceStylist.Guidance(java.lang.String, java.lang.String, java.lang.String, android.graphics.drawable.Drawable);
+ method public java.lang.String getBreadcrumb();
+ method public java.lang.String getDescription();
+ method public android.graphics.drawable.Drawable getIconDrawable();
+ method public java.lang.String getTitle();
+ }
+
+ public class GuidedAction extends android.support.v17.leanback.widget.Action {
+ method public int getCheckSetId();
+ method public java.lang.CharSequence getDescription();
+ method public java.lang.CharSequence getEditTitle();
+ method public android.content.Intent getIntent();
+ method public java.lang.CharSequence getTitle();
+ method public boolean hasMultilineDescription();
+ method public boolean hasNext();
+ method public boolean infoOnly();
+ method public boolean isChecked();
+ method public boolean isEditTitleUsed();
+ method public boolean isEditable();
+ method public boolean isEnabled();
+ method public void setChecked(boolean);
+ method public void setDescription(java.lang.CharSequence);
+ method public void setEditTitle(java.lang.CharSequence);
+ method public void setEnabled(boolean);
+ method public void setTitle(java.lang.CharSequence);
+ field public static final int DEFAULT_CHECK_SET_ID = 1; // 0x1
+ field public static final int NO_CHECK_SET = 0; // 0x0
+ field public static final int NO_DRAWABLE = 0; // 0x0
+ }
+
+ public static class GuidedAction.Builder {
+ ctor public GuidedAction.Builder();
+ method public android.support.v17.leanback.widget.GuidedAction build();
+ method public android.support.v17.leanback.widget.GuidedAction.Builder checkSetId(int);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder checked(boolean);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder description(java.lang.String);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder editTitle(java.lang.String);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder editable(boolean);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder enabled(boolean);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder hasNext(boolean);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder icon(android.graphics.drawable.Drawable);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder iconResourceId(int, android.content.Context);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder id(long);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder infoOnly(boolean);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder intent(android.content.Intent);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder multilineDescription(boolean);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder title(java.lang.String);
+ }
+
+ public class GuidedActionEditText extends android.widget.EditText implements android.support.v17.leanback.widget.ImeKeyMonitor {
+ ctor public GuidedActionEditText(android.content.Context);
+ ctor public GuidedActionEditText(android.content.Context, android.util.AttributeSet);
+ ctor public GuidedActionEditText(android.content.Context, android.util.AttributeSet, int);
+ method public void setImeKeyListener(android.support.v17.leanback.widget.ImeKeyMonitor.ImeKeyListener);
+ }
+
+ public class GuidedActionsStylist implements android.support.v17.leanback.widget.FragmentAnimationProvider {
+ ctor public GuidedActionsStylist();
+ method public android.support.v17.leanback.widget.VerticalGridView getActionsGridView();
+ method public void onAnimateItemChecked(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
+ method public void onAnimateItemFocused(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
+ method public void onAnimateItemPressed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
+ method public void onBindViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
+ method public android.view.View onCreateView(android.view.LayoutInflater, android.view.ViewGroup);
+ method public android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder onCreateViewHolder(android.view.ViewGroup);
+ method public void onImeAppearing(java.util.List<android.animation.Animator>);
+ method public void onImeDisappearing(java.util.List<android.animation.Animator>);
+ method public int onProvideItemLayoutId();
+ method public int onProvideLayoutId();
+ field protected android.support.v17.leanback.widget.VerticalGridView mActionsGridView;
+ field protected android.view.View mMainView;
+ field protected android.view.View mSelectorView;
+ }
+
+ public static class GuidedActionsStylist.ViewHolder {
+ ctor public GuidedActionsStylist.ViewHolder(android.view.View);
+ method public android.widget.ImageView getCheckmarkView();
+ method public android.widget.ImageView getChevronView();
+ method public android.view.View getContentView();
+ method public android.widget.TextView getDescriptionView();
+ method public android.widget.EditText getEditableTitleView();
+ method public android.widget.ImageView getIconView();
+ method public android.widget.TextView getTitleView();
+ field public final android.view.View view;
+ }
+
+ public class HeaderItem {
+ ctor public HeaderItem(long, java.lang.String);
+ ctor public HeaderItem(java.lang.String);
+ method public final long getId();
+ method public final java.lang.String getName();
+ }
+
+ public class HorizontalGridView extends android.support.v7.widget.RecyclerView {
+ ctor public HorizontalGridView(android.content.Context);
+ ctor public HorizontalGridView(android.content.Context, android.util.AttributeSet);
+ ctor public HorizontalGridView(android.content.Context, android.util.AttributeSet, int);
+ method public final boolean getFadingLeftEdge();
+ method public final int getFadingLeftEdgeLength();
+ method public final int getFadingLeftEdgeOffset();
+ method public final boolean getFadingRightEdge();
+ method public final int getFadingRightEdgeLength();
+ method public final int getFadingRightEdgeOffset();
+ method protected void initAttributes(android.content.Context, android.util.AttributeSet);
+ method public final void setFadingLeftEdge(boolean);
+ method public final void setFadingLeftEdgeLength(int);
+ method public final void setFadingLeftEdgeOffset(int);
+ method public final void setFadingRightEdge(boolean);
+ method public final void setFadingRightEdgeLength(int);
+ method public final void setFadingRightEdgeOffset(int);
+ method public void setNumRows(int);
+ method public void setRowHeight(int);
+ }
+
+ public final class HorizontalHoverCardSwitcher extends android.support.v17.leanback.widget.PresenterSwitcher {
+ ctor public HorizontalHoverCardSwitcher();
+ method protected void insertView(android.view.View);
+ method public void select(android.support.v17.leanback.widget.HorizontalGridView, android.view.View, java.lang.Object);
+ }
+
+ public class ImageCardView extends android.support.v17.leanback.widget.BaseCardView {
+ ctor public ImageCardView(android.content.Context, int);
+ ctor public ImageCardView(android.content.Context, android.util.AttributeSet, int);
+ ctor public ImageCardView(android.content.Context);
+ ctor public ImageCardView(android.content.Context, android.util.AttributeSet);
+ method public android.graphics.drawable.Drawable getBadgeImage();
+ method public java.lang.CharSequence getContentText();
+ method public android.graphics.drawable.Drawable getInfoAreaBackground();
+ method public android.graphics.drawable.Drawable getMainImage();
+ method public final android.widget.ImageView getMainImageView();
+ method public java.lang.CharSequence getTitleText();
+ method public void setBadgeImage(android.graphics.drawable.Drawable);
+ method public void setContentText(java.lang.CharSequence);
+ method public void setInfoAreaBackground(android.graphics.drawable.Drawable);
+ method public void setInfoAreaBackgroundColor(int);
+ method public void setMainImage(android.graphics.drawable.Drawable);
+ method public void setMainImage(android.graphics.drawable.Drawable, boolean);
+ method public void setMainImageAdjustViewBounds(boolean);
+ method public void setMainImageDimensions(int, int);
+ method public void setMainImageScaleType(android.widget.ImageView.ScaleType);
+ method public void setTitleText(java.lang.CharSequence);
+ field public static final int CARD_TYPE_FLAG_CONTENT = 2; // 0x2
+ field public static final int CARD_TYPE_FLAG_ICON_LEFT = 8; // 0x8
+ field public static final int CARD_TYPE_FLAG_ICON_RIGHT = 4; // 0x4
+ field public static final int CARD_TYPE_FLAG_IMAGE_ONLY = 0; // 0x0
+ field public static final int CARD_TYPE_FLAG_TITLE = 1; // 0x1
+ }
+
+ public abstract interface ImeKeyMonitor {
+ method public abstract void setImeKeyListener(android.support.v17.leanback.widget.ImeKeyMonitor.ImeKeyListener);
+ }
+
+ public static abstract interface ImeKeyMonitor.ImeKeyListener {
+ method public abstract boolean onKeyPreIme(android.widget.EditText, int, android.view.KeyEvent);
+ }
+
+ public final class ItemAlignmentFacet {
+ ctor public ItemAlignmentFacet();
+ method public android.support.v17.leanback.widget.ItemAlignmentFacet.ItemAlignmentDef[] getAlignmentDefs();
+ method public boolean isMultiAlignment();
+ method public void setAlignmentDefs(android.support.v17.leanback.widget.ItemAlignmentFacet.ItemAlignmentDef[]);
+ field public static final float ITEM_ALIGN_OFFSET_PERCENT_DISABLED = -1.0f;
+ }
+
+ public static class ItemAlignmentFacet.ItemAlignmentDef {
+ ctor public ItemAlignmentFacet.ItemAlignmentDef();
+ method public final int getItemAlignmentFocusViewId();
+ method public final int getItemAlignmentOffset();
+ method public final float getItemAlignmentOffsetPercent();
+ method public final int getItemAlignmentViewId();
+ method public final boolean isItemAlignmentOffsetWithPadding();
+ method public final void setItemAlignmentFocusViewId(int);
+ method public final void setItemAlignmentOffset(int);
+ method public final void setItemAlignmentOffsetPercent(float);
+ method public final void setItemAlignmentOffsetWithPadding(boolean);
+ method public final void setItemAlignmentViewId(int);
+ }
+
+ public class ItemBridgeAdapter extends android.support.v7.widget.RecyclerView.Adapter implements android.support.v17.leanback.widget.FacetProviderAdapter {
+ ctor public ItemBridgeAdapter(android.support.v17.leanback.widget.ObjectAdapter, android.support.v17.leanback.widget.PresenterSelector);
+ ctor public ItemBridgeAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ ctor public ItemBridgeAdapter();
+ method public void clear();
+ method public android.support.v17.leanback.widget.FacetProvider getFacetProvider(int);
+ method public int getItemCount();
+ method public java.util.ArrayList<android.support.v17.leanback.widget.Presenter> getPresenterMapper();
+ method public android.support.v17.leanback.widget.ItemBridgeAdapter.Wrapper getWrapper();
+ method protected void onAddPresenter(android.support.v17.leanback.widget.Presenter, int);
+ method protected void onAttachedToWindow(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ method protected void onBind(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ method public final void onBindViewHolder(android.support.v7.widget.RecyclerView.ViewHolder, int);
+ method protected void onCreate(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ method public final android.support.v7.widget.RecyclerView.ViewHolder onCreateViewHolder(android.view.ViewGroup, int);
+ method protected void onDetachedFromWindow(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ method protected void onUnbind(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ method public final void onViewAttachedToWindow(android.support.v7.widget.RecyclerView.ViewHolder);
+ method public final void onViewDetachedFromWindow(android.support.v7.widget.RecyclerView.ViewHolder);
+ method public final void onViewRecycled(android.support.v7.widget.RecyclerView.ViewHolder);
+ method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public void setAdapterListener(android.support.v17.leanback.widget.ItemBridgeAdapter.AdapterListener);
+ method public void setPresenterMapper(java.util.ArrayList<android.support.v17.leanback.widget.Presenter>);
+ method public void setWrapper(android.support.v17.leanback.widget.ItemBridgeAdapter.Wrapper);
+ }
+
+ public static class ItemBridgeAdapter.AdapterListener {
+ ctor public ItemBridgeAdapter.AdapterListener();
+ method public void onAddPresenter(android.support.v17.leanback.widget.Presenter, int);
+ method public void onAttachedToWindow(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ method public void onBind(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ method public void onCreate(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ method public void onDetachedFromWindow(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ method public void onUnbind(android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder);
+ }
+
+ public class ItemBridgeAdapter.ViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder implements android.support.v17.leanback.widget.FacetProvider {
+ method public final java.lang.Object getExtraObject();
+ method public java.lang.Object getFacet(java.lang.Class<?>);
+ method public final java.lang.Object getItem();
+ method public final android.support.v17.leanback.widget.Presenter getPresenter();
+ method public final android.support.v17.leanback.widget.Presenter.ViewHolder getViewHolder();
+ method public void setExtraObject(java.lang.Object);
+ }
+
+ public static abstract class ItemBridgeAdapter.Wrapper {
+ ctor public ItemBridgeAdapter.Wrapper();
+ method public abstract android.view.View createWrapper(android.view.View);
+ method public abstract void wrap(android.view.View, android.view.View);
+ }
+
+ public class ItemBridgeAdapterShadowOverlayWrapper extends android.support.v17.leanback.widget.ItemBridgeAdapter.Wrapper {
+ ctor public ItemBridgeAdapterShadowOverlayWrapper(android.support.v17.leanback.widget.ShadowOverlayHelper);
+ method public android.view.View createWrapper(android.view.View);
+ method public void wrap(android.view.View, android.view.View);
+ }
+
+ public class ListRow extends android.support.v17.leanback.widget.Row {
+ ctor public ListRow(android.support.v17.leanback.widget.HeaderItem, android.support.v17.leanback.widget.ObjectAdapter);
+ ctor public ListRow(long, android.support.v17.leanback.widget.HeaderItem, android.support.v17.leanback.widget.ObjectAdapter);
+ ctor public ListRow(android.support.v17.leanback.widget.ObjectAdapter);
+ method public final android.support.v17.leanback.widget.ObjectAdapter getAdapter();
+ }
+
+ public final class ListRowHoverCardView extends android.widget.LinearLayout {
+ ctor public ListRowHoverCardView(android.content.Context);
+ ctor public ListRowHoverCardView(android.content.Context, android.util.AttributeSet);
+ ctor public ListRowHoverCardView(android.content.Context, android.util.AttributeSet, int);
+ method public final java.lang.CharSequence getDescription();
+ method public final java.lang.CharSequence getTitle();
+ method public final void setDescription(java.lang.CharSequence);
+ method public final void setTitle(java.lang.CharSequence);
+ }
+
+ public class ListRowPresenter extends android.support.v17.leanback.widget.RowPresenter {
+ ctor public ListRowPresenter();
+ ctor public ListRowPresenter(int);
+ ctor public ListRowPresenter(int, boolean);
+ method public final boolean areChildRoundedCornersEnabled();
+ method protected android.support.v17.leanback.widget.RowPresenter.ViewHolder createRowViewHolder(android.view.ViewGroup);
+ method protected android.support.v17.leanback.widget.ShadowOverlayHelper.Options createShadowOverlayOptions();
+ method public final void enableChildRoundedCorners(boolean);
+ method public int getExpandedRowHeight();
+ method public final int getFocusZoomFactor();
+ method public final android.support.v17.leanback.widget.PresenterSelector getHoverCardPresenterSelector();
+ method public int getRecycledPoolSize(android.support.v17.leanback.widget.Presenter);
+ method public int getRowHeight();
+ method public final boolean getShadowEnabled();
+ method public final deprecated int getZoomFactor();
+ method public final boolean isFocusDimmerUsed();
+ method public final boolean isKeepChildForeground();
+ method public boolean isUsingDefaultListSelectEffect();
+ method public final boolean isUsingDefaultSelectEffect();
+ method public boolean isUsingDefaultShadow();
+ method public boolean isUsingZOrder(android.content.Context);
+ method public void setExpandedRowHeight(int);
+ method public final void setHoverCardPresenterSelector(android.support.v17.leanback.widget.PresenterSelector);
+ method public final void setKeepChildForeground(boolean);
+ method public void setRecycledPoolSize(android.support.v17.leanback.widget.Presenter, int);
+ method public void setRowHeight(int);
+ method public final void setShadowEnabled(boolean);
+ }
+
+ public static class ListRowPresenter.ViewHolder extends android.support.v17.leanback.widget.RowPresenter.ViewHolder {
+ ctor public ListRowPresenter.ViewHolder(android.view.View, android.support.v17.leanback.widget.HorizontalGridView, android.support.v17.leanback.widget.ListRowPresenter);
+ method public final android.support.v17.leanback.widget.ItemBridgeAdapter getBridgeAdapter();
+ method public final android.support.v17.leanback.widget.HorizontalGridView getGridView();
+ method public final android.support.v17.leanback.widget.ListRowPresenter getListRowPresenter();
+ }
+
+ public final class ListRowView extends android.widget.LinearLayout {
+ ctor public ListRowView(android.content.Context);
+ ctor public ListRowView(android.content.Context, android.util.AttributeSet);
+ ctor public ListRowView(android.content.Context, android.util.AttributeSet, int);
+ method public android.support.v17.leanback.widget.HorizontalGridView getGridView();
+ }
+
+ public abstract class ObjectAdapter {
+ ctor public ObjectAdapter(android.support.v17.leanback.widget.PresenterSelector);
+ ctor public ObjectAdapter(android.support.v17.leanback.widget.Presenter);
+ ctor public ObjectAdapter();
+ method public abstract java.lang.Object get(int);
+ method public long getId(int);
+ method public final android.support.v17.leanback.widget.Presenter getPresenter(java.lang.Object);
+ method public final android.support.v17.leanback.widget.PresenterSelector getPresenterSelector();
+ method public final boolean hasStableIds();
+ method protected final void notifyChanged();
+ method protected final void notifyItemRangeChanged(int, int);
+ method protected final void notifyItemRangeInserted(int, int);
+ method protected final void notifyItemRangeRemoved(int, int);
+ method protected void onHasStableIdsChanged();
+ method protected void onPresenterSelectorChanged();
+ method public final void registerObserver(android.support.v17.leanback.widget.ObjectAdapter.DataObserver);
+ method public final void setHasStableIds(boolean);
+ method public final void setPresenterSelector(android.support.v17.leanback.widget.PresenterSelector);
+ method public abstract int size();
+ method public final void unregisterAllObservers();
+ method public final void unregisterObserver(android.support.v17.leanback.widget.ObjectAdapter.DataObserver);
+ field public static final int NO_ID = -1; // 0xffffffff
+ }
+
+ public static abstract class ObjectAdapter.DataObserver {
+ ctor public ObjectAdapter.DataObserver();
+ method public void onChanged();
+ method public void onItemRangeChanged(int, int);
+ method public void onItemRangeInserted(int, int);
+ method public void onItemRangeRemoved(int, int);
+ }
+
+ public abstract interface OnActionClickedListener {
+ method public abstract void onActionClicked(android.support.v17.leanback.widget.Action);
+ }
+
+ public abstract interface OnChildLaidOutListener {
+ method public abstract void onChildLaidOut(android.view.ViewGroup, android.view.View, int, long);
+ }
+
+ public abstract deprecated interface OnChildSelectedListener {
+ method public abstract void onChildSelected(android.view.ViewGroup, android.view.View, int, long);
+ }
+
+ public abstract class OnChildViewHolderSelectedListener {
+ ctor public OnChildViewHolderSelectedListener();
+ method public void onChildViewHolderSelected(android.support.v7.widget.RecyclerView, android.support.v7.widget.RecyclerView.ViewHolder, int, int);
+ }
+
+ public abstract interface OnItemViewClickedListener {
+ method public abstract void onItemClicked(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object, android.support.v17.leanback.widget.RowPresenter.ViewHolder, android.support.v17.leanback.widget.Row);
+ }
+
+ public abstract interface OnItemViewSelectedListener {
+ method public abstract void onItemSelected(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object, android.support.v17.leanback.widget.RowPresenter.ViewHolder, android.support.v17.leanback.widget.Row);
+ }
+
+ public class PlaybackControlsRow extends android.support.v17.leanback.widget.Row {
+ ctor public PlaybackControlsRow(java.lang.Object);
+ ctor public PlaybackControlsRow();
+ method public android.support.v17.leanback.widget.Action getActionForKeyCode(int);
+ method public android.support.v17.leanback.widget.Action getActionForKeyCode(android.support.v17.leanback.widget.ObjectAdapter, int);
+ method public int getBufferedProgress();
+ method public int getCurrentTime();
+ method public final android.graphics.drawable.Drawable getImageDrawable();
+ method public final java.lang.Object getItem();
+ method public final android.support.v17.leanback.widget.ObjectAdapter getPrimaryActionsAdapter();
+ method public final android.support.v17.leanback.widget.ObjectAdapter getSecondaryActionsAdapter();
+ method public int getTotalTime();
+ method public void setBufferedProgress(int);
+ method public void setCurrentTime(int);
+ method public final void setImageBitmap(android.content.Context, android.graphics.Bitmap);
+ method public final void setImageDrawable(android.graphics.drawable.Drawable);
+ method public final void setPrimaryActionsAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public final void setSecondaryActionsAdapter(android.support.v17.leanback.widget.ObjectAdapter);
+ method public void setTotalTime(int);
+ }
+
+ public static class PlaybackControlsRow.ClosedCaptioningAction extends android.support.v17.leanback.widget.PlaybackControlsRow.MultiAction {
+ ctor public PlaybackControlsRow.ClosedCaptioningAction(android.content.Context);
+ ctor public PlaybackControlsRow.ClosedCaptioningAction(android.content.Context, int);
+ field public static int OFF;
+ field public static int ON;
+ }
+
+ public static class PlaybackControlsRow.FastForwardAction extends android.support.v17.leanback.widget.PlaybackControlsRow.MultiAction {
+ ctor public PlaybackControlsRow.FastForwardAction(android.content.Context);
+ ctor public PlaybackControlsRow.FastForwardAction(android.content.Context, int);
+ }
+
+ public static class PlaybackControlsRow.HighQualityAction extends android.support.v17.leanback.widget.PlaybackControlsRow.MultiAction {
+ ctor public PlaybackControlsRow.HighQualityAction(android.content.Context);
+ ctor public PlaybackControlsRow.HighQualityAction(android.content.Context, int);
+ field public static int OFF;
+ field public static int ON;
+ }
+
+ public static class PlaybackControlsRow.MoreActions extends android.support.v17.leanback.widget.Action {
+ ctor public PlaybackControlsRow.MoreActions(android.content.Context);
+ }
+
+ public static abstract class PlaybackControlsRow.MultiAction extends android.support.v17.leanback.widget.Action {
+ ctor public PlaybackControlsRow.MultiAction(int);
+ method public int getActionCount();
+ method public android.graphics.drawable.Drawable getDrawable(int);
+ method public int getIndex();
+ method public java.lang.String getLabel(int);
+ method public java.lang.String getSecondaryLabel(int);
+ method public void nextIndex();
+ method public void setDrawables(android.graphics.drawable.Drawable[]);
+ method public void setIndex(int);
+ method public void setLabels(java.lang.String[]);
+ method public void setSecondaryLabels(java.lang.String[]);
+ }
+
+ public static class PlaybackControlsRow.PlayPauseAction extends android.support.v17.leanback.widget.PlaybackControlsRow.MultiAction {
+ ctor public PlaybackControlsRow.PlayPauseAction(android.content.Context);
+ field public static int PAUSE;
+ field public static int PLAY;
+ }
+
+ public static class PlaybackControlsRow.RepeatAction extends android.support.v17.leanback.widget.PlaybackControlsRow.MultiAction {
+ ctor public PlaybackControlsRow.RepeatAction(android.content.Context);
+ ctor public PlaybackControlsRow.RepeatAction(android.content.Context, int);
+ ctor public PlaybackControlsRow.RepeatAction(android.content.Context, int, int);
+ field public static int ALL;
+ field public static int NONE;
+ field public static int ONE;
+ }
+
+ public static class PlaybackControlsRow.RewindAction extends android.support.v17.leanback.widget.PlaybackControlsRow.MultiAction {
+ ctor public PlaybackControlsRow.RewindAction(android.content.Context);
+ ctor public PlaybackControlsRow.RewindAction(android.content.Context, int);
+ }
+
+ public static class PlaybackControlsRow.ShuffleAction extends android.support.v17.leanback.widget.PlaybackControlsRow.MultiAction {
+ ctor public PlaybackControlsRow.ShuffleAction(android.content.Context);
+ ctor public PlaybackControlsRow.ShuffleAction(android.content.Context, int);
+ field public static int OFF;
+ field public static int ON;
+ }
+
+ public static class PlaybackControlsRow.SkipNextAction extends android.support.v17.leanback.widget.Action {
+ ctor public PlaybackControlsRow.SkipNextAction(android.content.Context);
+ }
+
+ public static class PlaybackControlsRow.SkipPreviousAction extends android.support.v17.leanback.widget.Action {
+ ctor public PlaybackControlsRow.SkipPreviousAction(android.content.Context);
+ }
+
+ public static abstract class PlaybackControlsRow.ThumbsAction extends android.support.v17.leanback.widget.PlaybackControlsRow.MultiAction {
+ ctor public PlaybackControlsRow.ThumbsAction(int, android.content.Context, int, int);
+ field public static int OUTLINE;
+ field public static int SOLID;
+ }
+
+ public static class PlaybackControlsRow.ThumbsDownAction extends android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsAction {
+ ctor public PlaybackControlsRow.ThumbsDownAction(android.content.Context);
+ }
+
+ public static class PlaybackControlsRow.ThumbsUpAction extends android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsAction {
+ ctor public PlaybackControlsRow.ThumbsUpAction(android.content.Context);
+ }
+
+ public class PlaybackControlsRowPresenter extends android.support.v17.leanback.widget.RowPresenter {
+ ctor public PlaybackControlsRowPresenter(android.support.v17.leanback.widget.Presenter);
+ ctor public PlaybackControlsRowPresenter();
+ method public boolean areSecondaryActionsHidden();
+ method protected android.support.v17.leanback.widget.RowPresenter.ViewHolder createRowViewHolder(android.view.ViewGroup);
+ method public int getBackgroundColor();
+ method public android.support.v17.leanback.widget.OnActionClickedListener getOnActionClickedListener();
+ method public int getProgressColor();
+ method public void setBackgroundColor(int);
+ method public void setOnActionClickedListener(android.support.v17.leanback.widget.OnActionClickedListener);
+ method public void setProgressColor(int);
+ method public void setSecondaryActionsHidden(boolean);
+ method public void showBottomSpace(android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder, boolean);
+ method public void showPrimaryActions(android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder);
+ }
+
+ public class PlaybackControlsRowPresenter.ViewHolder extends android.support.v17.leanback.widget.RowPresenter.ViewHolder {
+ field public final android.support.v17.leanback.widget.Presenter.ViewHolder mDescriptionViewHolder;
+ }
+
+ public abstract class Presenter implements android.support.v17.leanback.widget.FacetProvider {
+ ctor public Presenter();
+ method protected static void cancelAnimationsRecursive(android.view.View);
+ method public final java.lang.Object getFacet(java.lang.Class<?>);
+ method public abstract void onBindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object);
+ method public abstract android.support.v17.leanback.widget.Presenter.ViewHolder onCreateViewHolder(android.view.ViewGroup);
+ method public abstract void onUnbindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public void onViewAttachedToWindow(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public void onViewDetachedFromWindow(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public final void setFacet(java.lang.Class<?>, java.lang.Object);
+ method public void setOnClickListener(android.support.v17.leanback.widget.Presenter.ViewHolder, android.view.View.OnClickListener);
+ }
+
+ public static class Presenter.ViewHolder implements android.support.v17.leanback.widget.FacetProvider {
+ ctor public Presenter.ViewHolder(android.view.View);
+ method public final java.lang.Object getFacet(java.lang.Class<?>);
+ method public final void setFacet(java.lang.Class<?>, java.lang.Object);
+ field public final android.view.View view;
+ }
+
+ public abstract class PresenterSelector {
+ ctor public PresenterSelector();
+ method public abstract android.support.v17.leanback.widget.Presenter getPresenter(java.lang.Object);
+ method public android.support.v17.leanback.widget.Presenter[] getPresenters();
+ }
+
+ public abstract class PresenterSwitcher {
+ ctor public PresenterSwitcher();
+ method public void clear();
+ method public final android.view.ViewGroup getParentViewGroup();
+ method public void init(android.view.ViewGroup, android.support.v17.leanback.widget.PresenterSelector);
+ method protected abstract void insertView(android.view.View);
+ method protected void onViewSelected(android.view.View);
+ method public void select(java.lang.Object);
+ method protected void showView(android.view.View, boolean);
+ method public void unselect();
+ }
+
+ public class Row {
+ ctor public Row(long, android.support.v17.leanback.widget.HeaderItem);
+ ctor public Row(android.support.v17.leanback.widget.HeaderItem);
+ ctor public Row();
+ method public final android.support.v17.leanback.widget.HeaderItem getHeaderItem();
+ method public final long getId();
+ method public final void setHeaderItem(android.support.v17.leanback.widget.HeaderItem);
+ method public final void setId(long);
+ }
+
+ public class RowHeaderPresenter extends android.support.v17.leanback.widget.Presenter {
+ ctor public RowHeaderPresenter();
+ method protected static float getFontDescent(android.widget.TextView, android.graphics.Paint);
+ method public int getSpaceUnderBaseline(android.support.v17.leanback.widget.RowHeaderPresenter.ViewHolder);
+ method public boolean isNullItemVisibilityGone();
+ method public void onBindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object);
+ method public android.support.v17.leanback.widget.Presenter.ViewHolder onCreateViewHolder(android.view.ViewGroup);
+ method protected void onSelectLevelChanged(android.support.v17.leanback.widget.RowHeaderPresenter.ViewHolder);
+ method public void onUnbindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public void setNullItemVisibilityGone(boolean);
+ method public final void setSelectLevel(android.support.v17.leanback.widget.RowHeaderPresenter.ViewHolder, float);
+ }
+
+ public static class RowHeaderPresenter.ViewHolder extends android.support.v17.leanback.widget.Presenter.ViewHolder {
+ ctor public RowHeaderPresenter.ViewHolder(android.view.View);
+ method public final float getSelectLevel();
+ }
+
+ public final class RowHeaderView extends android.widget.TextView {
+ ctor public RowHeaderView(android.content.Context);
+ ctor public RowHeaderView(android.content.Context, android.util.AttributeSet);
+ ctor public RowHeaderView(android.content.Context, android.util.AttributeSet, int);
+ }
+
+ public abstract class RowPresenter extends android.support.v17.leanback.widget.Presenter {
+ ctor public RowPresenter();
+ method protected abstract android.support.v17.leanback.widget.RowPresenter.ViewHolder createRowViewHolder(android.view.ViewGroup);
+ method protected void dispatchItemSelectedListener(android.support.v17.leanback.widget.RowPresenter.ViewHolder, boolean);
+ method public void freeze(android.support.v17.leanback.widget.RowPresenter.ViewHolder, boolean);
+ method public final android.support.v17.leanback.widget.RowHeaderPresenter getHeaderPresenter();
+ method public final android.support.v17.leanback.widget.RowPresenter.ViewHolder getRowViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public final boolean getSelectEffectEnabled();
+ method public final float getSelectLevel(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public final int getSyncActivatePolicy();
+ method protected void initializeRowViewHolder(android.support.v17.leanback.widget.RowPresenter.ViewHolder);
+ method protected boolean isClippingChildren();
+ method public boolean isUsingDefaultSelectEffect();
+ method protected void onBindRowViewHolder(android.support.v17.leanback.widget.RowPresenter.ViewHolder, java.lang.Object);
+ method public final void onBindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object);
+ method public final android.support.v17.leanback.widget.Presenter.ViewHolder onCreateViewHolder(android.view.ViewGroup);
+ method protected void onRowViewAttachedToWindow(android.support.v17.leanback.widget.RowPresenter.ViewHolder);
+ method protected void onRowViewDetachedFromWindow(android.support.v17.leanback.widget.RowPresenter.ViewHolder);
+ method protected void onRowViewExpanded(android.support.v17.leanback.widget.RowPresenter.ViewHolder, boolean);
+ method protected void onRowViewSelected(android.support.v17.leanback.widget.RowPresenter.ViewHolder, boolean);
+ method protected void onSelectLevelChanged(android.support.v17.leanback.widget.RowPresenter.ViewHolder);
+ method protected void onUnbindRowViewHolder(android.support.v17.leanback.widget.RowPresenter.ViewHolder);
+ method public final void onUnbindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public final void onViewAttachedToWindow(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public final void onViewDetachedFromWindow(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public void setEntranceTransitionState(android.support.v17.leanback.widget.RowPresenter.ViewHolder, boolean);
+ method public final void setHeaderPresenter(android.support.v17.leanback.widget.RowHeaderPresenter);
+ method public final void setRowViewExpanded(android.support.v17.leanback.widget.Presenter.ViewHolder, boolean);
+ method public final void setRowViewSelected(android.support.v17.leanback.widget.Presenter.ViewHolder, boolean);
+ method public final void setSelectEffectEnabled(boolean);
+ method public final void setSelectLevel(android.support.v17.leanback.widget.Presenter.ViewHolder, float);
+ method public final void setSyncActivatePolicy(int);
+ field public static final int SYNC_ACTIVATED_CUSTOM = 0; // 0x0
+ field public static final int SYNC_ACTIVATED_TO_EXPANDED = 1; // 0x1
+ field public static final int SYNC_ACTIVATED_TO_EXPANDED_AND_SELECTED = 3; // 0x3
+ field public static final int SYNC_ACTIVATED_TO_SELECTED = 2; // 0x2
+ }
+
+ public static class RowPresenter.ViewHolder extends android.support.v17.leanback.widget.Presenter.ViewHolder {
+ ctor public RowPresenter.ViewHolder(android.view.View);
+ method public final android.support.v17.leanback.widget.RowHeaderPresenter.ViewHolder getHeaderViewHolder();
+ method public final android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public final android.support.v17.leanback.widget.OnItemViewSelectedListener getOnItemViewSelectedListener();
+ method public android.view.View.OnKeyListener getOnKeyListener();
+ method public final android.support.v17.leanback.widget.Row getRow();
+ method public final float getSelectLevel();
+ method public final boolean isExpanded();
+ method public final boolean isSelected();
+ method public final void setActivated(boolean);
+ method public final void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public final void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public void setOnKeyListener(android.view.View.OnKeyListener);
+ method public final void syncActivatedStatus(android.view.View);
+ field protected final android.support.v17.leanback.graphics.ColorOverlayDimmer mColorDimmer;
+ }
+
+ public class SearchBar extends android.widget.RelativeLayout {
+ ctor public SearchBar(android.content.Context);
+ ctor public SearchBar(android.content.Context, android.util.AttributeSet);
+ ctor public SearchBar(android.content.Context, android.util.AttributeSet, int);
+ method public void displayCompletions(java.util.List<java.lang.String>);
+ method public void displayCompletions(android.view.inputmethod.CompletionInfo[]);
+ method public android.graphics.drawable.Drawable getBadgeDrawable();
+ method public java.lang.CharSequence getHint();
+ method public java.lang.String getTitle();
+ method public void setBadgeDrawable(android.graphics.drawable.Drawable);
+ method public void setSearchBarListener(android.support.v17.leanback.widget.SearchBar.SearchBarListener);
+ method public void setSearchQuery(java.lang.String);
+ method public void setSpeechRecognitionCallback(android.support.v17.leanback.widget.SpeechRecognitionCallback);
+ method public void setSpeechRecognizer(android.speech.SpeechRecognizer);
+ method public void setTitle(java.lang.String);
+ method public void startRecognition();
+ method public void stopRecognition();
+ }
+
+ public static abstract interface SearchBar.SearchBarListener {
+ method public abstract void onKeyboardDismiss(java.lang.String);
+ method public abstract void onSearchQueryChange(java.lang.String);
+ method public abstract void onSearchQuerySubmit(java.lang.String);
+ }
+
+ public class SearchEditText extends android.support.v17.leanback.widget.StreamingTextView {
+ ctor public SearchEditText(android.content.Context);
+ ctor public SearchEditText(android.content.Context, android.util.AttributeSet);
+ ctor public SearchEditText(android.content.Context, android.util.AttributeSet, int);
+ method public void setOnKeyboardDismissListener(android.support.v17.leanback.widget.SearchEditText.OnKeyboardDismissListener);
+ }
+
+ public static abstract interface SearchEditText.OnKeyboardDismissListener {
+ method public abstract void onKeyboardDismiss();
+ }
+
+ public class SearchOrbView extends android.widget.FrameLayout implements android.view.View.OnClickListener {
+ ctor public SearchOrbView(android.content.Context);
+ ctor public SearchOrbView(android.content.Context, android.util.AttributeSet);
+ ctor public SearchOrbView(android.content.Context, android.util.AttributeSet, int);
+ method public void enableOrbColorAnimation(boolean);
+ method public int getOrbColor();
+ method public android.support.v17.leanback.widget.SearchOrbView.Colors getOrbColors();
+ method public android.graphics.drawable.Drawable getOrbIcon();
+ method public void onClick(android.view.View);
+ method public void setOnOrbClickedListener(android.view.View.OnClickListener);
+ method public void setOrbColor(int);
+ method public deprecated void setOrbColor(int, int);
+ method public void setOrbColors(android.support.v17.leanback.widget.SearchOrbView.Colors);
+ method public void setOrbIcon(android.graphics.drawable.Drawable);
+ }
+
+ public static class SearchOrbView.Colors {
+ ctor public SearchOrbView.Colors(int);
+ ctor public SearchOrbView.Colors(int, int);
+ ctor public SearchOrbView.Colors(int, int, int);
+ method public static int getBrightColor(int);
+ field public int brightColor;
+ field public int color;
+ field public int iconColor;
+ }
+
+ public class ShadowOverlayContainer extends android.widget.FrameLayout {
+ ctor public ShadowOverlayContainer(android.content.Context);
+ ctor public ShadowOverlayContainer(android.content.Context, android.util.AttributeSet);
+ ctor public ShadowOverlayContainer(android.content.Context, android.util.AttributeSet, int);
+ method public int getShadowType();
+ method public android.view.View getWrappedView();
+ method public deprecated void initialize(boolean, boolean);
+ method public deprecated void initialize(boolean, boolean, boolean);
+ method public static void prepareParentForShadow(android.view.ViewGroup);
+ method public void setOverlayColor(int);
+ method public void setShadowFocusLevel(float);
+ method public static boolean supportsDynamicShadow();
+ method public static boolean supportsShadow();
+ method public void useDynamicShadow();
+ method public void useDynamicShadow(float, float);
+ method public void useStaticShadow();
+ method public void wrap(android.view.View);
+ field public static final int SHADOW_DYNAMIC = 3; // 0x3
+ field public static final int SHADOW_NONE = 1; // 0x1
+ field public static final int SHADOW_STATIC = 2; // 0x2
+ }
+
+ public final class ShadowOverlayHelper {
+ method public android.support.v17.leanback.widget.ShadowOverlayContainer createShadowOverlayContainer(android.content.Context);
+ method public int getShadowType();
+ method public boolean needsOverlay();
+ method public boolean needsRoundedCorner();
+ method public boolean needsWrapper();
+ method public void onViewCreated(android.view.View);
+ method public void prepareParentForShadow(android.view.ViewGroup);
+ method public static void setNoneWrapperOverlayColor(android.view.View, int);
+ method public static void setNoneWrapperShadowFocusLevel(android.view.View, float);
+ method public void setOverlayColor(android.view.View, int);
+ method public void setShadowFocusLevel(android.view.View, float);
+ method public static boolean supportsDynamicShadow();
+ method public static boolean supportsForeground();
+ method public static boolean supportsRoundedCorner();
+ method public static boolean supportsShadow();
+ field public static final int SHADOW_DYNAMIC = 3; // 0x3
+ field public static final int SHADOW_NONE = 1; // 0x1
+ field public static final int SHADOW_STATIC = 2; // 0x2
+ }
+
+ public static final class ShadowOverlayHelper.Builder {
+ ctor public ShadowOverlayHelper.Builder();
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper build(android.content.Context);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder keepForegroundDrawable(boolean);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder needsOverlay(boolean);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder needsRoundedCorner(boolean);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder needsShadow(boolean);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder options(android.support.v17.leanback.widget.ShadowOverlayHelper.Options);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder preferZOrder(boolean);
+ }
+
+ public static final class ShadowOverlayHelper.Options {
+ ctor public ShadowOverlayHelper.Options();
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Options dynamicShadowZ(float, float);
+ method public final float getDynamicShadowFocusedZ();
+ method public final float getDynamicShadowUnfocusedZ();
+ method public final int getRoundedCornerRadius();
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Options roundedCornerRadius(int);
+ field public static final android.support.v17.leanback.widget.ShadowOverlayHelper.Options DEFAULT;
+ }
+
+ public final class SinglePresenterSelector extends android.support.v17.leanback.widget.PresenterSelector {
+ ctor public SinglePresenterSelector(android.support.v17.leanback.widget.Presenter);
+ method public android.support.v17.leanback.widget.Presenter getPresenter(java.lang.Object);
+ }
+
+ public class SparseArrayObjectAdapter extends android.support.v17.leanback.widget.ObjectAdapter {
+ ctor public SparseArrayObjectAdapter(android.support.v17.leanback.widget.PresenterSelector);
+ ctor public SparseArrayObjectAdapter(android.support.v17.leanback.widget.Presenter);
+ ctor public SparseArrayObjectAdapter();
+ method public void clear(int);
+ method public void clear();
+ method public java.lang.Object get(int);
+ method public int indexOf(java.lang.Object);
+ method public int indexOf(int);
+ method public java.lang.Object lookup(int);
+ method public void notifyArrayItemRangeChanged(int, int);
+ method public void set(int, java.lang.Object);
+ method public int size();
+ }
+
+ public class SpeechOrbView extends android.support.v17.leanback.widget.SearchOrbView {
+ ctor public SpeechOrbView(android.content.Context);
+ ctor public SpeechOrbView(android.content.Context, android.util.AttributeSet);
+ ctor public SpeechOrbView(android.content.Context, android.util.AttributeSet, int);
+ method public void setSoundLevel(int);
+ method public void showListening();
+ method public void showNotListening();
+ }
+
+ public abstract interface SpeechRecognitionCallback {
+ method public abstract void recognizeSpeech();
+ }
+
+ class StreamingTextView extends android.widget.EditText {
+ ctor public StreamingTextView(android.content.Context, android.util.AttributeSet);
+ ctor public StreamingTextView(android.content.Context, android.util.AttributeSet, int);
+ method public static boolean isLayoutRtl(android.view.View);
+ method public void reset();
+ method public void setFinalRecognizedText(java.lang.CharSequence);
+ method public void updateRecognizedText(java.lang.String, java.lang.String);
+ method public void updateRecognizedText(java.lang.String, java.util.List<java.lang.Float>);
+ }
+
+ public class TitleHelper {
+ ctor public TitleHelper(android.view.ViewGroup, android.support.v17.leanback.widget.TitleView);
+ method public android.support.v17.leanback.widget.BrowseFrameLayout.OnFocusSearchListener getOnFocusSearchListener();
+ method public android.view.ViewGroup getSceneRoot();
+ method public android.support.v17.leanback.widget.TitleView getTitleView();
+ method public void showTitle(boolean);
+ }
+
+ public class TitleView extends android.widget.FrameLayout {
+ ctor public TitleView(android.content.Context);
+ ctor public TitleView(android.content.Context, android.util.AttributeSet);
+ ctor public TitleView(android.content.Context, android.util.AttributeSet, int);
+ method public void enableAnimation(boolean);
+ method public android.graphics.drawable.Drawable getBadgeDrawable();
+ method public android.support.v17.leanback.widget.SearchOrbView.Colors getSearchAffordanceColors();
+ method public android.view.View getSearchAffordanceView();
+ method public java.lang.CharSequence getTitle();
+ method public void setBadgeDrawable(android.graphics.drawable.Drawable);
+ method public void setOnSearchClickedListener(android.view.View.OnClickListener);
+ method public void setSearchAffordanceColors(android.support.v17.leanback.widget.SearchOrbView.Colors);
+ method public void setTitle(java.lang.String);
+ }
+
+ public class VerticalGridPresenter extends android.support.v17.leanback.widget.Presenter {
+ ctor public VerticalGridPresenter();
+ ctor public VerticalGridPresenter(int);
+ ctor public VerticalGridPresenter(int, boolean);
+ method public final boolean areChildRoundedCornersEnabled();
+ method protected android.support.v17.leanback.widget.VerticalGridPresenter.ViewHolder createGridViewHolder(android.view.ViewGroup);
+ method protected android.support.v17.leanback.widget.ShadowOverlayHelper.Options createShadowOverlayOptions();
+ method public final void enableChildRoundedCorners(boolean);
+ method public final int getFocusZoomFactor();
+ method public final boolean getKeepChildForeground();
+ method public int getNumberOfColumns();
+ method public final android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public final android.support.v17.leanback.widget.OnItemViewSelectedListener getOnItemViewSelectedListener();
+ method public final boolean getShadowEnabled();
+ method protected void initializeGridViewHolder(android.support.v17.leanback.widget.VerticalGridPresenter.ViewHolder);
+ method public final boolean isFocusDimmerUsed();
+ method public boolean isUsingDefaultShadow();
+ method public boolean isUsingZOrder(android.content.Context);
+ method public void onBindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object);
+ method public final android.support.v17.leanback.widget.VerticalGridPresenter.ViewHolder onCreateViewHolder(android.view.ViewGroup);
+ method public void onUnbindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public void setEntranceTransitionState(android.support.v17.leanback.widget.VerticalGridPresenter.ViewHolder, boolean);
+ method public final void setKeepChildForeground(boolean);
+ method public void setNumberOfColumns(int);
+ method public final void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method public final void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
+ method public final void setShadowEnabled(boolean);
+ }
+
+ public static class VerticalGridPresenter.ViewHolder extends android.support.v17.leanback.widget.Presenter.ViewHolder {
+ ctor public VerticalGridPresenter.ViewHolder(android.support.v17.leanback.widget.VerticalGridView);
+ method public android.support.v17.leanback.widget.VerticalGridView getGridView();
+ }
+
+ public class VerticalGridView extends android.support.v7.widget.RecyclerView {
+ ctor public VerticalGridView(android.content.Context);
+ ctor public VerticalGridView(android.content.Context, android.util.AttributeSet);
+ ctor public VerticalGridView(android.content.Context, android.util.AttributeSet, int);
+ method protected void initAttributes(android.content.Context, android.util.AttributeSet);
+ method public void setColumnWidth(int);
+ method public void setNumColumns(int);
+ }
+
+}
+
diff --git a/v17/leanback/api/current.txt b/v17/leanback/api/current.txt
index fb2832d820..a4decd8b8f 100644
--- a/v17/leanback/api/current.txt
+++ b/v17/leanback/api/current.txt
@@ -37,6 +37,7 @@ package android.support.v17.leanback.app {
public class BrowseFragment extends android.support.v17.leanback.app.BrandedFragment {
ctor public BrowseFragment();
method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String, int);
+ method protected java.lang.Object createEntranceTransition();
method public void enableRowScaling(boolean);
method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
method public int getBrandColor();
@@ -46,6 +47,12 @@ package android.support.v17.leanback.app {
method public final boolean isHeadersTransitionOnBackEnabled();
method public boolean isInHeadersTransition();
method public boolean isShowingHeaders();
+ method protected void onEntranceTransitionEnd();
+ method protected void onEntranceTransitionPrepare();
+ method protected void onEntranceTransitionStart();
+ method public void onSaveInstanceState(android.os.Bundle);
+ method public void onStart();
+ method protected void runEntranceTransition(java.lang.Object);
method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
method public void setBrandColor(int);
method public void setBrowseTransitionListener(android.support.v17.leanback.app.BrowseFragment.BrowseTransitionListener);
@@ -71,6 +78,7 @@ package android.support.v17.leanback.app {
public class BrowseSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
ctor public BrowseSupportFragment();
method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String, int);
+ method protected java.lang.Object createEntranceTransition();
method public void enableRowScaling(boolean);
method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
method public int getBrandColor();
@@ -80,6 +88,12 @@ package android.support.v17.leanback.app {
method public final boolean isHeadersTransitionOnBackEnabled();
method public boolean isInHeadersTransition();
method public boolean isShowingHeaders();
+ method protected void onEntranceTransitionEnd();
+ method protected void onEntranceTransitionPrepare();
+ method protected void onEntranceTransitionStart();
+ method public void onSaveInstanceState(android.os.Bundle);
+ method public void onStart();
+ method protected void runEntranceTransition(java.lang.Object);
method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
method public void setBrandColor(int);
method public void setBrowseTransitionListener(android.support.v17.leanback.app.BrowseSupportFragment.BrowseTransitionListener);
@@ -104,11 +118,17 @@ package android.support.v17.leanback.app {
public class DetailsFragment extends android.support.v17.leanback.app.BrandedFragment {
ctor public DetailsFragment();
+ method protected java.lang.Object createEntranceTransition();
method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
method protected android.view.View inflateTitle(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+ method protected void onEntranceTransitionEnd();
+ method protected void onEntranceTransitionPrepare();
+ method protected void onEntranceTransitionStart();
method protected void onSetDetailsOverviewRowStatus(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter, android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder, int, int, int);
method protected void onSetRowStatus(android.support.v17.leanback.widget.RowPresenter, android.support.v17.leanback.widget.RowPresenter.ViewHolder, int, int, int);
+ method public void onStart();
+ method protected void runEntranceTransition(java.lang.Object);
method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
@@ -120,11 +140,17 @@ package android.support.v17.leanback.app {
public class DetailsSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
ctor public DetailsSupportFragment();
+ method protected java.lang.Object createEntranceTransition();
method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
method protected android.view.View inflateTitle(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+ method protected void onEntranceTransitionEnd();
+ method protected void onEntranceTransitionPrepare();
+ method protected void onEntranceTransitionStart();
method protected void onSetDetailsOverviewRowStatus(android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter, android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder, int, int, int);
method protected void onSetRowStatus(android.support.v17.leanback.widget.RowPresenter, android.support.v17.leanback.widget.RowPresenter.ViewHolder, int, int, int);
+ method public void onStart();
+ method protected void runEntranceTransition(java.lang.Object);
method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
@@ -177,23 +203,109 @@ package android.support.v17.leanback.app {
public class GuidedStepFragment extends android.app.Fragment {
ctor public GuidedStepFragment();
method public static int add(android.app.FragmentManager, android.support.v17.leanback.app.GuidedStepFragment);
+ method public static int add(android.app.FragmentManager, android.support.v17.leanback.app.GuidedStepFragment, int);
+ method public static int addAsRoot(android.app.Activity, android.support.v17.leanback.app.GuidedStepFragment, int);
+ method public android.support.v17.leanback.widget.GuidedAction findActionById(long);
+ method public int findActionPositionById(long);
+ method public android.support.v17.leanback.widget.GuidedAction findButtonActionById(long);
+ method public int findButtonActionPositionById(long);
+ method public void finishGuidedStepFragments();
+ method public java.lang.String generateStackEntryName();
+ method public static java.lang.String generateStackEntryName(int, java.lang.Class);
method public android.view.View getActionItemView(int);
method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getActions();
+ method public android.view.View getButtonActionItemView(int);
+ method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getButtonActions();
method public static android.support.v17.leanback.app.GuidedStepFragment getCurrentGuidedStepFragment(android.app.FragmentManager);
method public android.support.v17.leanback.widget.GuidanceStylist getGuidanceStylist();
method public android.support.v17.leanback.widget.GuidedActionsStylist getGuidedActionsStylist();
+ method public android.support.v17.leanback.widget.GuidedActionsStylist getGuidedButtonActionsStylist();
+ method public static java.lang.String getGuidedStepFragmentClassName(java.lang.String);
method public int getSelectedActionPosition();
- method protected boolean isEntryTransitionEnabled();
+ method public int getSelectedButtonActionPosition();
+ method public int getUiStyle();
+ method public static boolean isUiStyleDefault(java.lang.String);
+ method public static boolean isUiStyleEntrance(java.lang.String);
+ method public void notifyActionChanged(int);
+ method public void notifyButtonActionChanged(int);
+ method protected void onAddSharedElementTransition(android.app.FragmentTransaction, android.support.v17.leanback.app.GuidedStepFragment);
method public void onCreateActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateActionsStylist();
+ method public android.view.View onCreateBackgroundView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+ method public void onCreateButtonActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
+ method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateButtonActionsStylist();
method public android.support.v17.leanback.widget.GuidanceStylist.Guidance onCreateGuidance(android.os.Bundle);
method public android.support.v17.leanback.widget.GuidanceStylist onCreateGuidanceStylist();
method public void onGuidedActionClicked(android.support.v17.leanback.widget.GuidedAction);
+ method public void onGuidedActionEdited(android.support.v17.leanback.widget.GuidedAction);
+ method public long onGuidedActionEditedAndProceed(android.support.v17.leanback.widget.GuidedAction);
method public void onGuidedActionFocused(android.support.v17.leanback.widget.GuidedAction);
+ method protected void onProvideFragmentTransitions();
method public int onProvideTheme();
+ method public void popBackStackToGuidedStepFragment(java.lang.Class, int);
method public void setActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
- method protected void setEntryTransitionEnabled(boolean);
+ method public void setButtonActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
method public void setSelectedActionPosition(int);
+ method public void setSelectedButtonActionPosition(int);
+ method public void setUiStyle(int);
+ field public static final java.lang.String EXTRA_UI_STYLE = "uiStyle";
+ field public static final int UI_STYLE_ACTIVITY_ROOT = 2; // 0x2
+ field public static final int UI_STYLE_ENTRANCE = 1; // 0x1
+ field public static final int UI_STYLE_REPLACE = 0; // 0x0
+ }
+
+ public class GuidedStepSupportFragment extends android.support.v4.app.Fragment {
+ ctor public GuidedStepSupportFragment();
+ method public static int add(android.support.v4.app.FragmentManager, android.support.v17.leanback.app.GuidedStepSupportFragment);
+ method public static int add(android.support.v4.app.FragmentManager, android.support.v17.leanback.app.GuidedStepSupportFragment, int);
+ method public static int addAsRoot(android.support.v4.app.FragmentActivity, android.support.v17.leanback.app.GuidedStepSupportFragment, int);
+ method public android.support.v17.leanback.widget.GuidedAction findActionById(long);
+ method public int findActionPositionById(long);
+ method public android.support.v17.leanback.widget.GuidedAction findButtonActionById(long);
+ method public int findButtonActionPositionById(long);
+ method public void finishGuidedStepSupportFragments();
+ method public java.lang.String generateStackEntryName();
+ method public static java.lang.String generateStackEntryName(int, java.lang.Class);
+ method public android.view.View getActionItemView(int);
+ method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getActions();
+ method public android.view.View getButtonActionItemView(int);
+ method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getButtonActions();
+ method public static android.support.v17.leanback.app.GuidedStepSupportFragment getCurrentGuidedStepSupportFragment(android.support.v4.app.FragmentManager);
+ method public android.support.v17.leanback.widget.GuidanceStylist getGuidanceStylist();
+ method public android.support.v17.leanback.widget.GuidedActionsStylist getGuidedActionsStylist();
+ method public android.support.v17.leanback.widget.GuidedActionsStylist getGuidedButtonActionsStylist();
+ method public static java.lang.String getGuidedStepSupportFragmentClassName(java.lang.String);
+ method public int getSelectedActionPosition();
+ method public int getSelectedButtonActionPosition();
+ method public int getUiStyle();
+ method public static boolean isUiStyleDefault(java.lang.String);
+ method public static boolean isUiStyleEntrance(java.lang.String);
+ method public void notifyActionChanged(int);
+ method public void notifyButtonActionChanged(int);
+ method protected void onAddSharedElementTransition(android.support.v4.app.FragmentTransaction, android.support.v17.leanback.app.GuidedStepSupportFragment);
+ method public void onCreateActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
+ method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateActionsStylist();
+ method public android.view.View onCreateBackgroundView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+ method public void onCreateButtonActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
+ method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateButtonActionsStylist();
+ method public android.support.v17.leanback.widget.GuidanceStylist.Guidance onCreateGuidance(android.os.Bundle);
+ method public android.support.v17.leanback.widget.GuidanceStylist onCreateGuidanceStylist();
+ method public void onGuidedActionClicked(android.support.v17.leanback.widget.GuidedAction);
+ method public void onGuidedActionEdited(android.support.v17.leanback.widget.GuidedAction);
+ method public long onGuidedActionEditedAndProceed(android.support.v17.leanback.widget.GuidedAction);
+ method public void onGuidedActionFocused(android.support.v17.leanback.widget.GuidedAction);
+ method protected void onProvideFragmentTransitions();
+ method public int onProvideTheme();
+ method public void popBackStackToGuidedStepSupportFragment(java.lang.Class, int);
+ method public void setActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
+ method public void setButtonActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
+ method public void setSelectedActionPosition(int);
+ method public void setSelectedButtonActionPosition(int);
+ method public void setUiStyle(int);
+ field public static final java.lang.String EXTRA_UI_STYLE = "uiStyle";
+ field public static final int UI_STYLE_ACTIVITY_ROOT = 2; // 0x2
+ field public static final int UI_STYLE_ENTRANCE = 1; // 0x1
+ field public static final int UI_STYLE_REPLACE = 0; // 0x0
}
public class HeadersFragment extends android.support.v17.leanback.app.BaseRowFragment {
@@ -300,12 +412,69 @@ package android.support.v17.leanback.app {
field public static final int PLAYBACK_SPEED_PAUSED = 0; // 0x0
}
+ public abstract class PlaybackControlSupportGlue implements android.support.v17.leanback.widget.OnActionClickedListener android.view.View.OnKeyListener {
+ ctor public PlaybackControlSupportGlue(android.content.Context, int[]);
+ ctor public PlaybackControlSupportGlue(android.content.Context, int[], int[]);
+ ctor public PlaybackControlSupportGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlaySupportFragment, int[]);
+ ctor public PlaybackControlSupportGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlaySupportFragment, int[], int[]);
+ method public android.support.v17.leanback.widget.PlaybackControlsRowPresenter createControlsRowAndPresenter();
+ method protected android.support.v17.leanback.widget.SparseArrayObjectAdapter createPrimaryActionsAdapter(android.support.v17.leanback.widget.PresenterSelector);
+ method public void enableProgressUpdating(boolean);
+ method public android.content.Context getContext();
+ method public android.support.v17.leanback.widget.PlaybackControlsRow getControlsRow();
+ method public abstract int getCurrentPosition();
+ method public abstract int getCurrentSpeedId();
+ method public int[] getFastForwardSpeeds();
+ method public android.support.v17.leanback.app.PlaybackOverlaySupportFragment getFragment();
+ method public abstract android.graphics.drawable.Drawable getMediaArt();
+ method public abstract int getMediaDuration();
+ method public abstract java.lang.CharSequence getMediaSubtitle();
+ method public abstract java.lang.CharSequence getMediaTitle();
+ method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public int[] getRewindSpeeds();
+ method public abstract long getSupportedActions();
+ method public int getUpdatePeriod();
+ method public abstract boolean hasValidMedia();
+ method public boolean isFadingEnabled();
+ method public abstract boolean isMediaPlaying();
+ method public void onActionClicked(android.support.v17.leanback.widget.Action);
+ method public boolean onKey(android.view.View, int, android.view.KeyEvent);
+ method protected void onMetadataChanged();
+ method protected abstract void onRowChanged(android.support.v17.leanback.widget.PlaybackControlsRow);
+ method protected void onStateChanged();
+ method protected abstract void pausePlayback();
+ method public void setControlsRow(android.support.v17.leanback.widget.PlaybackControlsRow);
+ method public void setFadingEnabled(boolean);
+ method public deprecated void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
+ method protected abstract void skipToNext();
+ method protected abstract void skipToPrevious();
+ method protected abstract void startPlayback(int);
+ method public void updateProgress();
+ field public static final int ACTION_CUSTOM_LEFT_FIRST = 1; // 0x1
+ field public static final int ACTION_CUSTOM_RIGHT_FIRST = 4096; // 0x1000
+ field public static final int ACTION_FAST_FORWARD = 128; // 0x80
+ field public static final int ACTION_PLAY_PAUSE = 64; // 0x40
+ field public static final int ACTION_REWIND = 32; // 0x20
+ field public static final int ACTION_SKIP_TO_NEXT = 256; // 0x100
+ field public static final int ACTION_SKIP_TO_PREVIOUS = 16; // 0x10
+ field public static final int PLAYBACK_SPEED_FAST_L0 = 10; // 0xa
+ field public static final int PLAYBACK_SPEED_FAST_L1 = 11; // 0xb
+ field public static final int PLAYBACK_SPEED_FAST_L2 = 12; // 0xc
+ field public static final int PLAYBACK_SPEED_FAST_L3 = 13; // 0xd
+ field public static final int PLAYBACK_SPEED_FAST_L4 = 14; // 0xe
+ field public static final int PLAYBACK_SPEED_INVALID = -1; // 0xffffffff
+ field public static final int PLAYBACK_SPEED_NORMAL = 1; // 0x1
+ field public static final int PLAYBACK_SPEED_PAUSED = 0; // 0x0
+ }
+
public class PlaybackOverlayFragment extends android.support.v17.leanback.app.DetailsFragment {
ctor public PlaybackOverlayFragment();
method public int getBackgroundType();
method public android.support.v17.leanback.app.PlaybackOverlayFragment.OnFadeCompleteListener getFadeCompleteListener();
method public final android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler getInputEventHandler();
method public boolean isFadingEnabled();
+ method public void onDestroyView();
+ method public void onResume();
method public void setBackgroundType(int);
method public void setFadeCompleteListener(android.support.v17.leanback.app.PlaybackOverlayFragment.OnFadeCompleteListener);
method public void setFadingEnabled(boolean);
@@ -332,6 +501,8 @@ package android.support.v17.leanback.app {
method public android.support.v17.leanback.app.PlaybackOverlaySupportFragment.OnFadeCompleteListener getFadeCompleteListener();
method public final android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler getInputEventHandler();
method public boolean isFadingEnabled();
+ method public void onDestroyView();
+ method public void onResume();
method public void setBackgroundType(int);
method public void setFadeCompleteListener(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.OnFadeCompleteListener);
method public void setFadingEnabled(boolean);
@@ -379,6 +550,7 @@ package android.support.v17.leanback.app {
method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String);
method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String, java.lang.String);
method public void displayCompletions(java.util.List<java.lang.String>);
+ method public void displayCompletions(android.view.inputmethod.CompletionInfo[]);
method public android.graphics.drawable.Drawable getBadgeDrawable();
method public android.content.Intent getRecognizerIntent();
method public java.lang.String getTitle();
@@ -405,6 +577,7 @@ package android.support.v17.leanback.app {
method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String);
method public static android.os.Bundle createArgs(android.os.Bundle, java.lang.String, java.lang.String);
method public void displayCompletions(java.util.List<java.lang.String>);
+ method public void displayCompletions(android.view.inputmethod.CompletionInfo[]);
method public android.graphics.drawable.Drawable getBadgeDrawable();
method public android.content.Intent getRecognizerIntent();
method public java.lang.String getTitle();
@@ -426,11 +599,16 @@ package android.support.v17.leanback.app {
method public abstract boolean onQueryTextSubmit(java.lang.String);
}
- public class VerticalGridFragment extends android.app.Fragment {
+ public class VerticalGridFragment extends android.support.v17.leanback.app.BrandedFragment {
ctor public VerticalGridFragment();
+ method protected java.lang.Object createEntranceTransition();
method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
method public android.support.v17.leanback.widget.VerticalGridPresenter getGridPresenter();
method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public void onDestroyView();
+ method public void onStart();
+ method public void onViewCreated(android.view.View, android.os.Bundle);
+ method protected void runEntranceTransition(java.lang.Object);
method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
method public void setGridPresenter(android.support.v17.leanback.widget.VerticalGridPresenter);
method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
@@ -438,11 +616,16 @@ package android.support.v17.leanback.app {
method public void setSelectedPosition(int);
}
- public class VerticalGridSupportFragment extends android.support.v4.app.Fragment {
+ public class VerticalGridSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
ctor public VerticalGridSupportFragment();
+ method protected java.lang.Object createEntranceTransition();
method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
method public android.support.v17.leanback.widget.VerticalGridPresenter getGridPresenter();
method public android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
+ method public void onDestroyView();
+ method public void onStart();
+ method public void onViewCreated(android.view.View, android.os.Bundle);
+ method protected void runEntranceTransition(java.lang.Object);
method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
method public void setGridPresenter(android.support.v17.leanback.widget.VerticalGridPresenter);
method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
@@ -722,12 +905,8 @@ package android.support.v17.leanback.widget {
}
public abstract interface FragmentAnimationProvider {
- method public abstract void onActivityEnter(java.util.List<android.animation.Animator>);
- method public abstract void onActivityExit(java.util.List<android.animation.Animator>);
- method public abstract void onFragmentEnter(java.util.List<android.animation.Animator>);
- method public abstract void onFragmentExit(java.util.List<android.animation.Animator>);
- method public abstract void onFragmentReenter(java.util.List<android.animation.Animator>);
- method public abstract void onFragmentReturn(java.util.List<android.animation.Animator>);
+ method public abstract void onImeAppearing(java.util.List<android.animation.Animator>);
+ method public abstract void onImeDisappearing(java.util.List<android.animation.Animator>);
}
public class FullWidthDetailsOverviewRowPresenter extends android.support.v17.leanback.widget.RowPresenter {
@@ -798,13 +977,10 @@ package android.support.v17.leanback.widget {
method public android.widget.TextView getDescriptionView();
method public android.widget.ImageView getIconView();
method public android.widget.TextView getTitleView();
- method public void onActivityEnter(java.util.List<android.animation.Animator>);
- method public void onActivityExit(java.util.List<android.animation.Animator>);
method public android.view.View onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.support.v17.leanback.widget.GuidanceStylist.Guidance);
- method public void onFragmentEnter(java.util.List<android.animation.Animator>);
- method public void onFragmentExit(java.util.List<android.animation.Animator>);
- method public void onFragmentReenter(java.util.List<android.animation.Animator>);
- method public void onFragmentReturn(java.util.List<android.animation.Animator>);
+ method public void onDestroyView();
+ method public void onImeAppearing(java.util.List<android.animation.Animator>);
+ method public void onImeDisappearing(java.util.List<android.animation.Animator>);
method public int onProvideLayoutId();
}
@@ -817,59 +993,112 @@ package android.support.v17.leanback.widget {
}
public class GuidedAction extends android.support.v17.leanback.widget.Action {
+ ctor protected GuidedAction();
method public int getCheckSetId();
method public java.lang.CharSequence getDescription();
+ method public int getDescriptionEditInputType();
+ method public int getDescriptionInputType();
+ method public java.lang.CharSequence getEditDescription();
+ method public int getEditInputType();
+ method public java.lang.CharSequence getEditTitle();
+ method public int getInputType();
method public android.content.Intent getIntent();
method public java.lang.CharSequence getTitle();
method public boolean hasMultilineDescription();
method public boolean hasNext();
method public boolean infoOnly();
method public boolean isChecked();
+ method public boolean isDescriptionEditable();
+ method public boolean isEditTitleUsed();
+ method public boolean isEditable();
method public boolean isEnabled();
+ method public boolean isFocusable();
method public void setChecked(boolean);
+ method public void setDescription(java.lang.CharSequence);
+ method public void setEditDescription(java.lang.CharSequence);
+ method public void setEditTitle(java.lang.CharSequence);
method public void setEnabled(boolean);
+ method public void setFocusable(boolean);
+ method public void setTitle(java.lang.CharSequence);
+ field public static final long ACTION_ID_CANCEL = -5L; // 0xfffffffffffffffbL
+ field public static final long ACTION_ID_CONTINUE = -7L; // 0xfffffffffffffff9L
+ field public static final long ACTION_ID_CURRENT = -3L; // 0xfffffffffffffffdL
+ field public static final long ACTION_ID_FINISH = -6L; // 0xfffffffffffffffaL
+ field public static final long ACTION_ID_NEXT = -2L; // 0xfffffffffffffffeL
+ field public static final long ACTION_ID_NO = -9L; // 0xfffffffffffffff7L
+ field public static final long ACTION_ID_OK = -4L; // 0xfffffffffffffffcL
+ field public static final long ACTION_ID_YES = -8L; // 0xfffffffffffffff8L
+ field public static final int CHECKBOX_CHECK_SET_ID = -1; // 0xffffffff
field public static final int DEFAULT_CHECK_SET_ID = 1; // 0x1
field public static final int NO_CHECK_SET = 0; // 0x0
- field public static final int NO_DRAWABLE = 0; // 0x0
}
public static class GuidedAction.Builder {
ctor public GuidedAction.Builder();
- method public android.support.v17.leanback.widget.GuidedAction build();
+ method protected final void applyValues(android.support.v17.leanback.widget.GuidedAction);
+ method public final android.support.v17.leanback.widget.GuidedAction build();
method public android.support.v17.leanback.widget.GuidedAction.Builder checkSetId(int);
method public android.support.v17.leanback.widget.GuidedAction.Builder checked(boolean);
- method public android.support.v17.leanback.widget.GuidedAction.Builder description(java.lang.String);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder constructCancel(android.content.Context);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder constructContinue(android.content.Context);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder constructFinish(android.content.Context);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder constructNo(android.content.Context);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder constructOK(android.content.Context);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder constructYes(android.content.Context);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder description(java.lang.CharSequence);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder descriptionEditInputType(int);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder descriptionEditable(boolean);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder descriptionInputType(int);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder editDescription(java.lang.CharSequence);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder editInputType(int);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder editTitle(java.lang.CharSequence);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder editable(boolean);
method public android.support.v17.leanback.widget.GuidedAction.Builder enabled(boolean);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder focusable(boolean);
method public android.support.v17.leanback.widget.GuidedAction.Builder hasNext(boolean);
method public android.support.v17.leanback.widget.GuidedAction.Builder icon(android.graphics.drawable.Drawable);
method public android.support.v17.leanback.widget.GuidedAction.Builder iconResourceId(int, android.content.Context);
method public android.support.v17.leanback.widget.GuidedAction.Builder id(long);
method public android.support.v17.leanback.widget.GuidedAction.Builder infoOnly(boolean);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder inputType(int);
method public android.support.v17.leanback.widget.GuidedAction.Builder intent(android.content.Intent);
method public android.support.v17.leanback.widget.GuidedAction.Builder multilineDescription(boolean);
- method public android.support.v17.leanback.widget.GuidedAction.Builder title(java.lang.String);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder title(java.lang.CharSequence);
+ }
+
+ public class GuidedActionEditText extends android.widget.EditText implements android.support.v17.leanback.widget.ImeKeyMonitor {
+ ctor public GuidedActionEditText(android.content.Context);
+ ctor public GuidedActionEditText(android.content.Context, android.util.AttributeSet);
+ ctor public GuidedActionEditText(android.content.Context, android.util.AttributeSet, int);
+ method public void setImeKeyListener(android.support.v17.leanback.widget.ImeKeyMonitor.ImeKeyListener);
}
public class GuidedActionsStylist implements android.support.v17.leanback.widget.FragmentAnimationProvider {
ctor public GuidedActionsStylist();
method public android.support.v17.leanback.widget.VerticalGridView getActionsGridView();
- method public void onActivityEnter(java.util.List<android.animation.Animator>);
- method public void onActivityExit(java.util.List<android.animation.Animator>);
+ method public int getItemViewType(android.support.v17.leanback.widget.GuidedAction);
+ method public boolean isButtonActions();
method public void onAnimateItemChecked(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
method public void onAnimateItemFocused(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
method public void onAnimateItemPressed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
+ method public void onAnimateItemPressedCancelled(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
+ method public void onBindCheckMarkView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
+ method public void onBindChevronView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
method public void onBindViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
method public android.view.View onCreateView(android.view.LayoutInflater, android.view.ViewGroup);
method public android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder onCreateViewHolder(android.view.ViewGroup);
- method public void onFragmentEnter(java.util.List<android.animation.Animator>);
- method public void onFragmentExit(java.util.List<android.animation.Animator>);
- method public void onFragmentReenter(java.util.List<android.animation.Animator>);
- method public void onFragmentReturn(java.util.List<android.animation.Animator>);
+ method public android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder onCreateViewHolder(android.view.ViewGroup, int);
+ method public void onDestroyView();
+ method protected void onEditingModeChange(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean);
+ method public void onImeAppearing(java.util.List<android.animation.Animator>);
+ method public void onImeDisappearing(java.util.List<android.animation.Animator>);
method public int onProvideItemLayoutId();
+ method public int onProvideItemLayoutId(int);
method public int onProvideLayoutId();
- field protected android.support.v17.leanback.widget.VerticalGridView mActionsGridView;
- field protected android.view.View mMainView;
- field protected android.view.View mSelectorView;
+ method public void setAsButtonActions();
+ method public void setEditingMode(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean);
+ method protected void setupImeOptions(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
+ field public static final int VIEW_TYPE_DEFAULT = 0; // 0x0
}
public static class GuidedActionsStylist.ViewHolder {
@@ -878,8 +1107,13 @@ package android.support.v17.leanback.widget {
method public android.widget.ImageView getChevronView();
method public android.view.View getContentView();
method public android.widget.TextView getDescriptionView();
+ method public android.widget.EditText getEditableDescriptionView();
+ method public android.widget.EditText getEditableTitleView();
+ method public android.view.View getEditingView();
method public android.widget.ImageView getIconView();
method public android.widget.TextView getTitleView();
+ method public boolean isInEditing();
+ method public boolean isInEditingDescription();
field public final android.view.View view;
}
@@ -918,9 +1152,10 @@ package android.support.v17.leanback.widget {
}
public class ImageCardView extends android.support.v17.leanback.widget.BaseCardView {
+ ctor public ImageCardView(android.content.Context, int);
+ ctor public ImageCardView(android.content.Context, android.util.AttributeSet, int);
ctor public ImageCardView(android.content.Context);
ctor public ImageCardView(android.content.Context, android.util.AttributeSet);
- ctor public ImageCardView(android.content.Context, android.util.AttributeSet, int);
method public android.graphics.drawable.Drawable getBadgeImage();
method public java.lang.CharSequence getContentText();
method public android.graphics.drawable.Drawable getInfoAreaBackground();
@@ -937,6 +1172,19 @@ package android.support.v17.leanback.widget {
method public void setMainImageDimensions(int, int);
method public void setMainImageScaleType(android.widget.ImageView.ScaleType);
method public void setTitleText(java.lang.CharSequence);
+ field public static final int CARD_TYPE_FLAG_CONTENT = 2; // 0x2
+ field public static final int CARD_TYPE_FLAG_ICON_LEFT = 8; // 0x8
+ field public static final int CARD_TYPE_FLAG_ICON_RIGHT = 4; // 0x4
+ field public static final int CARD_TYPE_FLAG_IMAGE_ONLY = 0; // 0x0
+ field public static final int CARD_TYPE_FLAG_TITLE = 1; // 0x1
+ }
+
+ public abstract interface ImeKeyMonitor {
+ method public abstract void setImeKeyListener(android.support.v17.leanback.widget.ImeKeyMonitor.ImeKeyListener);
+ }
+
+ public static abstract interface ImeKeyMonitor.ImeKeyListener {
+ method public abstract boolean onKeyPreIme(android.widget.EditText, int, android.view.KeyEvent);
}
public final class ItemAlignmentFacet {
@@ -1012,6 +1260,12 @@ package android.support.v17.leanback.widget {
method public abstract void wrap(android.view.View, android.view.View);
}
+ public class ItemBridgeAdapterShadowOverlayWrapper extends android.support.v17.leanback.widget.ItemBridgeAdapter.Wrapper {
+ ctor public ItemBridgeAdapterShadowOverlayWrapper(android.support.v17.leanback.widget.ShadowOverlayHelper);
+ method public android.view.View createWrapper(android.view.View);
+ method public void wrap(android.view.View, android.view.View);
+ }
+
public class ListRow extends android.support.v17.leanback.widget.Row {
ctor public ListRow(android.support.v17.leanback.widget.HeaderItem, android.support.v17.leanback.widget.ObjectAdapter);
ctor public ListRow(long, android.support.v17.leanback.widget.HeaderItem, android.support.v17.leanback.widget.ObjectAdapter);
@@ -1035,6 +1289,7 @@ package android.support.v17.leanback.widget {
ctor public ListRowPresenter(int, boolean);
method public final boolean areChildRoundedCornersEnabled();
method protected android.support.v17.leanback.widget.RowPresenter.ViewHolder createRowViewHolder(android.view.ViewGroup);
+ method protected android.support.v17.leanback.widget.ShadowOverlayHelper.Options createShadowOverlayOptions();
method public final void enableChildRoundedCorners(boolean);
method public int getExpandedRowHeight();
method public final int getFocusZoomFactor();
@@ -1044,12 +1299,14 @@ package android.support.v17.leanback.widget {
method public final boolean getShadowEnabled();
method public final deprecated int getZoomFactor();
method public final boolean isFocusDimmerUsed();
+ method public final boolean isKeepChildForeground();
method public boolean isUsingDefaultListSelectEffect();
method public final boolean isUsingDefaultSelectEffect();
method public boolean isUsingDefaultShadow();
method public boolean isUsingZOrder(android.content.Context);
method public void setExpandedRowHeight(int);
method public final void setHoverCardPresenterSelector(android.support.v17.leanback.widget.PresenterSelector);
+ method public final void setKeepChildForeground(boolean);
method public void setRecycledPoolSize(android.support.v17.leanback.widget.Presenter, int);
method public void setRowHeight(int);
method public final void setShadowEnabled(boolean);
@@ -1327,7 +1584,6 @@ package android.support.v17.leanback.widget {
public abstract class RowPresenter extends android.support.v17.leanback.widget.Presenter {
ctor public RowPresenter();
- method public boolean canDrawOutOfBounds();
method protected abstract android.support.v17.leanback.widget.RowPresenter.ViewHolder createRowViewHolder(android.view.ViewGroup);
method protected void dispatchItemSelectedListener(android.support.v17.leanback.widget.RowPresenter.ViewHolder, boolean);
method public void freeze(android.support.v17.leanback.widget.RowPresenter.ViewHolder, boolean);
@@ -1387,6 +1643,7 @@ package android.support.v17.leanback.widget {
ctor public SearchBar(android.content.Context, android.util.AttributeSet);
ctor public SearchBar(android.content.Context, android.util.AttributeSet, int);
method public void displayCompletions(java.util.List<java.lang.String>);
+ method public void displayCompletions(android.view.inputmethod.CompletionInfo[]);
method public android.graphics.drawable.Drawable getBadgeDrawable();
method public java.lang.CharSequence getHint();
method public java.lang.String getTitle();
@@ -1443,15 +1700,14 @@ package android.support.v17.leanback.widget {
field public int iconColor;
}
- public class ShadowOverlayContainer extends android.view.ViewGroup {
+ public class ShadowOverlayContainer extends android.widget.FrameLayout {
ctor public ShadowOverlayContainer(android.content.Context);
ctor public ShadowOverlayContainer(android.content.Context, android.util.AttributeSet);
ctor public ShadowOverlayContainer(android.content.Context, android.util.AttributeSet, int);
method public int getShadowType();
method public android.view.View getWrappedView();
method public deprecated void initialize(boolean, boolean);
- method public void initialize(boolean, boolean, boolean);
- method protected void onLayout(boolean, int, int, int, int);
+ method public deprecated void initialize(boolean, boolean, boolean);
method public static void prepareParentForShadow(android.view.ViewGroup);
method public void setOverlayColor(int);
method public void setShadowFocusLevel(float);
@@ -1466,6 +1722,48 @@ package android.support.v17.leanback.widget {
field public static final int SHADOW_STATIC = 2; // 0x2
}
+ public final class ShadowOverlayHelper {
+ method public android.support.v17.leanback.widget.ShadowOverlayContainer createShadowOverlayContainer(android.content.Context);
+ method public int getShadowType();
+ method public boolean needsOverlay();
+ method public boolean needsRoundedCorner();
+ method public boolean needsWrapper();
+ method public void onViewCreated(android.view.View);
+ method public void prepareParentForShadow(android.view.ViewGroup);
+ method public static void setNoneWrapperOverlayColor(android.view.View, int);
+ method public static void setNoneWrapperShadowFocusLevel(android.view.View, float);
+ method public void setOverlayColor(android.view.View, int);
+ method public void setShadowFocusLevel(android.view.View, float);
+ method public static boolean supportsDynamicShadow();
+ method public static boolean supportsForeground();
+ method public static boolean supportsRoundedCorner();
+ method public static boolean supportsShadow();
+ field public static final int SHADOW_DYNAMIC = 3; // 0x3
+ field public static final int SHADOW_NONE = 1; // 0x1
+ field public static final int SHADOW_STATIC = 2; // 0x2
+ }
+
+ public static final class ShadowOverlayHelper.Builder {
+ ctor public ShadowOverlayHelper.Builder();
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper build(android.content.Context);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder keepForegroundDrawable(boolean);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder needsOverlay(boolean);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder needsRoundedCorner(boolean);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder needsShadow(boolean);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder options(android.support.v17.leanback.widget.ShadowOverlayHelper.Options);
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Builder preferZOrder(boolean);
+ }
+
+ public static final class ShadowOverlayHelper.Options {
+ ctor public ShadowOverlayHelper.Options();
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Options dynamicShadowZ(float, float);
+ method public final float getDynamicShadowFocusedZ();
+ method public final float getDynamicShadowUnfocusedZ();
+ method public final int getRoundedCornerRadius();
+ method public android.support.v17.leanback.widget.ShadowOverlayHelper.Options roundedCornerRadius(int);
+ field public static final android.support.v17.leanback.widget.ShadowOverlayHelper.Options DEFAULT;
+ }
+
public final class SinglePresenterSelector extends android.support.v17.leanback.widget.PresenterSelector {
ctor public SinglePresenterSelector(android.support.v17.leanback.widget.Presenter);
method public android.support.v17.leanback.widget.Presenter getPresenter(java.lang.Object);
@@ -1538,8 +1836,10 @@ package android.support.v17.leanback.widget {
ctor public VerticalGridPresenter(int, boolean);
method public final boolean areChildRoundedCornersEnabled();
method protected android.support.v17.leanback.widget.VerticalGridPresenter.ViewHolder createGridViewHolder(android.view.ViewGroup);
+ method protected android.support.v17.leanback.widget.ShadowOverlayHelper.Options createShadowOverlayOptions();
method public final void enableChildRoundedCorners(boolean);
method public final int getFocusZoomFactor();
+ method public final boolean getKeepChildForeground();
method public int getNumberOfColumns();
method public final android.support.v17.leanback.widget.OnItemViewClickedListener getOnItemViewClickedListener();
method public final android.support.v17.leanback.widget.OnItemViewSelectedListener getOnItemViewSelectedListener();
@@ -1551,6 +1851,8 @@ package android.support.v17.leanback.widget {
method public void onBindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object);
method public final android.support.v17.leanback.widget.VerticalGridPresenter.ViewHolder onCreateViewHolder(android.view.ViewGroup);
method public void onUnbindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder);
+ method public void setEntranceTransitionState(android.support.v17.leanback.widget.VerticalGridPresenter.ViewHolder, boolean);
+ method public final void setKeepChildForeground(boolean);
method public void setNumberOfColumns(int);
method public final void setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener);
method public final void setOnItemViewSelectedListener(android.support.v17.leanback.widget.OnItemViewSelectedListener);
diff --git a/v17/leanback/api21/android/support/v17/leanback/transition/FadeAndShortSlide.java b/v17/leanback/api21/android/support/v17/leanback/transition/FadeAndShortSlide.java
new file mode 100644
index 0000000000..1762c1522f
--- /dev/null
+++ b/v17/leanback/api21/android/support/v17/leanback/transition/FadeAndShortSlide.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.TimeInterpolator;
+import android.transition.Fade;
+import android.transition.Transition;
+import android.transition.TransitionValues;
+import android.transition.Visibility;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
+
+/**
+ * Execute horizontal slide of 1/4 width and fade (to workaround bug 23718734)
+ * @hide
+ */
+public class FadeAndShortSlide extends Visibility {
+
+ private static final TimeInterpolator sDecelerate = new DecelerateInterpolator();
+ // private static final TimeInterpolator sAccelerate = new AccelerateInterpolator();
+ private static final String PROPNAME_SCREEN_POSITION =
+ "android:fadeAndShortSlideTransition:screenPosition";
+
+ private CalculateSlide mSlideCalculator = sCalculateEnd;
+ private Visibility mFade = new Fade();
+
+ private interface CalculateSlide {
+
+ /** Returns the translation value for view when it goes out of the scene */
+ float getGoneX(ViewGroup sceneRoot, View view, int[] position);
+ }
+
+ private static final CalculateSlide sCalculateStart = new CalculateSlide() {
+ @Override
+ public float getGoneX(ViewGroup sceneRoot, View view, int[] position) {
+ final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+ final float x;
+ if (isRtl) {
+ x = view.getTranslationX() + sceneRoot.getWidth() / 4;
+ } else {
+ x = view.getTranslationX() - sceneRoot.getWidth() / 4;
+ }
+ return x;
+ }
+ };
+
+ private static final CalculateSlide sCalculateEnd = new CalculateSlide() {
+ @Override
+ public float getGoneX(ViewGroup sceneRoot, View view, int[] position) {
+ final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+ final float x;
+ if (isRtl) {
+ x = view.getTranslationX() - sceneRoot.getWidth() / 4;
+ } else {
+ x = view.getTranslationX() + sceneRoot.getWidth() / 4;
+ }
+ return x;
+ }
+ };
+
+ private static final CalculateSlide sCalculateBoth = new CalculateSlide() {
+
+ @Override
+ public float getGoneX(ViewGroup sceneRoot, View view, int[] position) {
+ final int viewCenter = position[0] + view.getWidth() / 2;
+ sceneRoot.getLocationOnScreen(position);
+ final int sceneRootCenter = position[0] + sceneRoot.getWidth() / 2;
+ if (viewCenter < sceneRootCenter) {
+ return view.getTranslationX() - sceneRoot.getWidth() / 2;
+ } else {
+ return view.getTranslationX() + sceneRoot.getWidth() / 2;
+ }
+ }
+ };
+
+ public FadeAndShortSlide() {
+ this(Gravity.START);
+ }
+
+ public FadeAndShortSlide(int slideEdge) {
+ setSlideEdge(slideEdge);
+ }
+
+ @Override
+ public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
+ super.setEpicenterCallback(epicenterCallback);
+ mFade.setEpicenterCallback(epicenterCallback);
+ }
+
+ private void captureValues(TransitionValues transitionValues) {
+ View view = transitionValues.view;
+ int[] position = new int[2];
+ view.getLocationOnScreen(position);
+ transitionValues.values.put(PROPNAME_SCREEN_POSITION, position);
+ }
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ mFade.captureStartValues(transitionValues);
+ captureValues(transitionValues);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ mFade.captureEndValues(transitionValues);
+ captureValues(transitionValues);
+ }
+
+ public void setSlideEdge(int slideEdge) {
+ switch (slideEdge) {
+ case Gravity.START:
+ mSlideCalculator = sCalculateStart;
+ break;
+ case Gravity.END:
+ mSlideCalculator = sCalculateEnd;
+ break;
+ case Gravity.START | Gravity.END:
+ mSlideCalculator = sCalculateBoth;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid slide direction");
+ }
+ // SidePropagation propagation = new SidePropagation();
+ // propagation.setSide(slideEdge);
+ // setPropagation(propagation);
+ }
+
+ @Override
+ public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+ TransitionValues endValues) {
+ if (endValues == null) {
+ return null;
+ }
+ if (sceneRoot == view) {
+ // workaround b/25375640, avoid run animation on sceneRoot
+ return null;
+ }
+ int[] position = (int[]) endValues.values.get(PROPNAME_SCREEN_POSITION);
+ int left = position[0];
+ float endX = view.getTranslationX();
+ float startX = mSlideCalculator.getGoneX(sceneRoot, view, position);
+ final Animator slideAnimator = TranslationAnimationCreator.createAnimation(view, endValues,
+ left, startX, endX, sDecelerate, this);
+ final AnimatorSet set = new AnimatorSet();
+ set.play(slideAnimator).with(mFade.onAppear(sceneRoot, view, startValues, endValues));
+
+ return set;
+ }
+
+ @Override
+ public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+ TransitionValues endValues) {
+ if (startValues == null) {
+ return null;
+ }
+ if (sceneRoot == view) {
+ // workaround b/25375640, avoid run animation on sceneRoot
+ return null;
+ }
+ int[] position = (int[]) startValues.values.get(PROPNAME_SCREEN_POSITION);
+ int left = position[0];
+ float startX = view.getTranslationX();
+ float endX = mSlideCalculator.getGoneX(sceneRoot, view, position);
+ final Animator slideAnimator = TranslationAnimationCreator.createAnimation(view,
+ startValues, left, startX, endX, sDecelerate /* sAccelerate */, this);
+ final AnimatorSet set = new AnimatorSet();
+ set.play(slideAnimator).with(mFade.onDisappear(sceneRoot, view, startValues, endValues));
+
+ return set;
+ }
+
+ @Override
+ public Transition addListener(TransitionListener listener) {
+ mFade.addListener(listener);
+ return super.addListener(listener);
+ }
+
+ @Override
+ public Transition removeListener(TransitionListener listener) {
+ mFade.removeListener(listener);
+ return super.removeListener(listener);
+ }
+
+ @Override
+ public Transition clone() {
+ FadeAndShortSlide clone = null;
+ clone = (FadeAndShortSlide) super.clone();
+ clone.mFade = (Visibility) mFade.clone();
+ return clone;
+ }
+}
+
diff --git a/v17/leanback/api21/android/support/v17/leanback/transition/TransitionHelperApi21.java b/v17/leanback/api21/android/support/v17/leanback/transition/TransitionHelperApi21.java
index 00ebf4c44c..c5a33cb84a 100644
--- a/v17/leanback/api21/android/support/v17/leanback/transition/TransitionHelperApi21.java
+++ b/v17/leanback/api21/android/support/v17/leanback/transition/TransitionHelperApi21.java
@@ -14,8 +14,12 @@
package android.support.v17.leanback.transition;
import android.R;
+import android.app.Fragment;
import android.content.Context;
import android.transition.ChangeTransform;
+import android.transition.Transition;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.AnimationUtils;
@@ -24,6 +28,24 @@ final class TransitionHelperApi21 {
TransitionHelperApi21() {
}
+ public static void setEnterTransition(android.app.Fragment fragment, Object transition) {
+ fragment.setEnterTransition((Transition)transition);
+ }
+
+ public static void setExitTransition(android.app.Fragment fragment, Object transition) {
+ fragment.setExitTransition((Transition)transition);
+ }
+
+ public static void setSharedElementEnterTransition(android.app.Fragment fragment,
+ Object transition) {
+ fragment.setSharedElementEnterTransition((Transition)transition);
+ }
+
+ public static void addSharedElement(android.app.FragmentTransaction ft,
+ View view, String transitionName) {
+ ft.addSharedElement(view, transitionName);
+ }
+
public static Object getSharedElementEnterTransition(Window window) {
return window.getSharedElementEnterTransition();
}
@@ -63,4 +85,12 @@ final class TransitionHelperApi21 {
public static Object createDefaultInterpolator(Context context) {
return AnimationUtils.loadInterpolator(context, R.interpolator.fast_out_linear_in);
}
+
+ public static Object createFadeAndShortSlide(int edge) {
+ return new FadeAndShortSlide(edge);
+ }
+
+ public static void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
+ viewGroup.setTransitionGroup(transitionGroup);
+ }
}
diff --git a/v17/leanback/api21/android/support/v17/leanback/transition/TranslationAnimationCreator.java b/v17/leanback/api21/android/support/v17/leanback/transition/TranslationAnimationCreator.java
new file mode 100644
index 0000000000..2cc35452cc
--- /dev/null
+++ b/v17/leanback/api21/android/support/v17/leanback/transition/TranslationAnimationCreator.java
@@ -0,0 +1,128 @@
+package android.support.v17.leanback.transition;
+
+import android.support.v17.leanback.R;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.graphics.Path;
+import android.transition.Transition;
+import android.transition.TransitionValues;
+import android.view.View;
+
+/**
+ * This class is used by Slide and Explode to create an animator that goes from the start position
+ * to the end position. It takes into account the canceled position so that it will not blink out or
+ * shift suddenly when the transition is interrupted.
+ * @hide
+ */
+class TranslationAnimationCreator {
+
+ /**
+ * Creates an animator that can be used for x and/or y translations. When interrupted, it sets a
+ * tag to keep track of the position so that it may be continued from position.
+ *
+ * @param view The view being moved. This may be in the overlay for onDisappear.
+ * @param values The values containing the view in the view hierarchy.
+ * @param viewPosX The x screen coordinate of view
+ * @param startX The start translation x of view
+ * @param endX The end translation x of view
+ * @param interpolator The interpolator to use with this animator.
+ * @return An animator that moves from (startX, startY) to (endX, endY) unless there was a
+ * previous interruption, in which case it moves from the current position to (endX,
+ * endY).
+ */
+ static Animator createAnimation(View view, TransitionValues values, int viewPosX, float startX,
+ float endX, TimeInterpolator interpolator, Transition transition) {
+ float terminalX = view.getTranslationX();
+ Integer startPosition = (Integer) values.view.getTag(R.id.transitionPosition);
+ if (startPosition != null) {
+ startX = startPosition - viewPosX + terminalX;
+ }
+ // Initial position is at translation startX, startY, so position is offset by that
+ // amount
+ int startPosX = viewPosX + Math.round(startX - terminalX);
+
+ view.setTranslationX(startX);
+ if (startX == endX) {
+ return null;
+ }
+ float y = view.getTranslationY();
+ Path path = new Path();
+ path.moveTo(startX, y);
+ path.lineTo(endX, y);
+ ObjectAnimator anim =
+ ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y, path);
+
+ TransitionPositionListener listener =
+ new TransitionPositionListener(view, values.view, startPosX, terminalX);
+ transition.addListener(listener);
+ anim.addListener(listener);
+ anim.addPauseListener(listener);
+ anim.setInterpolator(interpolator);
+ return anim;
+ }
+
+ private static class TransitionPositionListener extends AnimatorListenerAdapter
+ implements Transition.TransitionListener {
+
+ private final View mViewInHierarchy;
+ private final View mMovingView;
+ private final int mStartX;
+ private Integer mTransitionPosition;
+ private float mPausedX;
+ private final float mTerminalX;
+
+ private TransitionPositionListener(View movingView, View viewInHierarchy, int startX,
+ float terminalX) {
+ mMovingView = movingView;
+ mViewInHierarchy = viewInHierarchy;
+ mStartX = startX - Math.round(mMovingView.getTranslationX());
+ mTerminalX = terminalX;
+ mTransitionPosition = (Integer) mViewInHierarchy.getTag(R.id.transitionPosition);
+ if (mTransitionPosition != null) {
+ mViewInHierarchy.setTag(R.id.transitionPosition, null);
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mTransitionPosition = Math.round(mStartX + mMovingView.getTranslationX());
+ mViewInHierarchy.setTag(R.id.transitionPosition, mTransitionPosition);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {}
+
+ @Override
+ public void onAnimationPause(Animator animator) {
+ mPausedX = mMovingView.getTranslationX();
+ mMovingView.setTranslationX(mTerminalX);
+ }
+
+ @Override
+ public void onAnimationResume(Animator animator) {
+ mMovingView.setTranslationX(mPausedX);
+ }
+
+ @Override
+ public void onTransitionStart(Transition transition) {}
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ mMovingView.setTranslationX(mTerminalX);
+ }
+
+ @Override
+ public void onTransitionCancel(Transition transition) {}
+
+ @Override
+ public void onTransitionPause(Transition transition) {}
+
+ @Override
+ public void onTransitionResume(Transition transition) {}
+ }
+
+}
+
diff --git a/v17/leanback/api21/android/support/v17/leanback/widget/RoundedRectHelperApi21.java b/v17/leanback/api21/android/support/v17/leanback/widget/RoundedRectHelperApi21.java
index c7fa0f36e7..a013ba1989 100644
--- a/v17/leanback/api21/android/support/v17/leanback/widget/RoundedRectHelperApi21.java
+++ b/v17/leanback/api21/android/support/v17/leanback/widget/RoundedRectHelperApi21.java
@@ -13,31 +13,47 @@
*/
package android.support.v17.leanback.widget;
-import android.support.v17.leanback.R;
-import android.graphics.Color;
+import android.util.SparseArray;
import android.graphics.Outline;
-import android.graphics.drawable.GradientDrawable;
import android.view.ViewOutlineProvider;
import android.view.View;
class RoundedRectHelperApi21 {
- private static int sCornerRadius;
+ private static SparseArray<ViewOutlineProvider> sRoundedRectProvider;
+ private static final int MAX_CACHED_PROVIDER = 32;
+
+ static final class RoundedRectOutlineProvider extends ViewOutlineProvider {
+
+ private int mRadius;
+
+ RoundedRectOutlineProvider(int radius) {
+ mRadius = radius;
+ }
- private static final ViewOutlineProvider sOutlineProvider = new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
- if (sCornerRadius == 0) {
- sCornerRadius = view.getResources().getDimensionPixelSize(
- R.dimen.lb_rounded_rect_corner_radius);
- }
- outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), sCornerRadius);
+ outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mRadius);
outline.setAlpha(1f);
}
};
- public static void setClipToRoundedOutline(View view, boolean clip) {
- view.setOutlineProvider(clip ? sOutlineProvider : ViewOutlineProvider.BACKGROUND);
+ public static void setClipToRoundedOutline(View view, boolean clip, int roundedCornerRadius) {
+ if (clip) {
+ if (sRoundedRectProvider == null) {
+ sRoundedRectProvider = new SparseArray<ViewOutlineProvider>();
+ }
+ ViewOutlineProvider provider = sRoundedRectProvider.get(roundedCornerRadius);
+ if (provider == null) {
+ provider = new RoundedRectOutlineProvider(roundedCornerRadius);
+ if (sRoundedRectProvider.size() < MAX_CACHED_PROVIDER) {
+ sRoundedRectProvider.put(roundedCornerRadius, provider);
+ }
+ }
+ view.setOutlineProvider(provider);
+ } else {
+ view.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
+ }
view.setClipToOutline(clip);
}
}
diff --git a/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java b/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java
index ab4d179183..66f7687daf 100644
--- a/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java
+++ b/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 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
@@ -13,20 +13,15 @@
*/
package android.support.v17.leanback.widget;
-import android.support.v17.leanback.R;
-import android.content.res.Resources;
-import android.graphics.Color;
import android.graphics.Outline;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.view.ViewGroup;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
class ShadowHelperApi21 {
static class ShadowImpl {
- ViewGroup mShadowContainer;
+ View mShadowContainer;
float mNormalZ;
float mFocusedZ;
}
@@ -41,9 +36,10 @@ class ShadowHelperApi21 {
/* add shadows and return a implementation detail object */
public static Object addDynamicShadow(
- ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
- if (roundedCorners) {
- RoundedRectHelperApi21.setClipToRoundedOutline(shadowContainer, true);
+ View shadowContainer, float unfocusedZ, float focusedZ, int roundedCornerRadius) {
+ if (roundedCornerRadius > 0) {
+ RoundedRectHelperApi21.setClipToRoundedOutline(shadowContainer, true,
+ roundedCornerRadius);
} else {
shadowContainer.setOutlineProvider(sOutlineProvider);
}
@@ -52,7 +48,6 @@ class ShadowHelperApi21 {
impl.mNormalZ = unfocusedZ;
impl.mFocusedZ = focusedZ;
shadowContainer.setZ(impl.mNormalZ);
- shadowContainer.setTransitionGroup(true);
return impl;
}
diff --git a/v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java b/v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java
new file mode 100644
index 0000000000..c4760d44aa
--- /dev/null
+++ b/v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 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 android.support.v17.leanback.widget;
+
+import android.support.v17.leanback.R;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Outline;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.view.ViewGroup;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+class ForegroundHelperApi23 {
+
+ public static Drawable getForeground(View view) {
+ return view.getForeground();
+ }
+
+ public static void setForeground(View view, Drawable drawable) {
+ view.setForeground(drawable);
+ }
+}
diff --git a/v17/leanback/build.gradle b/v17/leanback/build.gradle
index 8dc79e8475..401a5c4100 100644
--- a/v17/leanback/build.gradle
+++ b/v17/leanback/build.gradle
@@ -19,8 +19,8 @@ android {
sourceSets {
main.manifest.srcFile 'AndroidManifest.xml'
- main.java.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'src']
- main.aidl.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'src']
+ main.java.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'api23', 'src']
+ main.aidl.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'api23', 'src']
main.res.srcDirs = ['res']
androidTest.setRoot('tests')
diff --git a/v17/leanback/common/android/support/v17/leanback/transition/TransitionListener.java b/v17/leanback/common/android/support/v17/leanback/transition/TransitionListener.java
index 80f05ede61..6a4056ea78 100644
--- a/v17/leanback/common/android/support/v17/leanback/transition/TransitionListener.java
+++ b/v17/leanback/common/android/support/v17/leanback/transition/TransitionListener.java
@@ -19,10 +19,20 @@ package android.support.v17.leanback.transition;
*/
public class TransitionListener {
+ protected Object mImpl;
+
public void onTransitionStart(Object transition) {
}
public void onTransitionEnd(Object transition) {
}
+ public void onTransitionCancel(Object transition) {
+ }
+
+ public void onTransitionPause(Object transition) {
+ }
+
+ public void onTransitionResume(Object transition) {
+ }
}
diff --git a/v17/leanback/generatev4.py b/v17/leanback/generatev4.py
index 605e9a1581..1b60b09ef4 100755
--- a/v17/leanback/generatev4.py
+++ b/v17/leanback/generatev4.py
@@ -20,7 +20,7 @@ import sys
print "Generate v4 fragment related code for leanback"
cls = ['Background', 'Base', 'BaseRow', 'Browse', 'Details', 'Error', 'Headers',
- 'PlaybackOverlay', 'Rows', 'Search', 'VerticalGrid', 'Branded']
+ 'PlaybackOverlay', 'Rows', 'Search', 'VerticalGrid', 'Branded', 'GuidedStep']
for w in cls:
print "copy {}Fragment to {}SupportFragment".format(w, w)
@@ -31,10 +31,24 @@ for w in cls:
outfile.write("/* This file is auto-generated from {}Fragment.java. DO NOT MODIFY. */\n\n".format(w))
for line in file:
+ line = line.replace('IS_FRAMEWORK_FRAGMENT = true', 'IS_FRAMEWORK_FRAGMENT = false');
for w in cls:
line = line.replace('{}Fragment'.format(w), '{}SupportFragment'.format(w))
line = line.replace('android.app.Fragment', 'android.support.v4.app.Fragment')
line = line.replace('android.app.Activity', 'android.support.v4.app.FragmentActivity')
+ line = line.replace('activity.getFragmentManager()', 'activity.getSupportFragmentManager()')
+ line = line.replace('Activity activity', 'FragmentActivity activity')
+ line = line.replace('(Activity', '(FragmentActivity')
outfile.write(line)
file.close()
outfile.close()
+
+file = open('src/android/support/v17/leanback/app/PlaybackControlGlue.java', 'r')
+outfile = open('src/android/support/v17/leanback/app/PlaybackControlSupportGlue.java', 'w')
+outfile.write("/* This file is auto-generated from PlaybackControlGlue.java. DO NOT MODIFY. */\n\n")
+for line in file:
+ line = line.replace('PlaybackControlGlue', 'PlaybackControlSupportGlue');
+ line = line.replace('PlaybackOverlayFragment', 'PlaybackOverlaySupportFragment');
+ outfile.write(line)
+file.close()
+outfile.close()
diff --git a/v17/leanback/kitkat/android/support/v17/leanback/transition/TransitionHelperKitkat.java b/v17/leanback/kitkat/android/support/v17/leanback/transition/TransitionHelperKitkat.java
index b4b6abe633..221b84acc0 100644
--- a/v17/leanback/kitkat/android/support/v17/leanback/transition/TransitionHelperKitkat.java
+++ b/v17/leanback/kitkat/android/support/v17/leanback/transition/TransitionHelperKitkat.java
@@ -185,9 +185,12 @@ final class TransitionHelperKitkat {
((Transition) transition).addTarget(targetView);
}
- static void setTransitionListener(Object transition, final TransitionListener listener) {
+ static void addTransitionListener(Object transition, final TransitionListener listener) {
+ if (listener == null) {
+ return;
+ }
Transition t = (Transition) transition;
- t.addListener(new Transition.TransitionListener() {
+ listener.mImpl = new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
@@ -196,10 +199,12 @@ final class TransitionHelperKitkat {
@Override
public void onTransitionResume(Transition transition) {
+ listener.onTransitionResume(transition);
}
@Override
public void onTransitionPause(Transition transition) {
+ listener.onTransitionPause(transition);
}
@Override
@@ -209,8 +214,19 @@ final class TransitionHelperKitkat {
@Override
public void onTransitionCancel(Transition transition) {
+ listener.onTransitionCancel(transition);
}
- });
+ };
+ t.addListener((Transition.TransitionListener) listener.mImpl);
+ }
+
+ static void removeTransitionListener(Object transition, final TransitionListener listener) {
+ if (listener == null || listener.mImpl == null) {
+ return;
+ }
+ Transition t = (Transition) transition;
+ t.removeListener((Transition.TransitionListener) listener.mImpl);
+ listener.mImpl = null;
}
static void runTransition(Object scene, Object transition) {
diff --git a/v17/leanback/project.properties b/v17/leanback/project.properties
index 91d2b02460..b2ef7dccc5 100644
--- a/v17/leanback/project.properties
+++ b/v17/leanback/project.properties
@@ -11,5 +11,5 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
-target=android-19
+target=android-23
android.library=true
diff --git a/v17/leanback/res/animator/lb_guidance_entry.xml b/v17/leanback/res/animator/lb_guidance_entry.xml
deleted file mode 100644
index e10d2ef0bc..0000000000
--- a/v17/leanback/res/animator/lb_guidance_entry.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:ordering="sequentially">
-
- <set android:ordering="together">
- <objectAnimator
- android:duration="@integer/lb_guidedstep_entry_animation_delay"
- android:propertyName="translationX"
- android:valueFrom="@dimen/lb_guidance_entry_translationX"
- android:valueTo="@dimen/lb_guidance_entry_translationX"
- android:valueType="floatType" />
-
- <objectAnimator
- android:duration="@integer/lb_guidedstep_entry_animation_delay"
- android:propertyName="alpha"
- android:valueFrom="0.0"
- android:valueTo="0.0"
- android:valueType="floatType" />
- </set>
-
- <set android:ordering="together">
- <objectAnimator
- android:duration="@integer/lb_guidedstep_entry_animation_duration"
- android:interpolator="@android:interpolator/decelerate_quad"
- android:propertyName="translationX"
- android:valueFrom="@dimen/lb_guidance_entry_translationX"
- android:valueTo="0.0"
- android:valueType="floatType" />
-
- <objectAnimator
- android:duration="@integer/lb_guidedstep_entry_animation_duration"
- android:interpolator="@android:interpolator/decelerate_quad"
- android:propertyName="alpha"
- android:valueFrom="0.0"
- android:valueTo="1.0"
- android:valueType="floatType" />
- </set>
-
-</set>
diff --git a/v17/leanback/res/animator/lb_guidedactions_entry.xml b/v17/leanback/res/animator/lb_guidedactions_entry.xml
deleted file mode 100644
index ec6c6551eb..0000000000
--- a/v17/leanback/res/animator/lb_guidedactions_entry.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:ordering="sequentially">
-
- <set android:ordering="together">
- <objectAnimator
- android:duration="@integer/lb_guidedstep_entry_animation_delay"
- android:propertyName="translationX"
- android:valueFrom="@dimen/lb_guidedactions_entry_translationX"
- android:valueTo="@dimen/lb_guidedactions_entry_translationX"
- android:valueType="floatType" />
-
- <objectAnimator
- android:duration="@integer/lb_guidedstep_entry_animation_delay"
- android:propertyName="alpha"
- android:valueFrom="0.0"
- android:valueTo="0.0"
- android:valueType="floatType" />
- </set>
-
- <set android:ordering="together">
- <objectAnimator
- android:duration="@integer/lb_guidedstep_entry_animation_duration"
- android:interpolator="@android:interpolator/decelerate_quad"
- android:propertyName="translationX"
- android:valueFrom="@dimen/lb_guidedactions_entry_translationX"
- android:valueTo="0.0"
- android:valueType="floatType" />
-
- <objectAnimator
- android:duration="@integer/lb_guidedstep_entry_animation_duration"
- android:interpolator="@android:interpolator/decelerate_quad"
- android:propertyName="alpha"
- android:valueFrom="0.0"
- android:valueTo="1.0"
- android:valueType="floatType" />
- </set>
-</set> \ No newline at end of file
diff --git a/v17/leanback/res/animator/lb_guidedactions_selector_hide.xml b/v17/leanback/res/animator/lb_guidedactions_selector_hide.xml
index f829eb3e89..e5dafb03b1 100644
--- a/v17/leanback/res/animator/lb_guidedactions_selector_hide.xml
+++ b/v17/leanback/res/animator/lb_guidedactions_selector_hide.xml
@@ -17,7 +17,6 @@
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@integer/lb_guidedactions_animation_duration"
android:propertyName="alpha"
- android:valueFrom="1.0"
android:valueTo="0.0"
android:interpolator="@animator/lb_decelerator_2"
android:valueType="floatType" />
diff --git a/v17/leanback/res/animator/lb_guidedactions_selector_show.xml b/v17/leanback/res/animator/lb_guidedactions_selector_show.xml
index e8d69e570a..fcfd9fa930 100644
--- a/v17/leanback/res/animator/lb_guidedactions_selector_show.xml
+++ b/v17/leanback/res/animator/lb_guidedactions_selector_show.xml
@@ -20,7 +20,6 @@
<objectAnimator
android:duration="@integer/lb_guidedactions_animation_duration"
android:propertyName="alpha"
- android:valueFrom="0"
android:valueTo="1.0"
android:interpolator="@animator/lb_decelerator_2"
android:valueType="floatType" />
diff --git a/v17/leanback/res/animator/lb_guidedactions_item_unchecked.xml b/v17/leanback/res/animator/lb_guidedstep_slide_down.xml
index 86525c8520..b31421fd53 100644
--- a/v17/leanback/res/animator/lb_guidedactions_item_unchecked.xml
+++ b/v17/leanback/res/animator/lb_guidedstep_slide_down.xml
@@ -15,8 +15,8 @@
limitations under the License.
-->
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:duration="@integer/lb_guidedactions_item_animation_duration"
- android:propertyName="alpha"
- android:valueFrom="1.0"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:propertyName="translationY"
+ android:valueFrom="@dimen/lb_guidedstep_slide_ime_distance"
android:valueTo="0.0"
android:valueType="floatType" />
diff --git a/v17/leanback/res/animator/lb_guidedstep_slide_in_from_end.xml b/v17/leanback/res/animator/lb_guidedstep_slide_in_from_end.xml
deleted file mode 100644
index 1dacdbc38c..0000000000
--- a/v17/leanback/res/animator/lb_guidedstep_slide_in_from_end.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:ordering="together" >
-
- <objectAnimator
- android:duration="@android:integer/config_longAnimTime"
- android:propertyName="translationX"
- android:valueFrom="@dimen/lb_guidedstep_slide_end_distance"
- android:valueTo="0.0"
- android:valueType="floatType" />
-
- <objectAnimator
- android:duration="@android:integer/config_longAnimTime"
- android:propertyName="alpha"
- android:valueFrom="0.0"
- android:valueTo="1.0"
- android:valueType="floatType" />
-
-</set>
diff --git a/v17/leanback/res/animator/lb_guidedstep_slide_in_from_start.xml b/v17/leanback/res/animator/lb_guidedstep_slide_in_from_start.xml
deleted file mode 100644
index 3c01324f9a..0000000000
--- a/v17/leanback/res/animator/lb_guidedstep_slide_in_from_start.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:ordering="together" >
-
- <objectAnimator
- android:duration="@android:integer/config_longAnimTime"
- android:propertyName="translationX"
- android:valueFrom="@dimen/lb_guidedstep_slide_start_distance"
- android:valueTo="0.0"
- android:valueType="floatType" />
-
- <objectAnimator
- android:duration="@android:integer/config_longAnimTime"
- android:propertyName="alpha"
- android:valueFrom="0.0"
- android:valueTo="1.0"
- android:valueType="floatType" />
-
-</set>
diff --git a/v17/leanback/res/animator/lb_guidedstep_slide_out_to_end.xml b/v17/leanback/res/animator/lb_guidedstep_slide_out_to_end.xml
deleted file mode 100644
index 879a0cf577..0000000000
--- a/v17/leanback/res/animator/lb_guidedstep_slide_out_to_end.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:ordering="together" >
-
- <objectAnimator
- android:duration="@android:integer/config_longAnimTime"
- android:propertyName="translationX"
- android:valueFrom="0.0"
- android:valueTo="@dimen/lb_guidedstep_slide_end_distance"
- android:valueType="floatType" />
-
- <objectAnimator
- android:duration="@android:integer/config_longAnimTime"
- android:propertyName="alpha"
- android:valueFrom="1.0"
- android:valueTo="0.0"
- android:valueType="floatType" />
-
-</set>
diff --git a/v17/leanback/res/animator/lb_guidedstep_slide_out_to_start.xml b/v17/leanback/res/animator/lb_guidedstep_slide_out_to_start.xml
deleted file mode 100644
index 4c9af82bd2..0000000000
--- a/v17/leanback/res/animator/lb_guidedstep_slide_out_to_start.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:ordering="together" >
-
- <objectAnimator
- android:duration="@android:integer/config_longAnimTime"
- android:propertyName="translationX"
- android:valueFrom="0.0"
- android:valueTo="@dimen/lb_guidedstep_slide_start_distance"
- android:valueType="floatType" />
-
- <objectAnimator
- android:duration="@android:integer/config_longAnimTime"
- android:propertyName="alpha"
- android:valueFrom="1.0"
- android:valueTo="0.0"
- android:valueType="floatType" />
-
-</set>
diff --git a/v17/leanback/res/animator/lb_guidedactions_item_checked.xml b/v17/leanback/res/animator/lb_guidedstep_slide_up.xml
index 463b9f7bf5..165fe18bca 100644
--- a/v17/leanback/res/animator/lb_guidedactions_item_checked.xml
+++ b/v17/leanback/res/animator/lb_guidedstep_slide_up.xml
@@ -15,8 +15,8 @@
limitations under the License.
-->
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:duration="@integer/lb_guidedactions_item_animation_duration"
- android:propertyName="alpha"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:propertyName="translationY"
android:valueFrom="0.0"
- android:valueTo="1.0"
+ android:valueTo="@dimen/lb_guidedstep_slide_ime_distance"
android:valueType="floatType" />
diff --git a/v17/leanback/res/drawable/lb_headers_right_fading.xml b/v17/leanback/res/drawable/lb_headers_right_fading.xml
index 96794db5a5..b20c4e84d0 100644
--- a/v17/leanback/res/drawable/lb_headers_right_fading.xml
+++ b/v17/leanback/res/drawable/lb_headers_right_fading.xml
@@ -20,6 +20,6 @@
<gradient
android:angle="0"
android:startColor="#00000000"
- android:endColor="@color/lb_default_brand_color"
+ android:endColor="?attr/defaultBrandColor"
/>
</shape>
diff --git a/v17/leanback/res/layout/lb_fullwidth_details_overview.xml b/v17/leanback/res/layout/lb_fullwidth_details_overview.xml
index 8dbb630b46..415bd82dea 100644
--- a/v17/leanback/res/layout/lb_fullwidth_details_overview.xml
+++ b/v17/leanback/res/layout/lb_fullwidth_details_overview.xml
@@ -34,7 +34,7 @@
android:layout_height="@dimen/lb_details_v2_card_height"
android:layout_marginTop="@dimen/lb_details_v2_blank_height"
android:clipToPadding="false"
- android:foreground="#ffffff"
+ android:background="?attr/defaultBrandColor"
android:elevation="@dimen/lb_details_overview_z"
>
@@ -48,6 +48,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/details_overview_actions_background"
+ android:background="?attr/defaultBrandColorDark"
android:orientation="vertical" >
<android.support.v17.leanback.widget.HorizontalGridView
diff --git a/v17/leanback/res/layout/lb_guidedactions.xml b/v17/leanback/res/layout/lb_guidedactions.xml
index 43617c9481..f2926d361b 100644
--- a/v17/leanback/res/layout/lb_guidedactions.xml
+++ b/v17/leanback/res/layout/lb_guidedactions.xml
@@ -16,20 +16,36 @@
-->
<!-- Layout for the settings list fragment -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <RelativeLayout
- style="?attr/guidedActionsContainerStyle" >
-
- <FrameLayout
- android:id="@+id/guidedactions_selector"
- style="?attr/guidedActionsSelectorStyle" />
-
+ android:id="@+id/guidedactions_root"
+ android:transitionName="guidedactions_root"
+ android:transitionGroup="false"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="match_parent">
+
+ <android.support.v17.leanback.widget.NonOverlappingView
+ android:id="@+id/guidedactions_list_background"
+ android:transitionName="guidedactions_list_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ android:background="?attr/guidedActionsBackgroundDark" />
+
+ <android.support.v17.leanback.widget.NonOverlappingFrameLayout
+ android:id="@+id/guidedactions_content"
+ android:transitionName="guidedactions_content"
+ android:transitionGroup="false"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<android.support.v17.leanback.widget.VerticalGridView
+ android:transitionGroup="true"
android:id="@+id/guidedactions_list"
style="?attr/guidedActionsListStyle" />
- </RelativeLayout>
+ <android.support.v17.leanback.widget.NonOverlappingView
+ android:id="@+id/guidedactions_selector"
+ android:transitionName="guidedactions_selector"
+ style="?attr/guidedActionsSelectorStyle" />
+ </android.support.v17.leanback.widget.NonOverlappingFrameLayout>
</RelativeLayout>
diff --git a/v17/leanback/res/layout/lb_guidedactions_item.xml b/v17/leanback/res/layout/lb_guidedactions_item.xml
index 4e414549e0..831c355a16 100644
--- a/v17/leanback/res/layout/lb_guidedactions_item.xml
+++ b/v17/leanback/res/layout/lb_guidedactions_item.xml
@@ -20,7 +20,7 @@
xmlns:tools="http://schemas.android.com/tools"
style="?attr/guidedActionItemContainerStyle" >
- <ImageView
+ <android.support.v17.leanback.widget.CheckableImageView
android:id="@+id/guidedactions_item_checkmark"
style="?attr/guidedActionItemCheckmarkStyle"
tools:ignore="ContentDescription" />
@@ -34,13 +34,14 @@
android:id="@+id/guidedactions_item_content"
style="?attr/guidedActionItemContentStyle" >
- <TextView
+ <android.support.v17.leanback.widget.GuidedActionEditText
android:id="@+id/guidedactions_item_title"
style="?attr/guidedActionItemTitleStyle" />
- <TextView
+ <android.support.v17.leanback.widget.GuidedActionEditText
android:id="@+id/guidedactions_item_description"
style="?attr/guidedActionItemDescriptionStyle" />
+
</android.support.v17.leanback.widget.NonOverlappingLinearLayout>
<ImageView
diff --git a/v17/leanback/res/layout/lb_guidedstep_background.xml b/v17/leanback/res/layout/lb_guidedstep_background.xml
new file mode 100644
index 0000000000..08ea47d519
--- /dev/null
+++ b/v17/leanback/res/layout/lb_guidedstep_background.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+<android.support.v17.leanback.widget.NonOverlappingView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/guidedstep_background"
+ android:transitionName="guidedstep_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?attr/guidedStepBackground" />
+
diff --git a/v17/leanback/res/layout/lb_guidedstep_fragment.xml b/v17/leanback/res/layout/lb_guidedstep_fragment.xml
index 6e0b7adf5b..a41d47d32b 100644
--- a/v17/leanback/res/layout/lb_guidedstep_fragment.xml
+++ b/v17/leanback/res/layout/lb_guidedstep_fragment.xml
@@ -15,21 +15,57 @@
limitations under the License.
-->
<!-- Layout for the frame of a 2 pane actions fragment. -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/content_frame"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/guidedstep_root"
+ android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
+ <LinearLayout
+ android:id="@+id/content_frame"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
- <FrameLayout
- android:id="@+id/content_fragment"
- android:layout_width="@dimen/lb_guidedstep_guidance_section_width"
- android:layout_height="match_parent"
- android:layout_alignParentStart="true" />
+ <android.support.v17.leanback.widget.NonOverlappingFrameLayout
+ android:id="@+id/content_fragment"
+ android:layout_toStartOf="@+id/action_fragment"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="match_parent"
+ android:layout_alignParentStart="true" />
- <FrameLayout
- android:id="@+id/action_fragment"
- android:layout_width="@dimen/lb_guidedactions_section_width_with_shadow"
- android:layout_height="match_parent"
- android:layout_alignParentEnd="true" />
+ <android.support.v17.leanback.widget.NonOverlappingFrameLayout
+ android:id="@+id/action_fragment_root"
+ android:transitionName="action_fragment_root"
+ android:transitionGroup="false"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:clipChildren="false"
+ android:paddingStart="@dimen/lb_guidedactions_section_shadow_width"
+ android:layout_width="0dp"
+ android:layout_weight="?attr/guidedActionContentWidthWeight"
+ android:layout_height="match_parent"
+ android:layout_alignParentEnd="true">
-</RelativeLayout> \ No newline at end of file
+ <android.support.v17.leanback.widget.NonOverlappingView
+ android:id="@+id/action_fragment_background"
+ android:transitionName="action_fragment_background"
+ android:orientation="horizontal"
+ android:outlineProvider="paddedBounds"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?attr/guidedActionsBackground"
+ android:elevation="?attr/guidedActionsElevation" />
+
+ <android.support.v17.leanback.widget.NonOverlappingLinearLayout
+ android:id="@+id/action_fragment"
+ android:transitionName="action_fragment"
+ android:transitionGroup="false"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:elevation="?attr/guidedActionsElevation" />
+ </android.support.v17.leanback.widget.NonOverlappingFrameLayout>
+
+ </LinearLayout>
+</FrameLayout> \ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_image_card_view.xml b/v17/leanback/res/layout/lb_image_card_view.xml
index 2261965ee1..1bc23f8846 100644
--- a/v17/leanback/res/layout/lb_image_card_view.xml
+++ b/v17/leanback/res/layout/lb_image_card_view.xml
@@ -15,59 +15,16 @@
limitations under the License.
-->
-<merge
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:lb="http://schemas.android.com/apk/res-auto">
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:lb="http://schemas.android.com/apk/res-auto" >
<ImageView
android:id="@+id/main_image"
- lb:layout_viewType="main"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scaleType="centerCrop"
- android:adjustViewBounds="true"
- android:contentDescription="@null" />
- <android.support.v17.leanback.widget.NonOverlappingRelativeLayout
- lb:layout_viewType="info"
- android:id="@+id/info_field"
- android:layout_width="match_parent"
- android:layout_height="@dimen/lb_basic_card_info_height"
- android:paddingStart="@dimen/lb_basic_card_info_padding_horizontal"
- android:paddingEnd="@dimen/lb_basic_card_info_padding_horizontal"
- android:paddingTop="@dimen/lb_basic_card_info_padding_top"
- android:layout_centerHorizontal="true" >
- <TextView
- android:id="@+id/title_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_marginBottom="@dimen/lb_basic_card_info_text_margin"
- android:maxLines="1"
- android:fontFamily="sans-serif-condensed"
- android:textColor="@color/lb_basic_card_title_text_color"
- android:textSize="@dimen/lb_basic_card_title_text_size"
- android:ellipsize="end" />
- <TextView
- android:id="@+id/content_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/title_text"
- android:layout_alignParentStart="true"
- android:layout_toStartOf="@+id/extra_badge"
- android:maxLines="1"
- android:fontFamily="sans-serif-condensed"
- android:textColor="@color/lb_basic_card_content_text_color"
- android:textSize="@dimen/lb_basic_card_content_text_size"
- android:ellipsize="none" />
- <ImageView
- android:id="@+id/extra_badge"
- android:layout_width="@dimen/lb_basic_card_info_badge_size"
- android:layout_height="@dimen/lb_basic_card_info_badge_size"
- android:layout_marginStart="@dimen/lb_basic_card_info_badge_margin"
- android:layout_alignBottom="@id/content_text"
- android:layout_alignParentEnd="true"
- android:scaleType="fitCenter"
- android:visibility="gone"
- android:contentDescription="@null" />
- </android.support.v17.leanback.widget.NonOverlappingRelativeLayout>
-</merge>
+ style="?attr/lbImageCardViewImageStyle" />
+
+ <android.support.v17.leanback.widget.NonOverlappingRelativeLayout
+ android:id="@+id/info_field"
+ style="?attr/lbImageCardViewInfoAreaStyle">
+ </android.support.v17.leanback.widget.NonOverlappingRelativeLayout>
+
+</merge> \ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml b/v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml
new file mode 100644
index 0000000000..35d2da655a
--- /dev/null
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/extra_badge"
+ android:layout_alignBottom="@+id/content_text"
+ android:layout_alignParentStart="true"
+ android:layout_marginEnd="@dimen/lb_basic_card_info_badge_margin"
+ style="?attr/lbImageCardViewBadgeStyle" /> \ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml b/v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml
new file mode 100644
index 0000000000..02dd917244
--- /dev/null
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/extra_badge"
+ android:layout_alignBottom="@+id/content_text"
+ android:layout_alignParentEnd="true"
+ android:layout_marginStart="@dimen/lb_basic_card_info_badge_margin"
+ style="?attr/lbImageCardViewBadgeStyle" /> \ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/layout/lb_image_card_view_themed_content.xml
index 45a40e176c..5592371532 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_content.xml
@@ -15,7 +15,6 @@
limitations under the License.
-->
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content_text"
+ style="?attr/lbImageCardViewContentStyle" />
diff --git a/v17/leanback/res/layout/lb_image_card_view_themed_title.xml b/v17/leanback/res/layout/lb_image_card_view_themed_title.xml
new file mode 100644
index 0000000000..67e2493887
--- /dev/null
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_title.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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="@+id/title_text"
+ style="?attr/lbImageCardViewTitleStyle" />
diff --git a/v17/leanback/res/layout/lb_search_fragment.xml b/v17/leanback/res/layout/lb_search_fragment.xml
index 57a46b4041..25150d3587 100644
--- a/v17/leanback/res/layout/lb_search_fragment.xml
+++ b/v17/leanback/res/layout/lb_search_fragment.xml
@@ -18,8 +18,6 @@ limitations under the License.
android:id="@+id/lb_search_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="@dimen/lb_search_bar_padding_top"
- android:clipToPadding="false"
android:clipChildren="false"
>
<FrameLayout
@@ -28,6 +26,7 @@ limitations under the License.
android:layout_height="match_parent"/>
<android.support.v17.leanback.widget.SearchBar
android:id="@+id/lb_search_bar"
+ android:layout_marginTop="@dimen/lb_search_bar_padding_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipChildren="false"
diff --git a/v17/leanback/res/transition-v21/lb_browse_entrance_transition.xml b/v17/leanback/res/transition-v21/lb_browse_entrance_transition.xml
index e26204bc81..9dd440b1d7 100644
--- a/v17/leanback/res/transition-v21/lb_browse_entrance_transition.xml
+++ b/v17/leanback/res/transition-v21/lb_browse_entrance_transition.xml
@@ -23,6 +23,6 @@
<slide
android:duration="350"
android:interpolator="@android:interpolator/linear_out_slow_in"
- android:slideEdge="right">
+ android:slideEdge="@integer/slideEdgeEnd">
</slide>
</transitionSet> \ No newline at end of file
diff --git a/v17/leanback/res/transition-v21/lb_browse_return_transition.xml b/v17/leanback/res/transition-v21/lb_browse_return_transition.xml
index 84ae9935b8..6d341b5eeb 100644
--- a/v17/leanback/res/transition-v21/lb_browse_return_transition.xml
+++ b/v17/leanback/res/transition-v21/lb_browse_return_transition.xml
@@ -18,7 +18,7 @@
<slide
android:interpolator="@android:interpolator/fast_out_linear_in"
android:duration="350"
- android:slideEdge="left">
+ android:slideEdge="@integer/slideEdgeStart">
<targets>
<target android:targetId="@id/browse_headers_root" />
<target android:targetId="@id/title_orb" />
@@ -27,7 +27,7 @@
<slide
android:interpolator="@android:interpolator/fast_out_linear_in"
android:duration="350"
- android:slideEdge="right">
+ android:slideEdge="@integer/slideEdgeEnd">
<targets>
<target android:excludeId="@+id/browse_headers_root" />
<target android:excludeId="@+id/title_orb" />
diff --git a/v17/leanback/res/transition-v21/lb_guidedstep_activity_enter.xml b/v17/leanback/res/transition-v21/lb_guidedstep_activity_enter.xml
new file mode 100644
index 0000000000..5ee74ee028
--- /dev/null
+++ b/v17/leanback/res/transition-v21/lb_guidedstep_activity_enter.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android" >
+ <fade
+ android:interpolator="@android:interpolator/fast_out_linear_in"
+ android:duration="@integer/lb_guidedstep_activity_background_fade_duration_ms">
+ <targets>
+ <target android:targetId="@id/guidedstep_background" />
+ </targets>
+ </fade>
+ <slide
+ android:interpolator="@android:interpolator/fast_out_linear_in"
+ android:duration="350"
+ android:slideEdge="@integer/slideEdgeStart">
+ <targets>
+ <target android:targetId="@id/guidance_icon" />
+ <target android:targetId="@id/guidance_title" />
+ <target android:targetId="@id/guidance_breadcrumb" />
+ <target android:targetId="@id/guidance_description" />
+ </targets>
+ </slide>
+ <slide
+ android:interpolator="@android:interpolator/fast_out_linear_in"
+ android:duration="350"
+ android:slideEdge="@integer/slideEdgeEnd">
+ <targets>
+ <target android:targetId="@id/action_fragment_background" />
+ <target android:targetId="@id/guidedactions_list_background" />
+ <target android:targetId="@id/guidedactions_content" />
+ <target android:targetId="@id/guidedactions_list" />
+ <target android:targetId="@id/guidedactions_selector" />
+ <target android:targetId="@id/guidedactions_list_background2" />
+ <target android:targetId="@id/guidedactions_content2" />
+ <target android:targetId="@id/guidedactions_list2" />
+ <target android:targetId="@id/guidedactions_selector2" />
+ </targets>
+ </slide>
+</transitionSet> \ No newline at end of file
diff --git a/v17/leanback/res/transition-v21/lb_vertical_grid_enter_transition.xml b/v17/leanback/res/transition-v21/lb_vertical_grid_enter_transition.xml
new file mode 100644
index 0000000000..00466cbbde
--- /dev/null
+++ b/v17/leanback/res/transition-v21/lb_vertical_grid_enter_transition.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android" >
+ <fade
+ android:interpolator="@android:interpolator/linear_out_slow_in"
+ android:duration="150"/>
+</transitionSet> \ No newline at end of file
diff --git a/v17/leanback/res/transition-v22/lb_browse_entrance_transition.xml b/v17/leanback/res/transition-v21/lb_vertical_grid_entrance_transition.xml
index 2068c64458..ee06953119 100644
--- a/v17/leanback/res/transition-v22/lb_browse_entrance_transition.xml
+++ b/v17/leanback/res/transition-v21/lb_vertical_grid_entrance_transition.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2015 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.
@@ -16,13 +16,9 @@
-->
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android" >
- <changeBounds
- android:duration="350"
- android:interpolator="@android:interpolator/linear_out_slow_in">
- </changeBounds>
<slide
android:duration="350"
android:interpolator="@android:interpolator/linear_out_slow_in"
- android:slideEdge="end">
+ android:slideEdge="bottom">
</slide>
</transitionSet> \ No newline at end of file
diff --git a/v17/leanback/res/transition-v22/lb_browse_return_transition.xml b/v17/leanback/res/transition-v21/lb_vertical_grid_return_transition.xml
index e8dbee0cd6..edb3816f3b 100644
--- a/v17/leanback/res/transition-v22/lb_browse_return_transition.xml
+++ b/v17/leanback/res/transition-v21/lb_vertical_grid_return_transition.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2015 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.
@@ -18,26 +18,15 @@
<slide
android:interpolator="@android:interpolator/fast_out_linear_in"
android:duration="350"
- android:slideEdge="start">
+ android:slideEdge="bottom">
<targets>
- <target android:targetId="@id/browse_headers_root" />
- <target android:targetId="@id/title_orb" />
- </targets>
- </slide>
- <slide
- android:interpolator="@android:interpolator/fast_out_linear_in"
- android:duration="350"
- android:slideEdge="end">
- <targets>
- <target android:excludeId="@+id/browse_headers_root" />
<target android:excludeId="@+id/title_orb" />
+ <target android:excludeId="@+id/title_text" />
+ <target android:excludeId="@+id/title_badge" />
</targets>
</slide>
<fade
android:interpolator="@android:interpolator/fast_out_linear_in"
android:duration="350">
- <targets>
- <target android:excludeId="@+id/browse_headers_root" />
- </targets>
</fade>
</transitionSet> \ No newline at end of file
diff --git a/v17/leanback/res/values-af/strings.xml b/v17/leanback/res/values-af/strings.xml
index c7109bbf9f..03104033a3 100644
--- a/v17/leanback/res/values-af/strings.xml
+++ b/v17/leanback/res/values-af/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Deaktiveer hoë gehalte"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktiveer onderskrifte"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Deaktiveer onderskrifte"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Voltooi"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Gaan voort"</string>
</resources>
diff --git a/v17/leanback/res/values-am/strings.xml b/v17/leanback/res/values-am/strings.xml
index d5bf0f5cc4..77d29936af 100644
--- a/v17/leanback/res/values-am/strings.xml
+++ b/v17/leanback/res/values-am/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ከፍተኛ ጥራትን አሰናክል"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"ዝግ የምስል ስር ጽሑፍ አጻጻፍን አንቃ"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"ዝግ የምስል ስር ጽሑፍ አጻጻፍን አሰናክል"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"ጨርስ"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"ቀጥል"</string>
</resources>
diff --git a/v17/leanback/res/values-ar/strings.xml b/v17/leanback/res/values-ar/strings.xml
index 31f4d1a056..c52be7fa76 100644
--- a/v17/leanback/res/values-ar/strings.xml
+++ b/v17/leanback/res/values-ar/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"تعطيل الجودة العالية"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"تمكين الترجمة المصاحبة"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"تعطيل الترجمة المصاحبة"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"إنهاء"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"متابعة"</string>
</resources>
diff --git a/v17/leanback/res/values-az-rAZ/strings.xml b/v17/leanback/res/values-az-rAZ/strings.xml
index d1e685f8a7..cb558a02d4 100644
--- a/v17/leanback/res/values-az-rAZ/strings.xml
+++ b/v17/leanback/res/values-az-rAZ/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Yüksək keyfiyyəti deaktiv edin"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Qapalı çəkilişi aktiv edin"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Qapalı çəkilişi deaktiv edin"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Bitir"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Davam edin"</string>
</resources>
diff --git a/v17/leanback/res/values-bg/strings.xml b/v17/leanback/res/values-bg/strings.xml
index 74c01b61fd..6b16775bcc 100644
--- a/v17/leanback/res/values-bg/strings.xml
+++ b/v17/leanback/res/values-bg/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Деактивиране на високото качество"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Активиране на субтитрите"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Деактивиране на субтитрите"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Край"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Напред"</string>
</resources>
diff --git a/v17/leanback/res/values-bn-rBD/strings.xml b/v17/leanback/res/values-bn-rBD/strings.xml
index 4f0526cde0..04669bd30e 100644
--- a/v17/leanback/res/values-bn-rBD/strings.xml
+++ b/v17/leanback/res/values-bn-rBD/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"উচ্চ গুণমান অক্ষম করুন"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"সাবটাইটেল সক্ষম করুন"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"সাবটাইটেল অক্ষম করুন"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"শেষ করুন"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"চালিয়ে যান"</string>
</resources>
diff --git a/v17/leanback/res/values-ca/strings.xml b/v17/leanback/res/values-ca/strings.xml
index dbf20a89bb..6578f3bafe 100644
--- a/v17/leanback/res/values-ca/strings.xml
+++ b/v17/leanback/res/values-ca/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desactiva l\'alta qualitat"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activa els subtítols tancats"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desactiva els subtítols tancats"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Finalitza"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continua"</string>
</resources>
diff --git a/v17/leanback/res/values-cs/strings.xml b/v17/leanback/res/values-cs/strings.xml
index 13f96893e8..8ffb4f304d 100644
--- a/v17/leanback/res/values-cs/strings.xml
+++ b/v17/leanback/res/values-cs/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Vypnout vysokou kvalitu"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Zapnout titulky"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Vypnout titulky"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Dokončit"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Pokračovat"</string>
</resources>
diff --git a/v17/leanback/res/values-da/strings.xml b/v17/leanback/res/values-da/strings.xml
index 701138f970..87c507b3c4 100644
--- a/v17/leanback/res/values-da/strings.xml
+++ b/v17/leanback/res/values-da/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Deaktiver høj kvalitet"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktivér undertekster"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Deaktiver undertekster"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Afslut"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Fortsæt"</string>
</resources>
diff --git a/v17/leanback/res/values-de/strings.xml b/v17/leanback/res/values-de/strings.xml
index db0c3e03da..9d018c619a 100644
--- a/v17/leanback/res/values-de/strings.xml
+++ b/v17/leanback/res/values-de/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Hohe Qualität deaktivieren"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Untertitel aktivieren"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Untertitel deaktivieren"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Fertigstellen"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Weiter"</string>
</resources>
diff --git a/v17/leanback/res/values-el/strings.xml b/v17/leanback/res/values-el/strings.xml
index 6c4f603f21..310b6a9962 100644
--- a/v17/leanback/res/values-el/strings.xml
+++ b/v17/leanback/res/values-el/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Απενεργοποίηση Υψηλής ποιότητας"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ενεργοποίηση υποτίτλων"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Απενεργοποίηση υποτίτλων"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Τέλος"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Συνέχεια"</string>
</resources>
diff --git a/v17/leanback/res/values-en-rAU/strings.xml b/v17/leanback/res/values-en-rAU/strings.xml
index ed22ccd781..0097135d1d 100644
--- a/v17/leanback/res/values-en-rAU/strings.xml
+++ b/v17/leanback/res/values-en-rAU/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Disable High Quality"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Enable Closed Captioning"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Disable Closed Captioning"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Finish"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continue"</string>
</resources>
diff --git a/v17/leanback/res/values-en-rGB/strings.xml b/v17/leanback/res/values-en-rGB/strings.xml
index ed22ccd781..0097135d1d 100644
--- a/v17/leanback/res/values-en-rGB/strings.xml
+++ b/v17/leanback/res/values-en-rGB/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Disable High Quality"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Enable Closed Captioning"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Disable Closed Captioning"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Finish"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continue"</string>
</resources>
diff --git a/v17/leanback/res/values-en-rIN/strings.xml b/v17/leanback/res/values-en-rIN/strings.xml
index ed22ccd781..0097135d1d 100644
--- a/v17/leanback/res/values-en-rIN/strings.xml
+++ b/v17/leanback/res/values-en-rIN/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Disable High Quality"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Enable Closed Captioning"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Disable Closed Captioning"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Finish"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continue"</string>
</resources>
diff --git a/v17/leanback/res/values-es-rUS/strings.xml b/v17/leanback/res/values-es-rUS/strings.xml
index ab05f83ad1..8341a4dc86 100644
--- a/v17/leanback/res/values-es-rUS/strings.xml
+++ b/v17/leanback/res/values-es-rUS/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Inhabilitar calidad alta"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Habilitar subtítulos"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Inhabilitar subtítulos"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Finalizar"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continuar"</string>
</resources>
diff --git a/v17/leanback/res/values-es/strings.xml b/v17/leanback/res/values-es/strings.xml
index 9e6c526684..9f308c03e5 100644
--- a/v17/leanback/res/values-es/strings.xml
+++ b/v17/leanback/res/values-es/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Inhabilitar alta calidad"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Habilitar subtítulos"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Inhabilitar subtítulos"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Finalizar"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continuar"</string>
</resources>
diff --git a/v17/leanback/res/values-et-rEE/strings.xml b/v17/leanback/res/values-et-rEE/strings.xml
index cfda00e9cb..a97c385246 100644
--- a/v17/leanback/res/values-et-rEE/strings.xml
+++ b/v17/leanback/res/values-et-rEE/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Keela kõrgkvaliteetne taasesitus"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Luba subtiitrid"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Keela subtiitrid"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Lõpeta"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Jätka"</string>
</resources>
diff --git a/v17/leanback/res/values-eu-rES/strings.xml b/v17/leanback/res/values-eu-rES/strings.xml
index d9f9bf7a43..c22f172a51 100644
--- a/v17/leanback/res/values-eu-rES/strings.xml
+++ b/v17/leanback/res/values-eu-rES/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desgaitu kalitate handiko erreprodukzioa"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Gaitu azpitituluak"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desgaitu azpitituluak"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Amaitu"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Jarraitu"</string>
</resources>
diff --git a/v17/leanback/res/values-fa/strings.xml b/v17/leanback/res/values-fa/strings.xml
index bb615fcd7f..58e823f5bf 100644
--- a/v17/leanback/res/values-fa/strings.xml
+++ b/v17/leanback/res/values-fa/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"غیرفعال کردن کیفیت بالا"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"فعال کردن زیرنویس"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"غیرفعال کردن زیرنویس"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"پایان"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"ادامه"</string>
</resources>
diff --git a/v17/leanback/res/values-fi/strings.xml b/v17/leanback/res/values-fi/strings.xml
index 92b5f12a44..0c55e6fea6 100644
--- a/v17/leanback/res/values-fi/strings.xml
+++ b/v17/leanback/res/values-fi/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Poista korkea laatu käytöstä"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ota tekstitys käyttöön"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Poista tekstitys käytöstä"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Valmis"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Jatka"</string>
</resources>
diff --git a/v17/leanback/res/values-fr-rCA/strings.xml b/v17/leanback/res/values-fr-rCA/strings.xml
index bbd3eea0c3..b28beae5e6 100644
--- a/v17/leanback/res/values-fr-rCA/strings.xml
+++ b/v17/leanback/res/values-fr-rCA/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Désactiver la lecture haute qualité"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activer le sous-titrage"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Désactiver le sous-titrage"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Terminer"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continuer"</string>
</resources>
diff --git a/v17/leanback/res/values-fr/strings.xml b/v17/leanback/res/values-fr/strings.xml
index 0a3e6feab4..914bf08b7b 100644
--- a/v17/leanback/res/values-fr/strings.xml
+++ b/v17/leanback/res/values-fr/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Désactiver la haute qualité"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activer les sous-titres"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Désactiver les sous-titres"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Terminer"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continuer"</string>
</resources>
diff --git a/v17/leanback/res/values-gl-rES/strings.xml b/v17/leanback/res/values-gl-rES/strings.xml
index 717b994e88..62b3a2b9c1 100644
--- a/v17/leanback/res/values-gl-rES/strings.xml
+++ b/v17/leanback/res/values-gl-rES/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desactivar alta calidade"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activar subtítulos"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desactivar subtítulos"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Finalizar"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continuar"</string>
</resources>
diff --git a/v17/leanback/res/values-gu-rIN/strings.xml b/v17/leanback/res/values-gu-rIN/strings.xml
index 2e4f30f50c..afec9da91e 100644
--- a/v17/leanback/res/values-gu-rIN/strings.xml
+++ b/v17/leanback/res/values-gu-rIN/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ઉચ્ચ ગુણવત્તા અક્ષમ કરો"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"ઉપશીર્ષક સક્ષમ કરો"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"વિગતવાર ઉપશીર્ષકોને અક્ષમ કરો"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"સમાપ્ત કરો"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"ચાલુ રાખો"</string>
</resources>
diff --git a/v17/leanback/res/values-hi/strings.xml b/v17/leanback/res/values-hi/strings.xml
index a926396977..c243c17dba 100644
--- a/v17/leanback/res/values-hi/strings.xml
+++ b/v17/leanback/res/values-hi/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"उच्च गुणवत्ता अक्षम करें"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"उपशीर्षक सक्षम करें"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"उपशीर्षक अक्षम करें"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"समाप्त करें"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"जारी रखें"</string>
</resources>
diff --git a/v17/leanback/res/values-hr/strings.xml b/v17/leanback/res/values-hr/strings.xml
index 974de0af77..bb6ebcc6f4 100644
--- a/v17/leanback/res/values-hr/strings.xml
+++ b/v17/leanback/res/values-hr/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Onemogući visoku kvalitetu"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Omogući titlove"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Onemogući titlove"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Završi"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Nastavi"</string>
</resources>
diff --git a/v17/leanback/res/values-hu/strings.xml b/v17/leanback/res/values-hu/strings.xml
index 427f1cd6fb..cfeb2ada2e 100644
--- a/v17/leanback/res/values-hu/strings.xml
+++ b/v17/leanback/res/values-hu/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Jó minőségű lejátszás letiltása"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Feliratok engedélyezése"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Feliratok letiltása"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Befejezés"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Folytatás"</string>
</resources>
diff --git a/v17/leanback/res/values-hy-rAM/strings.xml b/v17/leanback/res/values-hy-rAM/strings.xml
index 7e8112e183..1ac5dd8113 100644
--- a/v17/leanback/res/values-hy-rAM/strings.xml
+++ b/v17/leanback/res/values-hy-rAM/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Անջատել բարձր որակը"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Միացնել խորագրերը"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Անջատել խորագրերը"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Վերջ"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Շարունակել"</string>
</resources>
diff --git a/v17/leanback/res/values-in/strings.xml b/v17/leanback/res/values-in/strings.xml
index 2dca7d3b66..6569825cdb 100644
--- a/v17/leanback/res/values-in/strings.xml
+++ b/v17/leanback/res/values-in/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Nonaktifkan Kualitas Tinggi"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktifkan Pembuatan Teks"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Nonaktifkan Pembuatan Teks"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Selesai"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Lanjutkan"</string>
</resources>
diff --git a/v17/leanback/res/values-is-rIS/strings.xml b/v17/leanback/res/values-is-rIS/strings.xml
index c84a4c6751..830b11e3df 100644
--- a/v17/leanback/res/values-is-rIS/strings.xml
+++ b/v17/leanback/res/values-is-rIS/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Slökkva á miklum gæðum"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Kveikja á skjátextum"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Slökkva á skjátextum"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Ljúka"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Halda áfram"</string>
</resources>
diff --git a/v17/leanback/res/values-it/strings.xml b/v17/leanback/res/values-it/strings.xml
index 1b58e0cebd..2f0ca47f2e 100644
--- a/v17/leanback/res/values-it/strings.xml
+++ b/v17/leanback/res/values-it/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Disattiva alta qualità"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Attiva sottotitoli"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Disattiva sottotitoli"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Fine"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continua"</string>
</resources>
diff --git a/v17/leanback/res/values-iw/strings.xml b/v17/leanback/res/values-iw/strings.xml
index f10249843b..f2bda5839e 100644
--- a/v17/leanback/res/values-iw/strings.xml
+++ b/v17/leanback/res/values-iw/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"השבת איכות גבוהה"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"הפעל כתוביות"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"השבת כתוביות"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"סיום"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"המשך"</string>
</resources>
diff --git a/v17/leanback/res/values-ja/strings.xml b/v17/leanback/res/values-ja/strings.xml
index 802631ce6f..09faa8b32d 100644
--- a/v17/leanback/res/values-ja/strings.xml
+++ b/v17/leanback/res/values-ja/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"高品質を無効にする"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"字幕を有効にする"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"字幕を無効にする"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"完了"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"続行"</string>
</resources>
diff --git a/v17/leanback/res/values-ka-rGE/strings.xml b/v17/leanback/res/values-ka-rGE/strings.xml
index 70aeada5c3..ac9f4cd7c3 100644
--- a/v17/leanback/res/values-ka-rGE/strings.xml
+++ b/v17/leanback/res/values-ka-rGE/strings.xml
@@ -50,4 +50,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"მაღალი ხარისხის გამორთვა"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"დახურული წარწერების ჩართვა"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"დახურული წარწერების გაუქმება"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"დასრულება"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"გაგრძელება"</string>
</resources>
diff --git a/v17/leanback/res/values-kk-rKZ/strings.xml b/v17/leanback/res/values-kk-rKZ/strings.xml
index 9ed6ce240e..380695b06b 100644
--- a/v17/leanback/res/values-kk-rKZ/strings.xml
+++ b/v17/leanback/res/values-kk-rKZ/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Жоғары сапаны өшіру"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Жасырын титрлерді қосу"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Жасырын титрлерді өшіру"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Аяқтау"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Жалғастыру"</string>
</resources>
diff --git a/v17/leanback/res/values-km-rKH/strings.xml b/v17/leanback/res/values-km-rKH/strings.xml
index 7874af2f57..60f90e5a7b 100644
--- a/v17/leanback/res/values-km-rKH/strings.xml
+++ b/v17/leanback/res/values-km-rKH/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"បិទ​គុណភាព​ខ្ពស់"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"បើក​ការ​ដាក់​ចំណង​ដែល​បាន​បិទ"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"បិទ​ការ​ដាក់​ចំណង​ដែល​បាន​បិទ"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"បញ្ចប់"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"បន្ត"</string>
</resources>
diff --git a/v17/leanback/res/values-kn-rIN/strings.xml b/v17/leanback/res/values-kn-rIN/strings.xml
index 196b154fcb..18206ed3f5 100644
--- a/v17/leanback/res/values-kn-rIN/strings.xml
+++ b/v17/leanback/res/values-kn-rIN/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ಹೆಚ್ಚು ಗುಣಮಟ್ಟವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"ಪೂರ್ಣಗೊಳಿಸು"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"ಮುಂದುವರಿಸು"</string>
</resources>
diff --git a/v17/leanback/res/values-ko/strings.xml b/v17/leanback/res/values-ko/strings.xml
index c244dbfbc7..e262b1c6fb 100644
--- a/v17/leanback/res/values-ko/strings.xml
+++ b/v17/leanback/res/values-ko/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"고화질 사용 중지"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"자막 사용 설정"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"자막 사용 중지"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"완료"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"계속"</string>
</resources>
diff --git a/v17/leanback/res/values-ky-rKG/strings.xml b/v17/leanback/res/values-ky-rKG/strings.xml
index 4ddb284364..74cc841465 100644
--- a/v17/leanback/res/values-ky-rKG/strings.xml
+++ b/v17/leanback/res/values-ky-rKG/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Жогорку сапатты өчүрүү"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Жабык субтитрлерди иштетүү"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Жабык субтитрлерди өчүрүү"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Бүтүрүү"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Улантуу"</string>
</resources>
diff --git a/v17/leanback/res/drawable/lb_guidedactions_item_checkmark.xml b/v17/leanback/res/values-ldrtl/integers.xml
index ec7903bf24..250523d3d1 100644
--- a/v17/leanback/res/drawable/lb_guidedactions_item_checkmark.xml
+++ b/v17/leanback/res/values-ldrtl/integers.xml
@@ -14,13 +14,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval" >
+<resources>
- <size
- android:height="@dimen/lb_guidedactions_item_checkmark_diameter"
- android:width="@dimen/lb_guidedactions_item_checkmark_diameter" />
+ <!-- Gravity.RIGHT -->
+ <integer name="slideEdgeStart">5</integer>
+ <!-- Gravity.LEFT -->
+ <integer name="slideEdgeEnd">3</integer>
- <solid android:color="@color/lb_tv_white" />
-
-</shape>
+</resources> \ No newline at end of file
diff --git a/v17/leanback/res/values-lo-rLA/strings.xml b/v17/leanback/res/values-lo-rLA/strings.xml
index 35f519b098..d919e9341a 100644
--- a/v17/leanback/res/values-lo-rLA/strings.xml
+++ b/v17/leanback/res/values-lo-rLA/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"​ປິດ​ນຳ​ໃຊ້​ການຫຼິ້ນ​ດ້ວຍຄຸນ​ນະ​ພາບ​ສູງ"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"​ເປີດ​ນຳ​ໃຊ້​​ຄຳ​ບັນ​ຍາຍ​ແບບ​ປິດ"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"​ປິດ​ນຳ​ໃຊ້​ຄຳ​ບັນ​ຍາຍ​ແບບ​ປິດ"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"ສໍາເລັດ"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"​ສືບ​ຕໍ່"</string>
</resources>
diff --git a/v17/leanback/res/values-lt/strings.xml b/v17/leanback/res/values-lt/strings.xml
index 6ca2bab0c2..415fc25be7 100644
--- a/v17/leanback/res/values-lt/strings.xml
+++ b/v17/leanback/res/values-lt/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Išjungti aukštą kokybę"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Įgalinti subtitrus"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Išjungti subtitrus"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Baigti"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Tęsti"</string>
</resources>
diff --git a/v17/leanback/res/values-lv/strings.xml b/v17/leanback/res/values-lv/strings.xml
index 7d3bc2be88..3979e43d1c 100644
--- a/v17/leanback/res/values-lv/strings.xml
+++ b/v17/leanback/res/values-lv/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Atspējot augstas kvalitātes vienumu atskaņošanu"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Iespējot slēgtos parakstus"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Atspējot slēgtos parakstus"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Pabeigt"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Turpināt"</string>
</resources>
diff --git a/v17/leanback/res/values-mk-rMK/strings.xml b/v17/leanback/res/values-mk-rMK/strings.xml
index 75666e0491..ccf6d62674 100644
--- a/v17/leanback/res/values-mk-rMK/strings.xml
+++ b/v17/leanback/res/values-mk-rMK/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Оневозможи висок квалитет"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Овозможи затворено објаснување"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Оневозможи затворено објаснување"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Заврши"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Продолжи"</string>
</resources>
diff --git a/v17/leanback/res/values-ml-rIN/strings.xml b/v17/leanback/res/values-ml-rIN/strings.xml
index b900f091d0..356b0e93c2 100644
--- a/v17/leanback/res/values-ml-rIN/strings.xml
+++ b/v17/leanback/res/values-ml-rIN/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ഉയർന്ന നിലവാരം പ്രവർത്തനരഹിതമാക്കുക"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"അടച്ച അടിക്കുറിപ്പ് നൽകൽ പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"അടച്ച അടിക്കുറിപ്പ് നൽകൽ പ്രവർത്തനരഹിതമാക്കുക"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"പൂര്‍ത്തിയാക്കുക"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"തുടരുക"</string>
</resources>
diff --git a/v17/leanback/res/values-mn-rMN/strings.xml b/v17/leanback/res/values-mn-rMN/strings.xml
index e4a8fcd8ac..a7a640fd8b 100644
--- a/v17/leanback/res/values-mn-rMN/strings.xml
+++ b/v17/leanback/res/values-mn-rMN/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Өндөр чанарыг идэвхгүйжүүлэх"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Текст тайлбарыг идэвхжүүлэх"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Текст тайлбарыг идэвхгүйжүүлэх"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Дуусгах"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Үргэлжлүүлэх"</string>
</resources>
diff --git a/v17/leanback/res/values-mr-rIN/strings.xml b/v17/leanback/res/values-mr-rIN/strings.xml
index 11748ecf5b..b9b568aacf 100644
--- a/v17/leanback/res/values-mr-rIN/strings.xml
+++ b/v17/leanback/res/values-mr-rIN/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"उच्च गुणवत्ता अक्षम करा"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"उपशीर्षके सक्षम करा"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"उपशीर्षके अक्षम करा"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"समाप्त"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"सुरू ठेवा"</string>
</resources>
diff --git a/v17/leanback/res/values-ms-rMY/strings.xml b/v17/leanback/res/values-ms-rMY/strings.xml
index c073e43509..0a5f8bd30e 100644
--- a/v17/leanback/res/values-ms-rMY/strings.xml
+++ b/v17/leanback/res/values-ms-rMY/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Lumpuhkan Kualiti Tinggi"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Dayakan Kapsyen Tertutup"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Lumpuhkan Kapsyen Tertutup"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Selesai"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Teruskan"</string>
</resources>
diff --git a/v17/leanback/res/values-my-rMM/strings.xml b/v17/leanback/res/values-my-rMM/strings.xml
index 2efaf7fc67..1b3cdeee48 100644
--- a/v17/leanback/res/values-my-rMM/strings.xml
+++ b/v17/leanback/res/values-my-rMM/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"အရည်အသွေးကောင်းအား ပိတ်ထားရန်"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"စာတမ်းထိုး ဖွင့်ရန်"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"စာတမ်းထိုးအား ပိတ်ထားရန်"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"ပြီးပြီ"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"ဆက်လုပ်ရန်"</string>
</resources>
diff --git a/v17/leanback/res/values-nb/strings.xml b/v17/leanback/res/values-nb/strings.xml
index f5ab2e16ad..c58544d756 100644
--- a/v17/leanback/res/values-nb/strings.xml
+++ b/v17/leanback/res/values-nb/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Deaktiver høy kvalitet"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktivér teksting"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Deaktiver teksting"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Fullfør"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Fortsett"</string>
</resources>
diff --git a/v17/leanback/res/values-ne-rNP/strings.xml b/v17/leanback/res/values-ne-rNP/strings.xml
index c399985fb2..54c9285697 100644
--- a/v17/leanback/res/values-ne-rNP/strings.xml
+++ b/v17/leanback/res/values-ne-rNP/strings.xml
@@ -48,4 +48,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"उच्च गुणस्तर असक्षम"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"बन्द क्याप्सनहरु सक्षम"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"बन्द क्याप्सनहरु असक्षम"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"समाप्त गर्नुहोस्"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"जारी राख्नुहोस्"</string>
</resources>
diff --git a/v17/leanback/res/values-nl/strings.xml b/v17/leanback/res/values-nl/strings.xml
index 1925e1483b..941aa79bd8 100644
--- a/v17/leanback/res/values-nl/strings.xml
+++ b/v17/leanback/res/values-nl/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Hoge kwaliteit uitschakelen"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ondertiteling inschakelen"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Ondertiteling uitschakelen"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Voltooien"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Doorgaan"</string>
</resources>
diff --git a/v17/leanback/res/values-pa-rIN/strings.xml b/v17/leanback/res/values-pa-rIN/strings.xml
index f9c7c4b259..f1976574ca 100644
--- a/v17/leanback/res/values-pa-rIN/strings.xml
+++ b/v17/leanback/res/values-pa-rIN/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ਉੱਚ ਗੁਣਵੱਤਾ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"ਬੰਦ ਕੈਪਸ਼ਨਿੰਗ ਸਮਰੱਥ ਬਣਾਓ"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"ਬੰਦ ਕੈਪਸ਼ਨਿੰਗ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"ਖ਼ਤਮ"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"ਜਾਰੀ ਰੱਖੋ"</string>
</resources>
diff --git a/v17/leanback/res/values-pl/strings.xml b/v17/leanback/res/values-pl/strings.xml
index 18b8bf67c8..7598c73c22 100644
--- a/v17/leanback/res/values-pl/strings.xml
+++ b/v17/leanback/res/values-pl/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Wyłącz wysoką jakość"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Włącz napisy"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Wyłącz napisy"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Zakończ"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Dalej"</string>
</resources>
diff --git a/v17/leanback/res/values-pt-rBR/strings.xml b/v17/leanback/res/values-pt-rBR/strings.xml
index 79b9d402ea..12c9533c68 100644
--- a/v17/leanback/res/values-pt-rBR/strings.xml
+++ b/v17/leanback/res/values-pt-rBR/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desativar alta qualidade"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ativar closed captioning"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desativar closed captioning"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Concluir"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continuar"</string>
</resources>
diff --git a/v17/leanback/res/values-pt-rPT/strings.xml b/v17/leanback/res/values-pt-rPT/strings.xml
index f269712c2f..7b12f5e6e1 100644
--- a/v17/leanback/res/values-pt-rPT/strings.xml
+++ b/v17/leanback/res/values-pt-rPT/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desativar alta qualidade"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ativar legendas"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desativar legendas"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Concluir"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continuar"</string>
</resources>
diff --git a/v17/leanback/res/values-pt/strings.xml b/v17/leanback/res/values-pt/strings.xml
index 79b9d402ea..12c9533c68 100644
--- a/v17/leanback/res/values-pt/strings.xml
+++ b/v17/leanback/res/values-pt/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desativar alta qualidade"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ativar closed captioning"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desativar closed captioning"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Concluir"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continuar"</string>
</resources>
diff --git a/v17/leanback/res/values-ro/strings.xml b/v17/leanback/res/values-ro/strings.xml
index cb6aa4aeb4..b4f9ee3e6d 100644
--- a/v17/leanback/res/values-ro/strings.xml
+++ b/v17/leanback/res/values-ro/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Dezactivează calitatea înaltă"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activează subtitrările"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Dezactivează subtitrările"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Finalizați"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Continuați"</string>
</resources>
diff --git a/v17/leanback/res/values-ru/strings.xml b/v17/leanback/res/values-ru/strings.xml
index fdb453b33c..864054aa14 100644
--- a/v17/leanback/res/values-ru/strings.xml
+++ b/v17/leanback/res/values-ru/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Отключить высокое качество."</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Включить субтитры."</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Отключить субтитры."</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Готово"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Далее"</string>
</resources>
diff --git a/v17/leanback/res/values-si-rLK/strings.xml b/v17/leanback/res/values-si-rLK/strings.xml
index e5c0cf481e..3db129389f 100644
--- a/v17/leanback/res/values-si-rLK/strings.xml
+++ b/v17/leanback/res/values-si-rLK/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"උපරිම ගුණත්වය අබල කරන ලදි"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"වැසුණු ශිර්ෂ කිරීම සබල කරන ලදි"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"වැසුණු ශිර්ෂ කිරීම අබල කරන ලදි"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"අවසානය"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"දිගටම කර ගෙන යන්න"</string>
</resources>
diff --git a/v17/leanback/res/values-sk/strings.xml b/v17/leanback/res/values-sk/strings.xml
index 74a9044e5e..a317d18479 100644
--- a/v17/leanback/res/values-sk/strings.xml
+++ b/v17/leanback/res/values-sk/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Zakázať médiá vo vysokej kvalite"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Zapnúť skryté titulky"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Vypnúť skryté titulky"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Dokončiť"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Pokračovať"</string>
</resources>
diff --git a/v17/leanback/res/values-sl/strings.xml b/v17/leanback/res/values-sl/strings.xml
index b5d0e1d54f..7b169521a5 100644
--- a/v17/leanback/res/values-sl/strings.xml
+++ b/v17/leanback/res/values-sl/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Onemogoči visoko kakovost"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Omogoči podnapise"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Onemogoči podnapise"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Dokončaj"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Naprej"</string>
</resources>
diff --git a/v17/leanback/res/values-sq-rAL/strings.xml b/v17/leanback/res/values-sq-rAL/strings.xml
index 28c313f6f1..723b90cfb9 100644
--- a/v17/leanback/res/values-sq-rAL/strings.xml
+++ b/v17/leanback/res/values-sq-rAL/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Çaktivizo \"Cilësinë e lartë\""</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktivizo titrat"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Çaktivizo titrat me sekuencë kohore"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Përfundo"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Vazhdo"</string>
</resources>
diff --git a/v17/leanback/res/values-sr/strings.xml b/v17/leanback/res/values-sr/strings.xml
index bb5c32d02a..df6c6b1530 100644
--- a/v17/leanback/res/values-sr/strings.xml
+++ b/v17/leanback/res/values-sr/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Онемогући висок квалитет"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Омогући титлове"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Онемогући титлове"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Доврши"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Настави"</string>
</resources>
diff --git a/v17/leanback/res/values-sv/strings.xml b/v17/leanback/res/values-sv/strings.xml
index 1a8e757137..9b874ca9f1 100644
--- a/v17/leanback/res/values-sv/strings.xml
+++ b/v17/leanback/res/values-sv/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Inaktivera hög kvalitet"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktivera textning"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Inaktivera textning"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Slutför"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Fortsätt"</string>
</resources>
diff --git a/v17/leanback/res/values-sw/strings.xml b/v17/leanback/res/values-sw/strings.xml
index 0ad04d1a25..53ef95ae5e 100644
--- a/v17/leanback/res/values-sw/strings.xml
+++ b/v17/leanback/res/values-sw/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Zima Ubora wa Juu"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Washa manukuu"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Zima manukuu"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Kamilisha"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Endelea"</string>
</resources>
diff --git a/v17/leanback/res/values-ta-rIN/strings.xml b/v17/leanback/res/values-ta-rIN/strings.xml
index 9472522b06..1cc2eea9de 100644
--- a/v17/leanback/res/values-ta-rIN/strings.xml
+++ b/v17/leanback/res/values-ta-rIN/strings.xml
@@ -20,7 +20,7 @@ limitations under the License.
<string name="orb_search_action" msgid="5651268540267663887">"செயலைத் தேடுக"</string>
<string name="lb_search_bar_hint" msgid="8325490927970116252">"தேடு"</string>
<string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"தேட, பேசவும்"</string>
- <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ஐத் தேடுக"</string>
+ <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> இல் தேடுக"</string>
<string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ஐத் தேட, பேசவும்"</string>
<string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
<string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"உயர் தரத்தை முடக்கு"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"விரிவான வசனங்களை இயக்கு"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"விரிவான வசனங்களை முடக்கு"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"முடி"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"தொடர்க"</string>
</resources>
diff --git a/v17/leanback/res/values-te-rIN/strings.xml b/v17/leanback/res/values-te-rIN/strings.xml
index f71e8cb771..32d311d7fd 100644
--- a/v17/leanback/res/values-te-rIN/strings.xml
+++ b/v17/leanback/res/values-te-rIN/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"అధిక నాణ్యతను నిలిపివేయి"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"సంవృత శీర్షికలను ప్రారంభించు"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"సంవృత శీర్షికలను నిలిపివేయి"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"ముగించు"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"కొనసాగించు"</string>
</resources>
diff --git a/v17/leanback/res/values-th/strings.xml b/v17/leanback/res/values-th/strings.xml
index 093a529280..d3eb2a3ba5 100644
--- a/v17/leanback/res/values-th/strings.xml
+++ b/v17/leanback/res/values-th/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ปิดใช้คุณภาพสูง"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"เปิดใช้คำบรรยาย"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"ปิดใช้คำบรรยาย"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"เสร็จสิ้น"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"ต่อไป"</string>
</resources>
diff --git a/v17/leanback/res/values-tl/strings.xml b/v17/leanback/res/values-tl/strings.xml
index a536298741..f50b4d15ec 100644
--- a/v17/leanback/res/values-tl/strings.xml
+++ b/v17/leanback/res/values-tl/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"I-disable ang Mataas na Kalidad"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"I-enable ang Paglalagay ng Subtitle"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"I-disable ang Paglalagay ng Subtitle"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Tapusin"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Magpatuloy"</string>
</resources>
diff --git a/v17/leanback/res/values-tr/strings.xml b/v17/leanback/res/values-tr/strings.xml
index 800436c4ad..814cb295ab 100644
--- a/v17/leanback/res/values-tr/strings.xml
+++ b/v17/leanback/res/values-tr/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Yüksek Kalitede Oynatmayı Devre Dışı Bırak"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Altyazıları Etkinleştir"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Altyazıları Devre Dışı Bırak"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Son"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Devam"</string>
</resources>
diff --git a/v17/leanback/res/values-uk/strings.xml b/v17/leanback/res/values-uk/strings.xml
index 79b2782089..a38db308b2 100644
--- a/v17/leanback/res/values-uk/strings.xml
+++ b/v17/leanback/res/values-uk/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Вимкнути високу якість"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Увімкнути субтитри"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Вимкнути субтитри"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Закінчити"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Продовжити"</string>
</resources>
diff --git a/v17/leanback/res/values-ur-rPK/strings.xml b/v17/leanback/res/values-ur-rPK/strings.xml
index b670251479..666cf7191a 100644
--- a/v17/leanback/res/values-ur-rPK/strings.xml
+++ b/v17/leanback/res/values-ur-rPK/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"اعلی معیار کو غیر فعال کریں"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"سب ٹائٹلز کو فعال کریں"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"سب ٹائٹلز کو غیر فعال کریں"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"مکمل کریں"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"جاری رکھیں"</string>
</resources>
diff --git a/v17/leanback/res/values-uz-rUZ/strings.xml b/v17/leanback/res/values-uz-rUZ/strings.xml
index c7612449a8..d81d8dea8b 100644
--- a/v17/leanback/res/values-uz-rUZ/strings.xml
+++ b/v17/leanback/res/values-uz-rUZ/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Yuqori sifatni o‘chirib qo‘yish"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Taglavhalarni yoqish"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Taglavhalarni o‘chirib qo‘yish"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Tugatish"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Davom etish"</string>
</resources>
diff --git a/v17/leanback/res/values-v19/themes.xml b/v17/leanback/res/values-v19/themes.xml
index 53befec16b..74e0e2e931 100644
--- a/v17/leanback/res/values-v19/themes.xml
+++ b/v17/leanback/res/values-v19/themes.xml
@@ -20,6 +20,7 @@
<item name="playbackProgressPrimaryColor">@color/lb_playback_progress_color_no_theme</item>
<item name="playbackControlsIconHighlightColor">@color/lb_playback_icon_highlight_no_theme</item>
<item name="defaultBrandColor">@color/lb_default_brand_color</item>
+ <item name="defaultBrandColorDark">@color/lb_default_brand_color_dark</item>
<item name="android:windowOverscan">true</item>
<item name="guidedStepTheme">@style/Theme.Leanback.GuidedStep</item>
diff --git a/v17/leanback/res/values-v21/themes.xml b/v17/leanback/res/values-v21/themes.xml
index 3b48dae00e..1072b2bce6 100644
--- a/v17/leanback/res/values-v21/themes.xml
+++ b/v17/leanback/res/values-v21/themes.xml
@@ -21,6 +21,8 @@
<item name="playbackControlsIconHighlightColor">?android:attr/colorAccent</item>
<item name="defaultBrandColor">?android:attr/colorPrimary</item>
<item name="android:colorPrimary">@color/lb_default_brand_color</item>
+ <item name="defaultBrandColorDark">?android:attr/colorPrimaryDark</item>
+ <item name="android:colorPrimaryDark">@color/lb_default_brand_color_dark</item>
<item name="android:windowOverscan">true</item>
<item name="guidedStepTheme">@style/Theme.Leanback.GuidedStep</item>
diff --git a/v17/leanback/res/values-v22/integers.xml b/v17/leanback/res/values-v22/integers.xml
new file mode 100644
index 0000000000..fdd7792e88
--- /dev/null
+++ b/v17/leanback/res/values-v22/integers.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+<resources>
+
+ <!-- Gravity.START -->
+ <integer name="slideEdgeStart">0x800003</integer>
+ <!-- Gravity.END -->
+ <integer name="slideEdgeEnd">0x800005</integer>
+
+</resources> \ No newline at end of file
diff --git a/v17/leanback/res/values-vi/strings.xml b/v17/leanback/res/values-vi/strings.xml
index baf1c44dc8..881734b9d5 100644
--- a/v17/leanback/res/values-vi/strings.xml
+++ b/v17/leanback/res/values-vi/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Tắt chế độ chất lượng cao"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Bật phụ đề"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Tắt phụ đề"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Hoàn tất"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Tiếp tục"</string>
</resources>
diff --git a/v17/leanback/res/values-zh-rCN/strings.xml b/v17/leanback/res/values-zh-rCN/strings.xml
index 17c52b6a67..fc3fa103ca 100644
--- a/v17/leanback/res/values-zh-rCN/strings.xml
+++ b/v17/leanback/res/values-zh-rCN/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"关闭高画质模式"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"开启字幕"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"关闭字幕"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"完成"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"继续"</string>
</resources>
diff --git a/v17/leanback/res/values-zh-rHK/strings.xml b/v17/leanback/res/values-zh-rHK/strings.xml
index 5e87989b17..7cba4b58c3 100644
--- a/v17/leanback/res/values-zh-rHK/strings.xml
+++ b/v17/leanback/res/values-zh-rHK/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"停用高畫質"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"啟用字幕"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"停用字幕"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"完成"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"繼續"</string>
</resources>
diff --git a/v17/leanback/res/values-zh-rTW/strings.xml b/v17/leanback/res/values-zh-rTW/strings.xml
index 67efc4026d..dcca2db98f 100644
--- a/v17/leanback/res/values-zh-rTW/strings.xml
+++ b/v17/leanback/res/values-zh-rTW/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"停用高品質播放"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"啟用字幕"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"停用字幕"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"完成"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"繼續"</string>
</resources>
diff --git a/v17/leanback/res/values-zu/strings.xml b/v17/leanback/res/values-zu/strings.xml
index f17455de39..f4c589d2b1 100644
--- a/v17/leanback/res/values-zu/strings.xml
+++ b/v17/leanback/res/values-zu/strings.xml
@@ -46,4 +46,6 @@ limitations under the License.
<string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Khubaza ikhwalithi ephezulu"</string>
<string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Nika amandla imibhalo engezansi"</string>
<string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Khubaza imihbalo engezansi"</string>
+ <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Qeda"</string>
+ <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Qhubeka"</string>
</resources>
diff --git a/v17/leanback/res/values/attrs.xml b/v17/leanback/res/values/attrs.xml
index e7da321249..90f010ae87 100644
--- a/v17/leanback/res/values/attrs.xml
+++ b/v17/leanback/res/values/attrs.xml
@@ -49,6 +49,10 @@
</declare-styleable>
<declare-styleable name="lbBaseCardView">
+ <!-- Defines the background of card -->
+ <attr name="cardForeground" format="reference|color"/>
+ <!-- Defines the background of card -->
+ <attr name="cardBackground" format="reference|color"/>
<!-- Defines the type of the card layout -->
<attr name="cardType" format="enum">
<!-- A simple card layout with a single layout region. -->
@@ -116,7 +120,23 @@
</declare-styleable>
<declare-styleable name="lbImageCardView">
+ <!-- Deprecated. Use 'lbImageCardViewInfoAreaStyle' instead. -->
<attr name="infoAreaBackground" format="reference|color"/>
+ <!-- Use these attributes to override a ImageCardView's component style. -->
+ <attr name="lbImageCardViewImageStyle" format="reference" />
+ <attr name="lbImageCardViewTitleStyle" format="reference" />
+ <attr name="lbImageCardViewContentStyle" format="reference" />
+ <attr name="lbImageCardViewBadgeStyle" format="reference" />
+ <attr name="lbImageCardViewInfoAreaStyle" format="reference" />
+ <!-- Defines what components the ImageCardView will use. -->
+ <attr name="lbImageCardViewType">
+ <flag name="Title" value="1" />
+ <flag name="Content" value="2" />
+ <flag name="IconOnRight" value="4" />
+ <flag name="IconOnLeft" value="8" />
+ <!-- Only display the main image. -->
+ <flag name="ImageOnly" value="0" />
+ </attr>
</declare-styleable>
<declare-styleable name="lbSearchOrbView">
@@ -258,6 +278,12 @@
b) SDK < 21: set the brand color explicitly via defaultBrandColor, or programatically.
-->
<attr name="defaultBrandColor" format="reference|color" />
+ <!-- Default dark brand color used for the background of certain leanback visual elements
+ such as the actions background. If your app runs on:
+ a) SDK 21+: set colorPrimaryDark, used by the leanback launcher and elsewhere, and defaultBrandColorDark will inherit it.
+ b) SDK < 21: set the brand color explicitly via defaultBrandColorDark, or programatically.
+ -->
+ <attr name="defaultBrandColorDark" format="reference|color" />
<!-- Default colors -->
<attr name="defaultSearchColor" format="reference|color" />
@@ -292,27 +318,18 @@
Theme attribute used to inspect theme inheritance. -->
<attr name="guidedStepThemeFlag" format="boolean" />
- <!-- Theme attribute for the animation used when a guided step element is animated in on
- fragment stack push. Default is {@link
- android.support.v17.leanback.R.animator#lb_guidedstep_slide_in_from_end}. -->
- <attr name="guidedStepEntryAnimation" format="reference" />
- <!-- Theme attribute for the animation used when a guided step element is animated out on
- fragment stack push. Default is {@link
- android.support.v17.leanback.R.animator#lb_guidedstep_slide_out_to_start}. -->
- <attr name="guidedStepExitAnimation" format="reference" />
- <!-- Theme attribute for the animation used when a guided step element is animated in on
- fragment stack pop. Default is {@link
- android.support.v17.leanback.R.animator#lb_guidedstep_slide_in_from_start}. -->
- <attr name="guidedStepReentryAnimation" format="reference" />
- <!-- Theme attribute for the animation used when a guided step element is animated out on
- fragment stack pop. Default is {@link
- android.support.v17.leanback.R.animator#lb_guidedstep_slide_out_to_end}. -->
- <attr name="guidedStepReturnAnimation" format="reference" />
-
- <!-- Theme attribute for the animation used when the guidance is animated in at activity
- start. Default is {@link android.support.v17.leanback.R.animator#lb_guidance_entry}.
- -->
- <attr name="guidanceEntryAnimation" format="reference" />
+ <!-- Theme attribute of background drawable used by GuidedStepFragment. -->
+ <attr name="guidedStepBackground" format="reference|color" />
+
+ <!-- Theme attribute for the animation used when a guided step element is animated in
+ response to the IME appearing. Default is {@link
+ android.support.v17.leanback.R.animator#lb_guidedstep_slide_up}. -->
+ <attr name="guidedStepImeAppearingAnimation" format="reference" />
+ <!-- Theme attribute for the animation used when a guided step element is animated in
+ response to the IME disappearing. Default is {@link
+ android.support.v17.leanback.R.animator#lb_guidedstep_slide_down}. -->
+ <attr name="guidedStepImeDisappearingAnimation" format="reference" />
+
<!-- Theme attribute for the style of the main container in a GuidanceStylist. Default is
{@link android.support.v17.leanback.R.style#Widget_Leanback_GuidanceContainerStyle}.-->
<attr name="guidanceContainerStyle" format="reference" />
@@ -329,10 +346,6 @@
{@link android.support.v17.leanback.R.style#Widget_Leanback_GuidanceIconStyle}. -->
<attr name="guidanceIconStyle" format="reference" />
- <!-- Theme attribute for the animation used in a GuidedActionsPresenter when the actions
- list is animated in at activity start. Default is {@link
- android.support.v17.leanback.R.animator#lb_guidedactions_entry}. -->
- <attr name="guidedActionsEntryAnimation" format="reference" />
<!-- Theme attribute for the animation used in a GuidedActionsPresenter when the action
selector is animated in at activity start. Default is {@link
android.support.v17.leanback.R.animator#lb_guidedactions_selector_show}. -->
@@ -341,12 +354,22 @@
selector is animated in at activity start. Default is {@link
android.support.v17.leanback.R.animator#lb_guidedactions_selector_hide}. -->
<attr name="guidedActionsSelectorHideAnimation" format="reference" />
- <!-- Theme attribute for the style of the container in a GuidedActionsPresenter. Default is
- {@link android.support.v17.leanback.R.style#Widget_Leanback_GuidedActionsContainerStyle}. -->
- <attr name="guidedActionsContainerStyle" format="reference" />
<!-- Theme attribute for the style of the item selector in a GuidedActionsPresenter. Default is
{@link android.support.v17.leanback.R.style#Widget_Leanback_GuidedActionsSelectorStyle}. -->
<attr name="guidedActionsSelectorStyle" format="reference" />
+
+ <!-- Theme attribute for the shadow elevation of GuidedActions. Default is
+ {@link android.support.v17.leanback.R.dimen#lb_guidedactions_elevation}.-->
+ <attr name="guidedActionsElevation" format="dimension|reference" />
+
+ <!-- Theme attribute for the background of GuidedActions. Default is
+ {@link android.support.v17.leanback.R.color#lb_guidedactions_background}.-->
+ <attr name="guidedActionsBackground" format="reference" />
+
+ <!-- Theme attribute for the dark version background of GuidedActions. Default is
+ {@link android.support.v17.leanback.R.color#lb_guidedactions_background_dark}.-->
+ <attr name="guidedActionsBackgroundDark" format="reference" />
+
<!-- Theme attribute for the style of the list in a GuidedActionsPresenter. Default is
{@link android.support.v17.leanback.R.style#Widget_Leanback_GuidedActionsListStyle}.-->
<attr name="guidedActionsListStyle" format="reference" />
@@ -381,14 +404,6 @@
<attr name="guidedActionItemChevronStyle" format="reference" />
<!-- Theme attribute for the animation used in a GuidedActionsPresenter when an action
- is checked. Default is {@link
- android.support.v17.leanback.R.animator#lb_guidedactions_item_checked}. -->
- <attr name="guidedActionCheckedAnimation" format="reference" />
- <!-- Theme attribute for the animation used in a GuidedActionsPresenter when an action
- is unchecked. Default is {@link
- android.support.v17.leanback.R.animator#lb_guidedactions_item_unchecked}. -->
- <attr name="guidedActionUncheckedAnimation" format="reference" />
- <!-- Theme attribute for the animation used in a GuidedActionsPresenter when an action
is pressed. Default is {@link
android.support.v17.leanback.R.animator#lb_guidedactions_item_pressed}. -->
<attr name="guidedActionPressedAnimation" format="reference" />
@@ -404,14 +419,12 @@
decoration when its action is disabled. Default is {@link
android.support.v17.leanback.R.string#lb_guidedactions_item_disabled_chevron_alpha}. -->
<attr name="guidedActionDisabledChevronAlpha" format="reference" />
- <!-- Theme attribute used in a GuidedActionsPresenter for the width of the text area of
- a single action when there is an icon present. Default is {@link
- android.support.v17.leanback.R.dimen#lb_guidedactions_item_text_width}. -->
- <attr name="guidedActionContentWidth" format="reference" />
- <!-- Theme attribute used in a GuidedActionsPresenter for the width of the text area of
- a single action when there is no icon present. Default is {@link
- android.support.v17.leanback.R.dimen#lb_guidedactions_item_text_width_no_icon}. -->
- <attr name="guidedActionContentWidthNoIcon" format="reference" />
+ <!-- Theme attribute used for the weight of actions. Default is {@link
+ android.support.v17.leanback.R.string#lb_guidedactions_width_weight}. -->
+ <attr name="guidedActionContentWidthWeight" format="reference" />
+ <!-- Theme attribute used for the weight of actions when there are two panels. Default is {@link
+ android.support.v17.leanback.R.string#lb_guidedactions_width_weight_two_panels}. -->
+ <attr name="guidedActionContentWidthWeightTwoPanels" format="reference" />
<!-- Theme attribute used in a GuidedActionsPresenter for the max lines of the title text
view when the action's isMultilineDescription is set to false. Default is {@link
android.support.v17.leanback.R.integer#lb_guidedactions_item_title_min_lines}. -->
@@ -431,4 +444,4 @@
</declare-styleable>
-</resources>
+</resources> \ No newline at end of file
diff --git a/v17/leanback/res/values/colors.xml b/v17/leanback/res/values/colors.xml
index e63c58b0f4..858ace53c3 100644
--- a/v17/leanback/res/values/colors.xml
+++ b/v17/leanback/res/values/colors.xml
@@ -52,6 +52,7 @@
<color name="lb_basic_card_content_text_color">#B3EEEEEE</color>
<color name="lb_default_brand_color">#FF455A64</color>
+ <color name="lb_default_brand_color_dark">#FF222D32</color>
<color name="lb_default_search_color">#FFFFAA3F</color>
<color name="lb_control_button_color">#66EEEEEE</color>
@@ -71,6 +72,7 @@
<!-- refactor naming here -->
<color name="lb_guidedactions_background">#FF111111</color>
+ <color name="lb_guidedactions_background_dark">#FF080808</color>
<color name="lb_guidedactions_selector_color">#26FFFFFF</color>
<color name="lb_guidedactions_item_unselected_text_color">#FFF1F1F1</color>
<!-- end refactor naming -->
diff --git a/v17/leanback/res/values/dimens.xml b/v17/leanback/res/values/dimens.xml
index 275612e453..053c7e0229 100644
--- a/v17/leanback/res/values/dimens.xml
+++ b/v17/leanback/res/values/dimens.xml
@@ -180,7 +180,7 @@
<!-- Search Fragment -->
- <dimen name="lb_search_browse_rows_align_top">120dp</dimen>
+ <dimen name="lb_search_browse_rows_align_top">147dp</dimen>
<dimen name="lb_search_browse_row_padding_start">56dp</dimen>
<dimen name="lb_search_orb_size">52dp</dimen>
@@ -203,6 +203,7 @@
<dimen name="lb_basic_card_info_height">52dp</dimen>
<dimen name="lb_basic_card_info_height_no_content">34dp</dimen>
<dimen name="lb_basic_card_info_padding_top">7dp</dimen>
+ <dimen name="lb_basic_card_info_padding_bottom">8dp</dimen>
<dimen name="lb_basic_card_info_padding_horizontal">11dp</dimen>
<dimen name="lb_basic_card_info_text_margin">1dp</dimen>
<dimen name="lb_basic_card_title_text_size">14sp</dimen>
@@ -223,19 +224,22 @@
<dimen name="lb_rounded_rect_corner_radius">2dp</dimen>
<!-- GuidedStepFragment -->
- <dimen name="lb_guidedstep_guidance_section_width">576dp</dimen>
<dimen name="lb_guidedstep_slide_start_distance">-200dp</dimen>
<dimen name="lb_guidedstep_slide_end_distance">200dp</dimen>
+ <dimen name="lb_guidedstep_slide_ime_distance">-100dp</dimen>
<dimen name="lb_guidance_entry_translationX">-120dp</dimen>
<dimen name="lb_guidedactions_entry_translationX">384dp</dimen>
- <dimen name="lb_guidedactions_section_width">384dp</dimen>
- <dimen name="lb_guidedactions_section_width_with_shadow">400dp</dimen>
+ <item name="lb_guidedactions_width_weight" format="float" type="string">0.666666667</item>
+ <item name="lb_guidedactions_width_weight_two_panels" format="float" type="string">1</item>
+ <dimen name="lb_guidedactions_section_shadow_width">16dp</dimen>
<dimen name="lb_guidedactions_elevation">12dp</dimen>
<dimen name="lb_guidedactions_selector_min_height">8dp</dimen>
<dimen name="lb_guidedactions_vertical_padding">12dp</dimen>
+ <item name="lb_guidedactions_item_disabled_text_alpha" format="float" type="string">0.25</item>
+ <item name="lb_guidedactions_item_disabled_description_text_alpha" format="float" type="string">0.25</item>
<item name="lb_guidedactions_item_unselected_text_alpha" format="float" type="string">1.00</item>
<item name="lb_guidedactions_item_unselected_description_text_alpha" format="float" type="string">0.50</item>
<item name="lb_guidedactions_item_enabled_chevron_alpha" format="float" type="string">1.00</item>
@@ -244,10 +248,10 @@
<dimen name="lb_guidedactions_item_text_width">248dp</dimen>
<dimen name="lb_guidedactions_item_text_width_no_icon">284dp</dimen>
<dimen name="lb_guidedactions_item_min_height">64dp</dimen>
- <dimen name="lb_guidedactions_item_start_padding">20dp</dimen>
+ <dimen name="lb_guidedactions_item_start_padding">28dp</dimen>
<dimen name="lb_guidedactions_item_end_padding">28dp</dimen>
<dimen name="lb_guidedactions_item_delimiter_padding">4dp</dimen>
- <dimen name="lb_guidedactions_item_checkmark_diameter">8dp</dimen>
+ <dimen name="lb_guidedactions_item_checkmark_diameter">16dp</dimen>
<dimen name="lb_guidedactions_item_icon_width">32dp</dimen>
<dimen name="lb_guidedactions_item_icon_height">32dp</dimen>
<dimen name="lb_guidedactions_item_title_font_size">18sp</dimen>
diff --git a/v17/leanback/res/values/ids.xml b/v17/leanback/res/values/ids.xml
index 6b679198e2..ca84efc8a8 100644
--- a/v17/leanback/res/values/ids.xml
+++ b/v17/leanback/res/values/ids.xml
@@ -16,7 +16,11 @@
-->
<resources>
<item type="id" name="lb_focus_animator" />
+ <item type="id" name="lb_shadow_impl" />
<item type="id" name="lb_slide_transition_value" />
+ <item type="id" name="transitionPosition" />
+
+ <item type="id" name="lb_guidedstep_background" />
<item type="id" name="lb_control_play_pause" />
<item type="id" name="lb_control_fast_forward" />
@@ -31,4 +35,10 @@
<item type="id" name="lb_control_high_quality" />
<item type="id" name="lb_control_closed_captioning" />
- </resources>
+ <item type="id" name="guidedactions_root2" />
+ <item type="id" name="guidedactions_list_background2" />
+ <item type="id" name="guidedactions_list2" />
+ <item type="id" name="guidedactions_selector2" />
+ <item type="id" name="guidedactions_content2" />
+
+</resources>
diff --git a/v17/leanback/res/values/integers.xml b/v17/leanback/res/values/integers.xml
index 8547e22f0d..c9f33842de 100644
--- a/v17/leanback/res/values/integers.xml
+++ b/v17/leanback/res/values/integers.xml
@@ -29,4 +29,11 @@
<integer name="lb_playback_rows_fade_out_ms">250</integer>
<integer name="lb_playback_rows_fade_delay_ms">100</integer>
<integer name="lb_playback_controls_show_time_ms">3000</integer>
+
+ <!-- Gravity.LEFT -->
+ <integer name="slideEdgeStart">3</integer>
+ <!-- Gravity.RIGHT -->
+ <integer name="slideEdgeEnd">5</integer>
+
+ <integer name="lb_guidedstep_activity_background_fade_duration_ms">350</integer>
</resources>
diff --git a/v17/leanback/res/values/strings.xml b/v17/leanback/res/values/strings.xml
index 2cd0ff119e..3d93db2abe 100644
--- a/v17/leanback/res/values/strings.xml
+++ b/v17/leanback/res/values/strings.xml
@@ -75,4 +75,8 @@ limitations under the License.
<!-- Talkback label for the control button to disable closed captioning -->
<string name="lb_playback_controls_closed_captioning_disable">Disable Closed Captioning</string>
+ <!-- Title of standard Finish action for GuidedStepFragment -->
+ <string name="lb_guidedaction_finish_title">Finish</string>
+ <!-- Title of standard Continue action for GuidedStepFragment -->
+ <string name="lb_guidedaction_continue_title">Continue</string>
</resources>
diff --git a/v17/leanback/res/values/styles.xml b/v17/leanback/res/values/styles.xml
index 3ee2821aaf..390446780d 100644
--- a/v17/leanback/res/values/styles.xml
+++ b/v17/leanback/res/values/styles.xml
@@ -87,14 +87,8 @@
<style name="Widget.Leanback" parent="Widget.LeanbackBase" />
<style name="Widget.Leanback.BaseCardViewStyle">
- <item name="android:foreground">@drawable/lb_card_foreground</item>
- </style>
-
- <style name="Widget.Leanback.ImageCardViewStyle" parent="Widget.Leanback.BaseCardViewStyle">
- <item name="cardType">infoUnder</item>
- <item name="infoVisibility">activated</item>
- <item name="android:background">@color/lb_basic_card_bg_color</item>
- <item name="infoAreaBackground">@color/lb_basic_card_info_bg_color</item>
+ <item name="cardForeground">@drawable/lb_card_foreground</item>
+ <item name="cardBackground">@color/lb_basic_card_bg_color</item>
</style>
<style name="Widget.Leanback.TitleView" >
@@ -104,6 +98,77 @@
<item name="android:paddingEnd">?attr/browsePaddingEnd</item>
</style>
+ <style name="Widget.Leanback.ImageCardViewStyle" parent="Widget.Leanback.BaseCardViewStyle">
+ <item name="cardType">infoUnder</item>
+ <item name="infoVisibility">activated</item>
+ <!-- In order to keep backward compatibility we have to create an icon on right. -->
+ <item name="lbImageCardViewType">Title|Content|IconOnRight</item>
+ <item name="lbImageCardViewImageStyle">@style/Widget.Leanback.ImageCardView.ImageStyle</item>
+ <item name="lbImageCardViewTitleStyle">@style/Widget.Leanback.ImageCardView.TitleStyle</item>
+ <item name="lbImageCardViewContentStyle">@style/Widget.Leanback.ImageCardView.ContentStyle</item>
+ <item name="lbImageCardViewBadgeStyle">@style/Widget.Leanback.ImageCardView.BadgeStyle</item>
+ <item name="lbImageCardViewInfoAreaStyle">@style/Widget.Leanback.ImageCardView.InfoAreaStyle</item>
+ <!-- Deprecated. Use 'Widget.Leanback.ImageCardView.InfoAreaStyle' instead. -->
+ <item name="infoAreaBackground">@null</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView" />
+
+ <style name="Widget.Leanback.ImageCardView.ImageStyle">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:adjustViewBounds">true</item>
+ <item name="android:contentDescription">@null</item>
+ <item name="android:scaleType">centerCrop</item>
+ <item name="layout_viewType">main</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView.InfoAreaStyle">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_centerHorizontal">true</item>
+ <item name="layout_viewType">info</item>
+ <item name="android:paddingBottom">@dimen/lb_basic_card_info_padding_bottom</item>
+ <item name="android:paddingEnd">@dimen/lb_basic_card_info_padding_horizontal</item>
+ <item name="android:paddingStart">@dimen/lb_basic_card_info_padding_horizontal</item>
+ <item name="android:paddingTop">@dimen/lb_basic_card_info_padding_top</item>
+ <item name="android:background">@color/lb_basic_card_info_bg_color</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView.TitleStyle">
+ <item name="android:id">@id/title_text</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:maxLines">1</item>
+ <item name="android:layout_marginBottom">@dimen/lb_basic_card_info_text_margin</item>
+ <item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:textColor">@color/lb_basic_card_title_text_color</item>
+ <item name="android:textSize">@dimen/lb_basic_card_title_text_size</item>
+ <item name="android:ellipsize">end</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView.ContentStyle">
+ <item name="android:id">@id/content_text</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_alignParentStart">true</item>
+ <item name="android:layout_below">@+id/title_text</item>
+ <item name="android:layout_toStartOf">@+id/extra_badge</item>
+ <item name="android:maxLines">1</item>
+ <item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:textColor">@color/lb_basic_card_content_text_color</item>
+ <item name="android:textSize">@dimen/lb_basic_card_content_text_size</item>
+ <item name="android:ellipsize">none</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView.BadgeStyle">
+ <item name="android:id">@id/extra_badge</item>
+ <item name="android:layout_width">@dimen/lb_basic_card_info_badge_size</item>
+ <item name="android:layout_height">@dimen/lb_basic_card_info_badge_size</item>
+ <item name="android:contentDescription">@null</item>
+ <item name="android:scaleType">fitCenter</item>
+ </style>
+
<style name="Widget.Leanback.Title" />
<style name="Widget.Leanback.Title.Text">
@@ -130,6 +195,7 @@
<style name="Widget.Leanback.GridItems" />
<style name="Widget.Leanback.Headers.VerticalGridView" >
+ <item name="android:background">?attr/defaultBrandColor</item>
<item name="android:paddingStart">?attr/browsePaddingStart</item>
<item name="focusOutFront">true</item>
<item name="focusOutEnd">true</item>
@@ -357,21 +423,11 @@
<item name="android:scaleType">fitCenter</item>
</style>
- <!-- Style for the container view in a GuidedActionsStylist's default layout. -->
- <style name="Widget.Leanback.GuidedActionsContainerStyle">
- <item name="android:layout_width">@dimen/lb_guidedactions_section_width</item>
- <item name="android:layout_height">match_parent</item>
- <item name="android:layout_alignParentEnd">true</item>
- <item name="android:background">@color/lb_guidedactions_background</item>
- <item name="android:elevation">@dimen/lb_guidedactions_elevation</item>
- </style>
-
<!-- Style for the selector view in a GuidedActionsStylist's default layout. -->
<style name="Widget.Leanback.GuidedActionsSelectorStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/lb_guidedactions_selector_min_height</item>
<item name="android:layout_centerVertical">true</item>
- <item name="android:alpha">0</item>
<item name="android:background">@color/lb_guidedactions_selector_color</item>
</style>
@@ -401,9 +457,8 @@
<item name="android:layout_height">@dimen/lb_guidedactions_item_checkmark_diameter</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_marginEnd">@dimen/lb_guidedactions_item_delimiter_padding</item>
- <item name="android:scaleType">center</item>
- <item name="android:src">@drawable/lb_guidedactions_item_checkmark</item>
- <item name="android:visibility">invisible</item>
+ <item name="android:scaleType">centerInside</item>
+ <item name="android:visibility">gone</item>
</style>
<!-- Style for an action's icon in a GuidedActionsStylist's default item layout. -->
@@ -418,7 +473,7 @@
<!-- Style for an action's text content in a GuidedActionsStylist's default item layout. -->
<style name="Widget.Leanback.GuidedActionItemContentStyle">
- <item name="android:layout_width">0dp</item>
+ <item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">start|center_vertical</item>
<item name="android:layout_weight">1</item>
@@ -430,11 +485,12 @@
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:alpha">@string/lb_guidedactions_item_unselected_text_alpha</item>
- <item name="android:ellipsize">marquee</item>
+ <item name="android:ellipsize">end</item>
<item name="android:fontFamily">sans-serif-condensed</item>
<item name="android:maxLines">@integer/lb_guidedactions_item_title_min_lines</item>
<item name="android:textColor">@color/lb_guidedactions_item_unselected_text_color</item>
<item name="android:textSize">@dimen/lb_guidedactions_item_title_font_size</item>
+ <item name="android:background">@null</item>
</style>
<!-- Style for an action's description in a GuidedActionsStylist's default item layout. -->
@@ -442,12 +498,13 @@
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:alpha">@string/lb_guidedactions_item_unselected_description_text_alpha</item>
- <item name="android:ellipsize">marquee</item>
+ <item name="android:ellipsize">end</item>
<item name="android:fontFamily">sans-serif-condensed</item>
<item name="android:maxLines">@integer/lb_guidedactions_item_description_min_lines</item>
<item name="android:textColor">@color/lb_guidedactions_item_unselected_text_color</item>
<item name="android:textSize">@dimen/lb_guidedactions_item_description_font_size</item>
<item name="android:visibility">gone</item>
+ <item name="android:background">@null</item>
</style>
<!-- Style for an action's chevron in a GuidedActionsStylist's default item layout. -->
diff --git a/v17/leanback/res/values/themes.xml b/v17/leanback/res/values/themes.xml
index 8178c50f8c..36362ddddc 100644
--- a/v17/leanback/res/values/themes.xml
+++ b/v17/leanback/res/values/themes.xml
@@ -15,13 +15,14 @@
limitations under the License.
-->
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- LeanbackBase may be overridden for specific api levels -->
<style name="Theme.LeanbackBase" parent="android:Theme.Holo.NoActionBar">
<item name="playbackProgressPrimaryColor">@color/lb_playback_progress_color_no_theme</item>
<item name="playbackControlsIconHighlightColor">@color/lb_playback_icon_highlight_no_theme</item>
<item name="defaultBrandColor">@color/lb_default_brand_color</item>
+ <item name="defaultBrandColorDark">@color/lb_default_brand_color_dark</item>
<item name="android:windowOverscan">true</item>
<item name="guidedStepTheme">@style/Theme.Leanback.GuidedStep</item>
@@ -95,6 +96,11 @@
<item name="android:windowReturnTransition">@transition/lb_browse_return_transition</item>
</style>
+ <style name="Theme.Leanback.VerticalGrid" parent="Theme.Leanback">
+ <item name="android:windowEnterTransition">@transition/lb_vertical_grid_enter_transition</item>
+ <item name="android:windowReturnTransition">@transition/lb_vertical_grid_return_transition</item>
+ </style>
+
<style name="Theme.Leanback.Details" parent="Theme.Leanback">
<item name="android:windowEnterTransition">@transition/lb_details_enter_transition</item>
<item name="android:windowReturnTransition">@transition/lb_details_return_transition</item>
@@ -111,12 +117,18 @@
<style name="Theme.Leanback.GuidedStep" parent="Theme.LeanbackBase">
<item name="guidedStepThemeFlag">true</item>
- <item name="guidedStepEntryAnimation">@animator/lb_guidedstep_slide_in_from_end</item>
- <item name="guidedStepExitAnimation">@animator/lb_guidedstep_slide_out_to_start</item>
- <item name="guidedStepReentryAnimation">@animator/lb_guidedstep_slide_in_from_start</item>
- <item name="guidedStepReturnAnimation">@animator/lb_guidedstep_slide_out_to_end</item>
- <item name="guidanceEntryAnimation">@animator/lb_guidance_entry</item>
- <item name="guidedActionsEntryAnimation">@animator/lb_guidedactions_entry</item>
+ <item name="android:windowEnterTransition">@transition/lb_guidedstep_activity_enter</item>
+
+ <!-- background applied to each GuidedStepFragment by default-->
+ <item name="guidedStepBackground">?android:attr/colorBackground</item>
+ <!-- Each GuidedStepFragment has a background so activity does not need a background.
+ But We still need a dumb background to keep the temporary translucent state last
+ as long as the background view fade-in transition -->
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowTransitionBackgroundFadeDuration">@integer/lb_guidedstep_activity_background_fade_duration_ms</item>
+
+ <item name="guidedStepImeAppearingAnimation">@animator/lb_guidedstep_slide_up</item>
+ <item name="guidedStepImeDisappearingAnimation">@animator/lb_guidedstep_slide_down</item>
<item name="guidanceContainerStyle">@style/Widget.Leanback.GuidanceContainerStyle</item>
<item name="guidanceIconStyle">@style/Widget.Leanback.GuidanceIconStyle</item>
@@ -124,7 +136,9 @@
<item name="guidanceBreadcrumbStyle">@style/Widget.Leanback.GuidanceBreadcrumbStyle</item>
<item name="guidanceDescriptionStyle">@style/Widget.Leanback.GuidanceDescriptionStyle</item>
- <item name="guidedActionsContainerStyle">@style/Widget.Leanback.GuidedActionsContainerStyle</item>
+ <item name="guidedActionsElevation">@dimen/lb_guidedactions_elevation</item>
+ <item name="guidedActionsBackground">@color/lb_guidedactions_background</item>
+ <item name="guidedActionsBackgroundDark">@color/lb_guidedactions_background_dark</item>
<item name="guidedActionsSelectorStyle">@style/Widget.Leanback.GuidedActionsSelectorStyle</item>
<item name="guidedActionsListStyle">@style/Widget.Leanback.GuidedActionsListStyle</item>
<item name="guidedActionsSelectorShowAnimation">@animator/lb_guidedactions_selector_show</item>
@@ -138,14 +152,12 @@
<item name="guidedActionItemDescriptionStyle">@style/Widget.Leanback.GuidedActionItemDescriptionStyle</item>
<item name="guidedActionItemChevronStyle">@style/Widget.Leanback.GuidedActionItemChevronStyle</item>
- <item name="guidedActionCheckedAnimation">@animator/lb_guidedactions_item_checked</item>
- <item name="guidedActionUncheckedAnimation">@animator/lb_guidedactions_item_unchecked</item>
<item name="guidedActionPressedAnimation">@animator/lb_guidedactions_item_pressed</item>
<item name="guidedActionUnpressedAnimation">@animator/lb_guidedactions_item_unpressed</item>
<item name="guidedActionEnabledChevronAlpha">@string/lb_guidedactions_item_enabled_chevron_alpha</item>
<item name="guidedActionDisabledChevronAlpha">@string/lb_guidedactions_item_disabled_chevron_alpha</item>
- <item name="guidedActionContentWidth">@dimen/lb_guidedactions_item_text_width</item>
- <item name="guidedActionContentWidthNoIcon">@dimen/lb_guidedactions_item_text_width_no_icon</item>
+ <item name="guidedActionContentWidthWeight">@string/lb_guidedactions_width_weight</item>
+ <item name="guidedActionContentWidthWeightTwoPanels">@string/lb_guidedactions_width_weight_two_panels</item>
<item name="guidedActionTitleMinLines">@integer/lb_guidedactions_item_title_min_lines</item>
<item name="guidedActionTitleMaxLines">@integer/lb_guidedactions_item_title_max_lines</item>
<item name="guidedActionDescriptionMinLines">@integer/lb_guidedactions_item_description_min_lines</item>
diff --git a/v17/leanback/src/android/support/v17/leanback/animation/UntargetableAnimatorSet.java b/v17/leanback/src/android/support/v17/leanback/animation/UntargetableAnimatorSet.java
deleted file mode 100644
index 9cdbc0cbfd..0000000000
--- a/v17/leanback/src/android/support/v17/leanback/animation/UntargetableAnimatorSet.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2015 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 android.support.v17.leanback.animation;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.TimeInterpolator;
-
-import java.util.ArrayList;
-
-/**
- * Custom fragment animations supplied by Fragment.onCreateAnimator have their targets set to the
- * fragment's main view by the fragment manager. Sometimes, this isn't what you want; you may be
- * supplying a heterogeneous collection of animations that already have targets. This class helps
- * you return such a collection of animations from onCreateAnimator without having their targets
- * reset.
- *
- * Note that one does not simply subclass AnimatorSet and override setTarget() because AnimatorSet
- * is final.
- * @hide
- */
-public class UntargetableAnimatorSet extends Animator {
-
- private final AnimatorSet mAnimatorSet;
-
- public UntargetableAnimatorSet(AnimatorSet animatorSet) {
- mAnimatorSet = animatorSet;
- }
-
- @Override
- public void addListener(Animator.AnimatorListener listener) {
- mAnimatorSet.addListener(listener);
- }
-
- @Override
- public void cancel() {
- mAnimatorSet.cancel();
- }
-
- @Override
- public Animator clone() {
- return mAnimatorSet.clone();
- }
-
- @Override
- public void end() {
- mAnimatorSet.end();
- }
-
- @Override
- public long getDuration() {
- return mAnimatorSet.getDuration();
- }
-
- @Override
- public ArrayList<Animator.AnimatorListener> getListeners() {
- return mAnimatorSet.getListeners();
- }
-
- @Override
- public long getStartDelay() {
- return mAnimatorSet.getStartDelay();
- }
-
- @Override
- public boolean isRunning() {
- return mAnimatorSet.isRunning();
- }
-
- @Override
- public boolean isStarted() {
- return mAnimatorSet.isStarted();
- }
-
- @Override
- public void removeAllListeners() {
- mAnimatorSet.removeAllListeners();
- }
-
- @Override
- public void removeListener(Animator.AnimatorListener listener) {
- mAnimatorSet.removeListener(listener);
- }
-
- @Override
- public Animator setDuration(long duration) {
- return mAnimatorSet.setDuration(duration);
- }
-
- @Override
- public void setInterpolator(TimeInterpolator value) {
- mAnimatorSet.setInterpolator(value);
- }
-
- @Override
- public void setStartDelay(long startDelay) {
- mAnimatorSet.setStartDelay(startDelay);
- }
-
- @Override
- public void setTarget(Object target) {
- // ignore
- }
-
- @Override
- public void setupEndValues() {
- mAnimatorSet.setupEndValues();
- }
-
- @Override
- public void setupStartValues() {
- mAnimatorSet.setupStartValues();
- }
-
- @Override
- public void start() {
- mAnimatorSet.start();
- }
-}
-
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BaseFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BaseFragment.java
index 5b2deac348..c878a86060 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BaseFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BaseFragment.java
@@ -30,8 +30,6 @@ class BaseFragment extends BrandedFragment {
private boolean mEntranceTransitionPreparePending = false;
private Object mEntranceTransition;
- static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
-
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -176,7 +174,7 @@ class BaseFragment extends BrandedFragment {
if (mEntranceTransition == null) {
return;
}
- sTransitionHelper.setTransitionListener(mEntranceTransition, new TransitionListener() {
+ TransitionHelper.addTransitionListener(mEntranceTransition, new TransitionListener() {
@Override
public void onTransitionEnd(Object transition) {
mEntranceTransition = null;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
index a72bb5b55d..b9c7d58429 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
@@ -32,8 +32,6 @@ class BaseSupportFragment extends BrandedSupportFragment {
private boolean mEntranceTransitionPreparePending = false;
private Object mEntranceTransition;
- static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
-
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -178,7 +176,7 @@ class BaseSupportFragment extends BrandedSupportFragment {
if (mEntranceTransition == null) {
return;
}
- sTransitionHelper.setTransitionListener(mEntranceTransition, new TransitionListener() {
+ TransitionHelper.addTransitionListener(mEntranceTransition, new TransitionListener() {
@Override
public void onTransitionEnd(Object transition) {
mEntranceTransition = null;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java
index 7e8f02fc40..8c417a4c2a 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java
@@ -425,7 +425,7 @@ public class BrowseFragment extends BaseFragment {
if (mBrowseTransitionListener != null) {
mBrowseTransitionListener.onHeadersTransitionStart(withHeaders);
}
- sTransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
+ TransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
mHeadersTransition);
if (mHeadersBackStackEnabled) {
if (!withHeaders) {
@@ -622,19 +622,19 @@ public class BrowseFragment extends BaseFragment {
mHeadersFragment.setBackgroundColor(mBrandColor);
}
- mSceneWithHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+ mSceneWithHeaders = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
@Override
public void run() {
showHeaders(true);
}
});
- mSceneWithoutHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+ mSceneWithoutHeaders = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
@Override
public void run() {
showHeaders(false);
}
});
- mSceneAfterEntranceTransition = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+ mSceneAfterEntranceTransition = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
@Override
public void run() {
setEntranceTransitionEndState();
@@ -644,11 +644,11 @@ public class BrowseFragment extends BaseFragment {
}
private void createHeadersTransition() {
- mHeadersTransition = sTransitionHelper.loadTransition(getActivity(),
+ mHeadersTransition = TransitionHelper.loadTransition(getActivity(),
mShowingHeaders ?
R.transition.lb_browse_headers_in : R.transition.lb_browse_headers_out);
- sTransitionHelper.setTransitionListener(mHeadersTransition, new TransitionListener() {
+ TransitionHelper.addTransitionListener(mHeadersTransition, new TransitionListener() {
@Override
public void onTransitionStart(Object transition) {
}
@@ -891,14 +891,13 @@ public class BrowseFragment extends BaseFragment {
@Override
protected Object createEntranceTransition() {
- return sTransitionHelper.loadTransition(getActivity(),
+ return TransitionHelper.loadTransition(getActivity(),
R.transition.lb_browse_entrance_transition);
}
@Override
protected void runEntranceTransition(Object entranceTransition) {
- sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
- entranceTransition);
+ TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
}
@Override
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java
index 44deec44c1..fa7f61ec9f 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java
@@ -427,7 +427,7 @@ public class BrowseSupportFragment extends BaseSupportFragment {
if (mBrowseTransitionListener != null) {
mBrowseTransitionListener.onHeadersTransitionStart(withHeaders);
}
- sTransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
+ TransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
mHeadersTransition);
if (mHeadersBackStackEnabled) {
if (!withHeaders) {
@@ -624,19 +624,19 @@ public class BrowseSupportFragment extends BaseSupportFragment {
mHeadersSupportFragment.setBackgroundColor(mBrandColor);
}
- mSceneWithHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+ mSceneWithHeaders = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
@Override
public void run() {
showHeaders(true);
}
});
- mSceneWithoutHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+ mSceneWithoutHeaders = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
@Override
public void run() {
showHeaders(false);
}
});
- mSceneAfterEntranceTransition = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
+ mSceneAfterEntranceTransition = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
@Override
public void run() {
setEntranceTransitionEndState();
@@ -646,11 +646,11 @@ public class BrowseSupportFragment extends BaseSupportFragment {
}
private void createHeadersTransition() {
- mHeadersTransition = sTransitionHelper.loadTransition(getActivity(),
+ mHeadersTransition = TransitionHelper.loadTransition(getActivity(),
mShowingHeaders ?
R.transition.lb_browse_headers_in : R.transition.lb_browse_headers_out);
- sTransitionHelper.setTransitionListener(mHeadersTransition, new TransitionListener() {
+ TransitionHelper.addTransitionListener(mHeadersTransition, new TransitionListener() {
@Override
public void onTransitionStart(Object transition) {
}
@@ -893,14 +893,13 @@ public class BrowseSupportFragment extends BaseSupportFragment {
@Override
protected Object createEntranceTransition() {
- return sTransitionHelper.loadTransition(getActivity(),
+ return TransitionHelper.loadTransition(getActivity(),
R.transition.lb_browse_entrance_transition);
}
@Override
protected void runEntranceTransition(Object entranceTransition) {
- sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
- entranceTransition);
+ TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
}
@Override
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
index d415de054e..ddafd5fd1c 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
@@ -14,6 +14,7 @@
package android.support.v17.leanback.app;
import android.support.v17.leanback.R;
+import android.support.v17.leanback.transition.TransitionHelper;
import android.support.v17.leanback.widget.BrowseFrameLayout;
import android.support.v17.leanback.widget.DetailsOverviewRow;
import android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter;
@@ -200,7 +201,7 @@ public class DetailsFragment extends BaseFragment {
}
}
- mSceneAfterEntranceTransition = sTransitionHelper.createScene(
+ mSceneAfterEntranceTransition = TransitionHelper.createScene(
(ViewGroup) view, new Runnable() {
@Override
public void run() {
@@ -394,25 +395,20 @@ public class DetailsFragment extends BaseFragment {
super.onStart();
setupChildFragmentLayout();
setupFocusSearchListener();
- mRowsFragment.getView().requestFocus();
if (isEntranceTransitionEnabled()) {
- // make sure recycler view animation is disabled
- mRowsFragment.onTransitionPrepare();
- mRowsFragment.onTransitionStart();
mRowsFragment.setEntranceTransitionState(false);
}
}
@Override
protected Object createEntranceTransition() {
- return sTransitionHelper.loadTransition(getActivity(),
+ return TransitionHelper.loadTransition(getActivity(),
R.transition.lb_details_enter_transition);
}
@Override
protected void runEntranceTransition(Object entranceTransition) {
- sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
- entranceTransition);
+ TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
}
@Override
@@ -420,4 +416,13 @@ public class DetailsFragment extends BaseFragment {
mRowsFragment.onTransitionEnd();
}
+ @Override
+ protected void onEntranceTransitionPrepare() {
+ mRowsFragment.onTransitionPrepare();
+ }
+
+ @Override
+ protected void onEntranceTransitionStart() {
+ mRowsFragment.onTransitionStart();
+ }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
index afaf5a81b0..7532d79dd1 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
@@ -16,6 +16,7 @@
package android.support.v17.leanback.app;
import android.support.v17.leanback.R;
+import android.support.v17.leanback.transition.TransitionHelper;
import android.support.v17.leanback.widget.BrowseFrameLayout;
import android.support.v17.leanback.widget.DetailsOverviewRow;
import android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter;
@@ -202,7 +203,7 @@ public class DetailsSupportFragment extends BaseSupportFragment {
}
}
- mSceneAfterEntranceTransition = sTransitionHelper.createScene(
+ mSceneAfterEntranceTransition = TransitionHelper.createScene(
(ViewGroup) view, new Runnable() {
@Override
public void run() {
@@ -396,25 +397,20 @@ public class DetailsSupportFragment extends BaseSupportFragment {
super.onStart();
setupChildFragmentLayout();
setupFocusSearchListener();
- mRowsSupportFragment.getView().requestFocus();
if (isEntranceTransitionEnabled()) {
- // make sure recycler view animation is disabled
- mRowsSupportFragment.onTransitionPrepare();
- mRowsSupportFragment.onTransitionStart();
mRowsSupportFragment.setEntranceTransitionState(false);
}
}
@Override
protected Object createEntranceTransition() {
- return sTransitionHelper.loadTransition(getActivity(),
+ return TransitionHelper.loadTransition(getActivity(),
R.transition.lb_details_enter_transition);
}
@Override
protected void runEntranceTransition(Object entranceTransition) {
- sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
- entranceTransition);
+ TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
}
@Override
@@ -422,4 +418,13 @@ public class DetailsSupportFragment extends BaseSupportFragment {
mRowsSupportFragment.onTransitionEnd();
}
+ @Override
+ protected void onEntranceTransitionPrepare() {
+ mRowsSupportFragment.onTransitionPrepare();
+ }
+
+ @Override
+ protected void onEntranceTransitionStart() {
+ mRowsSupportFragment.onTransitionStart();
+ }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
index 41ecac9983..142e9718e6 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
@@ -19,6 +19,7 @@ import android.media.AudioManager;
import android.support.v17.leanback.R;
import android.support.v17.leanback.widget.GuidedAction;
import android.support.v17.leanback.widget.GuidedActionsStylist;
+import android.support.v17.leanback.widget.ImeKeyMonitor;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.Log;
@@ -26,9 +27,14 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
import java.util.ArrayList;
import java.util.List;
@@ -43,6 +49,9 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
private static final String TAG = "GuidedActionAdapter";
private static final boolean DEBUG = false;
+ private static final String TAG_EDIT = "EditableAction";
+ private static final boolean DEBUG_EDIT = false;
+
/**
* Object listening for click events within a {@link GuidedActionAdapter}.
*/
@@ -66,11 +75,32 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
}
/**
+ * Object listening for edit events within a {@link GuidedActionAdapter}.
+ */
+ public interface EditListener {
+
+ /**
+ * Called when the user exits edit mode on an action.
+ */
+ public long onGuidedActionEdited(GuidedAction action);
+
+ /**
+ * Called when Ime Open
+ */
+ public void onImeOpen();
+
+ /**
+ * Called when Ime Close
+ */
+ public void onImeClose();
+ }
+
+ /**
* View holder containing a {@link GuidedAction}.
*/
- private static class ActionViewHolder extends ViewHolder {
+ static class ActionViewHolder extends ViewHolder {
- private final GuidedActionsStylist.ViewHolder mStylistViewHolder;
+ final GuidedActionsStylist.ViewHolder mStylistViewHolder;
private GuidedAction mAction;
/**
@@ -98,30 +128,36 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
}
}
- private RecyclerView mRecyclerView;
private final ActionOnKeyListener mActionOnKeyListener;
private final ActionOnFocusListener mActionOnFocusListener;
+ private final ActionEditListener mActionEditListener;
private final List<GuidedAction> mActions;
private ClickListener mClickListener;
- private GuidedActionsStylist mStylist;
+ private final GuidedActionsStylist mStylist;
private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (v != null && v.getWindowToken() != null && mClickListener != null) {
- ActionViewHolder avh = (ActionViewHolder)mRecyclerView.getChildViewHolder(v);
+ if (v != null && v.getWindowToken() != null && getRecyclerView() != null) {
+ ActionViewHolder avh = (ActionViewHolder)getRecyclerView().getChildViewHolder(v);
GuidedAction action = avh.getAction();
- if (action.isEnabled() && !action.infoOnly()) {
- mClickListener.onGuidedActionClicked(action);
+ if (action.isEditable() || action.isDescriptionEditable()) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme by click");
+ mGroup.openIme(GuidedActionAdapter.this, avh);
+ } else {
+ handleCheckedActions(avh);
+ if (action.isEnabled() && !action.infoOnly()) {
+ performOnActionClick(avh);
+ }
}
}
}
};
+ GuidedActionAdapterGroup mGroup;
/**
* Constructs a GuidedActionAdapter with the given list of guided actions, the given click and
* focus listeners, and the given presenter.
* @param actions The list of guided actions this adapter will manage.
- * @param clickListener The click listener for items in this adapter.
* @param focusListener The focus listener for items in this adapter.
* @param presenter The presenter that will manage the display of items in this adapter.
*/
@@ -131,8 +167,9 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
mActions = new ArrayList<GuidedAction>(actions);
mClickListener = clickListener;
mStylist = presenter;
- mActionOnKeyListener = new ActionOnKeyListener(clickListener, mActions);
+ mActionOnKeyListener = new ActionOnKeyListener();
mActionOnFocusListener = new ActionOnFocusListener(focusListener);
+ mActionEditListener = new ActionEditListener();
}
/**
@@ -164,12 +201,27 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
}
/**
+ * Return index of action in array
+ * @param action Action to search index.
+ * @return Index of Action in array.
+ */
+ public int indexOf(GuidedAction action) {
+ return mActions.indexOf(action);
+ }
+
+ /**
+ * @return GuidedActionsStylist used to build the actions list UI.
+ */
+ public GuidedActionsStylist getGuidedActionsStylist() {
+ return mStylist;
+ }
+
+ /**
* Sets the click listener for items managed by this adapter.
* @param clickListener The click listener for this adapter.
*/
public void setClickListener(ClickListener clickListener) {
mClickListener = clickListener;
- mActionOnKeyListener.setListener(clickListener);
}
/**
@@ -192,16 +244,12 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
* {@inheritDoc}
*/
@Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mRecyclerView = recyclerView;
+ public int getItemViewType(int position) {
+ return mStylist.getItemViewType(mActions.get(position));
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
- mRecyclerView = null;
+ private RecyclerView getRecyclerView() {
+ return mStylist.getActionsGridView();
}
/**
@@ -209,15 +257,29 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- GuidedActionsStylist.ViewHolder vh = mStylist.onCreateViewHolder(parent);
+ GuidedActionsStylist.ViewHolder vh = mStylist.onCreateViewHolder(parent, viewType);
View v = vh.view;
v.setOnKeyListener(mActionOnKeyListener);
v.setOnClickListener(mOnClickListener);
v.setOnFocusChangeListener(mActionOnFocusListener);
+ setupListeners(vh.getEditableTitleView());
+ setupListeners(vh.getEditableDescriptionView());
+
return new ActionViewHolder(v, vh);
}
+ private void setupListeners(EditText edit) {
+ if (edit != null) {
+ edit.setPrivateImeOptions("EscapeNorth=1;");
+ edit.setOnEditorActionListener(mActionEditListener);
+ if (edit instanceof ImeKeyMonitor) {
+ ImeKeyMonitor monitor = (ImeKeyMonitor)edit;
+ monitor.setImeKeyListener(mActionEditListener);
+ }
+ }
+ }
+
/**
* {@inheritDoc}
*/
@@ -226,7 +288,7 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
if (position >= mActions.size()) {
return;
}
- ActionViewHolder avh = (ActionViewHolder)holder;
+ final ActionViewHolder avh = (ActionViewHolder)holder;
GuidedAction action = mActions.get(position);
avh.setAction(action);
mStylist.onBindViewHolder(avh.mStylistViewHolder, action);
@@ -254,8 +316,8 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
}
public void unFocus() {
- if (mSelectedView != null) {
- ViewHolder vh = mRecyclerView.getChildViewHolder(mSelectedView);
+ if (mSelectedView != null && getRecyclerView() != null) {
+ ViewHolder vh = getRecyclerView().getChildViewHolder(mSelectedView);
if (vh != null) {
ActionViewHolder avh = (ActionViewHolder)vh;
mStylist.onAnimateItemFocused(avh.mStylistViewHolder, false);
@@ -268,8 +330,10 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
@Override
public void onFocusChange(View v, boolean hasFocus) {
- ActionViewHolder avh = (ActionViewHolder)mRecyclerView.getChildViewHolder(v);
- mStylist.onAnimateItemFocused(avh.mStylistViewHolder, hasFocus);
+ if (getRecyclerView() == null) {
+ return;
+ }
+ ActionViewHolder avh = (ActionViewHolder) getRecyclerView().getChildViewHolder(v);
if (hasFocus) {
mSelectedView = v;
if (mFocusListener != null) {
@@ -279,27 +343,74 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
}
} else {
if (mSelectedView == v) {
+ mStylist.onAnimateItemPressedCancelled(avh.mStylistViewHolder);
mSelectedView = null;
}
}
+ mStylist.onAnimateItemFocused(avh.mStylistViewHolder, hasFocus);
}
}
- private class ActionOnKeyListener implements View.OnKeyListener {
+ public ActionViewHolder findSubChildViewHolder(View v) {
+ // Needed because RecyclerView.getChildViewHolder does not traverse the hierarchy
+ if (getRecyclerView() == null) {
+ return null;
+ }
+ ActionViewHolder result = null;
+ ViewParent parent = v.getParent();
+ while (parent != getRecyclerView() && parent != null && v != null) {
+ v = (View)parent;
+ parent = parent.getParent();
+ }
+ if (parent != null && v != null) {
+ result = (ActionViewHolder)getRecyclerView().getChildViewHolder(v);
+ }
+ return result;
+ }
- private final List<GuidedAction> mActions;
- private boolean mKeyPressed = false;
- private ClickListener mClickListener;
+ public void handleCheckedActions(ActionViewHolder avh) {
+ GuidedAction action = avh.getAction();
+ int actionCheckSetId = action.getCheckSetId();
+ if (getRecyclerView() != null && actionCheckSetId != GuidedAction.NO_CHECK_SET) {
+ // Find any actions that are checked and are in the same group
+ // as the selected action. Fade their checkmarks out.
+ if (actionCheckSetId != GuidedAction.CHECKBOX_CHECK_SET_ID) {
+ for (int i = 0, size = mActions.size(); i < size; i++) {
+ GuidedAction a = mActions.get(i);
+ if (a != action && a.getCheckSetId() == actionCheckSetId && a.isChecked()) {
+ a.setChecked(false);
+ ViewHolder vh = getRecyclerView().findViewHolderForPosition(i);
+ if (vh != null) {
+ GuidedActionsStylist.ViewHolder subViewHolder =
+ ((ActionViewHolder)vh).mStylistViewHolder;
+ mStylist.onAnimateItemChecked(subViewHolder, false);
+ }
+ }
+ }
+ }
- public ActionOnKeyListener(ClickListener listener,
- List<GuidedAction> actions) {
- mClickListener = listener;
- mActions = actions;
+ // If we we'ren't already checked, fade our checkmark in.
+ if (!action.isChecked()) {
+ action.setChecked(true);
+ mStylist.onAnimateItemChecked(avh.mStylistViewHolder, true);
+ } else {
+ if (actionCheckSetId == GuidedAction.CHECKBOX_CHECK_SET_ID) {
+ action.setChecked(false);
+ mStylist.onAnimateItemChecked(avh.mStylistViewHolder, false);
+ }
+ }
}
+ }
- public void setListener(ClickListener listener) {
- mClickListener = listener;
+ public void performOnActionClick(ActionViewHolder avh) {
+ if (mClickListener != null) {
+ mClickListener.onGuidedActionClicked(avh.getAction());
}
+ }
+
+ private class ActionOnKeyListener implements View.OnKeyListener {
+
+ private boolean mKeyPressed = false;
private void playSound(View v, int soundEffect) {
if (v.isSoundEffectsEnabled()) {
@@ -314,7 +425,7 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
*/
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
- if (v == null || event == null) {
+ if (v == null || event == null || getRecyclerView() == null) {
return false;
}
boolean handled = false;
@@ -325,7 +436,8 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
case KeyEvent.KEYCODE_BUTTON_Y:
case KeyEvent.KEYCODE_ENTER:
- ActionViewHolder avh = (ActionViewHolder)mRecyclerView.getChildViewHolder(v);
+ ActionViewHolder avh = (ActionViewHolder) getRecyclerView()
+ .getChildViewHolder(v);
GuidedAction action = avh.getAction();
if (!action.isEnabled() || action.infoOnly()) {
@@ -338,33 +450,25 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
+ if (DEBUG) {
+ Log.d(TAG, "Enter Key down");
+ }
if (!mKeyPressed) {
mKeyPressed = true;
-
playSound(v, AudioManager.FX_KEY_CLICK);
-
- if (DEBUG) {
- Log.d(TAG, "Enter Key down");
- }
-
mStylist.onAnimateItemPressed(avh.mStylistViewHolder,
mKeyPressed);
- handled = true;
}
break;
case KeyEvent.ACTION_UP:
+ if (DEBUG) {
+ Log.d(TAG, "Enter Key up");
+ }
+ // Sometimes we are losing ACTION_DOWN for the first ENTER after pressed
+ // Escape in IME.
if (mKeyPressed) {
mKeyPressed = false;
-
- if (DEBUG) {
- Log.d(TAG, "Enter Key up");
- }
-
- mStylist.onAnimateItemPressed(avh.mStylistViewHolder,
- mKeyPressed);
- handleCheckedActions(avh, action);
- mClickListener.onGuidedActionClicked(action);
- handled = true;
+ mStylist.onAnimateItemPressed(avh.mStylistViewHolder, mKeyPressed);
}
break;
default:
@@ -377,30 +481,40 @@ class GuidedActionAdapter extends RecyclerView.Adapter {
return handled;
}
- private void handleCheckedActions(ActionViewHolder avh, GuidedAction action) {
- int actionCheckSetId = action.getCheckSetId();
- if (actionCheckSetId != GuidedAction.NO_CHECK_SET) {
- // Find any actions that are checked and are in the same group
- // as the selected action. Fade their checkmarks out.
- for (int i = 0, size = mActions.size(); i < size; i++) {
- GuidedAction a = mActions.get(i);
- if (a != action && a.getCheckSetId() == actionCheckSetId && a.isChecked()) {
- a.setChecked(false);
- ViewHolder vh = mRecyclerView.findViewHolderForPosition(i);
- if (vh != null) {
- GuidedActionsStylist.ViewHolder subViewHolder =
- ((ActionViewHolder)vh).mStylistViewHolder;
- mStylist.onAnimateItemChecked(subViewHolder, false);
- }
- }
- }
+ }
- // If we we'ren't already checked, fade our checkmark in.
- if (!action.isChecked()) {
- action.setChecked(true);
- mStylist.onAnimateItemChecked(avh.mStylistViewHolder, true);
- }
+ private class ActionEditListener implements OnEditorActionListener,
+ ImeKeyMonitor.ImeKeyListener {
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME action: " + actionId);
+ boolean handled = false;
+ if (actionId == EditorInfo.IME_ACTION_NEXT ||
+ actionId == EditorInfo.IME_ACTION_DONE) {
+ mGroup.fillAndGoNext(GuidedActionAdapter.this, v);
+ handled = true;
+ } else if (actionId == EditorInfo.IME_ACTION_NONE) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme escape north");
+ // Escape north handling: stay on current item, but close editor
+ handled = true;
+ mGroup.fillAndStay(GuidedActionAdapter.this, v);
}
+ return handled;
}
+
+ @Override
+ public boolean onKeyPreIme(EditText editText, int keyCode, KeyEvent event) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME key: " + keyCode);
+ if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
+ mGroup.fillAndStay(GuidedActionAdapter.this, editText);
+ } else if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() ==
+ KeyEvent.ACTION_UP) {
+ mGroup.fillAndGoNext(GuidedActionAdapter.this, editText);
+ }
+ return false;
+ }
+
}
+
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapterGroup.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapterGroup.java
new file mode 100644
index 0000000000..8f8951c5e8
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapterGroup.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.app;
+
+import android.content.Context;
+import android.support.v17.leanback.app.GuidedActionAdapter.ActionViewHolder;
+import android.support.v17.leanback.app.GuidedActionAdapter.ClickListener;
+import android.support.v17.leanback.app.GuidedActionAdapter.EditListener;
+import android.support.v17.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.ImeKeyMonitor;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewParent;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import java.util.ArrayList;
+
+/**
+ * Internal implementation manages a group of GuidedActionAdapters, control the next action after
+ * editing finished, maintain the Ime open/close status.
+ */
+class GuidedActionAdapterGroup {
+
+ private static final String TAG_EDIT = "EditableAction";
+ private static final boolean DEBUG_EDIT = false;
+
+ ArrayList<GuidedActionAdapter> mAdapters = new ArrayList<GuidedActionAdapter>();
+ private boolean mImeOpened;
+ private EditListener mEditListener;
+
+ GuidedActionAdapterGroup() {
+ }
+
+ public void addAdpter(GuidedActionAdapter adapter) {
+ mAdapters.add(adapter);
+ adapter.mGroup = this;
+ }
+
+ public void setEditListener(EditListener listener) {
+ mEditListener = listener;
+ }
+
+ boolean focusToNextAction(GuidedActionAdapter adapter, GuidedAction action, long nextActionId) {
+ // for ACTION_ID_NEXT, we first find out the matching index in Actions list.
+ int index = 0;
+ if (nextActionId == GuidedAction.ACTION_ID_NEXT) {
+ index = adapter.indexOf(action);
+ if (index < 0) {
+ return false;
+ }
+ // start from next, if reach end, will go next Adapter below
+ index++;
+ }
+
+ int adapterIndex = mAdapters.indexOf(adapter);
+ do {
+ int size = adapter.getCount();
+ if (nextActionId == GuidedAction.ACTION_ID_NEXT) {
+ while (index < size && !adapter.getItem(index).isFocusable()) {
+ index++;
+ }
+ } else {
+ while (index < size && adapter.getItem(index).getId() != nextActionId) {
+ index++;
+ }
+ }
+ if (index < size) {
+ ActionViewHolder vh = (ActionViewHolder) adapter.getGuidedActionsStylist()
+ .getActionsGridView().findViewHolderForPosition(index);
+ if (vh != null) {
+ if (vh.getAction().isEditable() || vh.getAction().isDescriptionEditable()) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme of next Action");
+ // open Ime on next action.
+ openIme(adapter, vh);
+ } else {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme and focus to next Action");
+ // close IME and focus to next (not editable) action
+ closeIme(vh.mStylistViewHolder.view);
+ vh.mStylistViewHolder.view.requestFocus();
+ }
+ return true;
+ }
+ return false;
+ }
+ // search from index 0 of next Adapter
+ adapterIndex++;
+ if (adapterIndex >= mAdapters.size()) {
+ break;
+ }
+ adapter = mAdapters.get(adapterIndex);
+ index = 0;
+ } while (true);
+ return false;
+ }
+
+ public void openIme(GuidedActionAdapter adapter, ActionViewHolder avh) {
+ adapter.getGuidedActionsStylist().setEditingMode(avh.mStylistViewHolder, avh.getAction(),
+ true);
+ View v = avh.mStylistViewHolder.getEditingView();
+ if (v == null) {
+ return;
+ }
+ InputMethodManager mgr = (InputMethodManager)
+ v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ v.requestFocus();
+ mgr.showSoftInput(v, 0);
+ if (!mImeOpened) {
+ mImeOpened = true;
+ mEditListener.onImeOpen();
+ }
+ }
+
+ public void closeIme(View v) {
+ if (mImeOpened) {
+ mImeOpened = false;
+ InputMethodManager mgr = (InputMethodManager)
+ v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ mgr.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ mEditListener.onImeClose();
+ }
+ }
+
+ private long finishEditing(GuidedActionAdapter adapter, ActionViewHolder avh) {
+ long nextActionId = mEditListener.onGuidedActionEdited(avh.getAction());
+ adapter.getGuidedActionsStylist().setEditingMode(avh.mStylistViewHolder, avh.getAction(),
+ false);
+ return nextActionId;
+ }
+
+ public void fillAndStay(GuidedActionAdapter adapter, TextView v) {
+ ActionViewHolder avh = adapter.findSubChildViewHolder(v);
+ updateTextIntoAction(avh, v);
+ finishEditing(adapter, avh);
+ closeIme(v);
+ avh.mStylistViewHolder.view.requestFocus();
+ }
+
+ public void fillAndGoNext(GuidedActionAdapter adapter, TextView v) {
+ boolean handled = false;
+ ActionViewHolder avh = adapter.findSubChildViewHolder(v);
+ updateTextIntoAction(avh, v);
+ adapter.performOnActionClick(avh);
+ long nextActionId = finishEditing(adapter, avh);
+ if (nextActionId != GuidedAction.ACTION_ID_CURRENT
+ && nextActionId != avh.getAction().getId()) {
+ handled = focusToNextAction(adapter, avh.getAction(), nextActionId);
+ }
+ if (!handled) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme no next action");
+ handled = true;
+ closeIme(v);
+ avh.mStylistViewHolder.view.requestFocus();
+ }
+ }
+
+ private void updateTextIntoAction(ActionViewHolder avh, TextView v) {
+ GuidedAction action = avh.getAction();
+ if (v == avh.mStylistViewHolder.getDescriptionView()) {
+ if (action.getEditDescription() != null) {
+ action.setEditDescription(v.getText());
+ } else {
+ action.setDescription(v.getText());
+ }
+ } else if (v == avh.mStylistViewHolder.getTitleView()) {
+ if (action.getEditTitle() != null) {
+ action.setEditTitle(v.getText());
+ } else {
+ action.setTitle(v.getText());
+ }
+ }
+ }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
index b1e87a1e4d..8be8f24f47 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
@@ -18,28 +18,34 @@ import android.animation.AnimatorSet;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
+import android.app.FragmentManager.BackStackEntry;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.res.TypedArray;
+import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
-import android.support.v17.leanback.animation.UntargetableAnimatorSet;
+import android.support.v17.leanback.transition.TransitionHelper;
import android.support.v17.leanback.R;
import android.support.v17.leanback.widget.GuidanceStylist;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
import android.support.v17.leanback.widget.GuidedActionsStylist;
import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v4.app.ActivityCompat;
+import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
+import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.RelativeLayout;
+import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
@@ -52,7 +58,7 @@ import java.util.List;
* <p>
* <h3>Basic Usage</h3>
* <p>
- * Clients of GuidedStepFragment typically create a custom subclass to attach to their Activities.
+ * Clients of GuidedStepFragment must create a custom subclass to attach to their Activities.
* This custom subclass provides the information necessary to construct the user interface and
* respond to user actions. At a minimum, subclasses should override:
* <ul>
@@ -61,6 +67,19 @@ import java.util.List;
* <li>{@link #onGuidedActionClicked}, to respond to those actions</li>
* </ul>
* <p>
+ * Clients use following helper functions to add GuidedStepFragment to Activity or FragmentManager:
+ * <ul>
+ * <li>{@link #addAsRoot(Activity, GuidedStepFragment, int)}, to be called during Activity onCreate,
+ * adds GuidedStepFragment as the first Fragment in activity.</li>
+ * <li>{@link #add(FragmentManager, GuidedStepFragment)} or {@link #add(FragmentManager,
+ * GuidedStepFragment, int)}, to add GuidedStepFragment on top of existing Fragments or
+ * replacing existing GuidedStepFragment when moving forward to next step.</li>
+ * <li>{@link #finishGuidedStepFragments()} can either finish the activity or pop all
+ * GuidedStepFragment from stack.
+ * <li>If app chooses not to use the helper function, it is the app's responsibility to call
+ * {@link #setUiStyle(int)} to select fragment transition and remember the stack entry where it
+ * need pops to.
+ * </ul>
* <h3>Theming and Stylists</h3>
* <p>
* GuidedStepFragment delegates its visual styling to classes called stylists. The {@link
@@ -106,8 +125,14 @@ import java.util.List;
* <p>
* <i>Note: Currently GuidedStepFragments grouped in this way must all be defined programmatically,
* rather than in XML. This restriction may be removed in the future.</i>
- * <p>
+ *
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepTheme
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepBackground
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidthWeight
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidthWeightTwoPanels
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsBackground
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsBackgroundDark
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsElevation
* @see GuidanceStylist
* @see GuidanceStylist.Guidance
* @see GuidedAction
@@ -118,24 +143,81 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
private static final String TAG_LEAN_BACK_ACTIONS_FRAGMENT = "leanBackGuidedStepFragment";
private static final String EXTRA_ACTION_SELECTED_INDEX = "selectedIndex";
- private static final String EXTRA_ACTION_ENTRY_TRANSITION_ENABLED = "entryTransitionEnabled";
- private static final String EXTRA_ENTRY_TRANSITION_PERFORMED = "entryTransitionPerformed";
+
+ private static final String ENTRY_NAME_REPLACE = "GuidedStepDefault";
+
+ private static final String ENTRY_NAME_ENTRANCE = "GuidedStepEntrance";
+
+ /**
+ * Fragment argument name for UI style. The argument value is persisted in fragment state.
+ * The value is initially {@link #UI_STYLE_ENTRANCE} and might be changed in one of the three
+ * helper functions:
+ * <ul>
+ * <li>{@link #addAsRoot(Activity, GuidedStepFragment, int)}</li>
+ * <li>{@link #add(FragmentManager, GuidedStepFragment)} or {@link #add(FragmentManager,
+ * GuidedStepFragment, int)}</li>
+ * </ul>
+ * <p>
+ * Argument value can be either:
+ * <ul>
+ * <li>{@link #UI_STYLE_REPLACE}</li>
+ * <li>{@link #UI_STYLE_ENTRANCE}</li>
+ * <li>{@link #UI_STYLE_ACTIVITY_ROOT}</li>
+ * </ul>
+ */
+ public static final String EXTRA_UI_STYLE = "uiStyle";
+
+ /**
+ * This is the case that we use GuidedStepFragment to replace another existing
+ * GuidedStepFragment when moving forward to next step. Default behavior of this style is:
+ * <ul>
+ * <li>Enter transition slides in from END(right), exit transition same as
+ * {@link #UI_STYLE_ENTRANCE}.
+ * </li>
+ * </ul>
+ */
+ public static final int UI_STYLE_REPLACE = 0;
+
+ /**
+ * Default value for argument {@link #EXTRA_UI_STYLE}. The default value is assigned in
+ * GuidedStepFragment constructor. This is the case that we show GuidedStepFragment on top of
+ * other content. The default behavior of this style:
+ * <ul>
+ * <li>Enter transition slides in from two sides, exit transition slide out to START(left).
+ * Background will be faded in. Note: Changing exit transition by UI style is not working
+ * because fragment transition asks for exit transition before UI style is restored in Fragment
+ * .onCreate().</li>
+ * </ul>
+ */
+ public static final int UI_STYLE_ENTRANCE = 1;
+
+ /**
+ * One possible value of argument {@link #EXTRA_UI_STYLE}. This is the case that we show first
+ * GuidedStepFragment in a separate activity. The default behavior of this style:
+ * <ul>
+ * <li>Enter transition is assigned null (will rely on activity transition), exit transition is
+ * same as {@link #UI_STYLE_ENTRANCE}. Note: Changing exit transition by UI style is not working
+ * because fragment transition asks for exit transition before UI style is restored in
+ * Fragment.onCreate().</li>
+ * </ul>
+ */
+ public static final int UI_STYLE_ACTIVITY_ROOT = 2;
+
private static final String TAG = "GuidedStepFragment";
- private static final boolean DEBUG = true;
- private static final int ANIMATION_FRAGMENT_ENTER = 1;
- private static final int ANIMATION_FRAGMENT_EXIT = 2;
- private static final int ANIMATION_FRAGMENT_ENTER_POP = 3;
- private static final int ANIMATION_FRAGMENT_EXIT_POP = 4;
+ private static final boolean DEBUG = false;
private int mTheme;
+ private ContextThemeWrapper mThemeWrapper;
private GuidanceStylist mGuidanceStylist;
private GuidedActionsStylist mActionsStylist;
+ private GuidedActionsStylist mButtonActionsStylist;
private GuidedActionAdapter mAdapter;
- private VerticalGridView mListView;
+ private GuidedActionAdapter mButtonAdapter;
+ private GuidedActionAdapterGroup mAdapterGroup;
private List<GuidedAction> mActions = new ArrayList<GuidedAction>();
+ private List<GuidedAction> mButtonActions = new ArrayList<GuidedAction>();
private int mSelectedIndex = -1;
- private boolean mEntryTransitionPerformed;
- private boolean mEntryTransitionEnabled = true;
+ private int mButtonSelectedIndex = -1;
public GuidedStepFragment() {
// We need to supply the theme before any potential call to onInflate in order
@@ -143,6 +225,8 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
mTheme = onProvideTheme();
mGuidanceStylist = onCreateGuidanceStylist();
mActionsStylist = onCreateActionsStylist();
+ mButtonActionsStylist = onCreateButtonActionsStylist();
+ onProvideFragmentTransitions();
}
/**
@@ -164,6 +248,15 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
}
/**
+ * Creates the presenter used to style a sided actions panel for button only.
+ * The default implementation returns a basic GuidedActionsStylist.
+ * @return The GuidedActionsStylist used in this fragment.
+ */
+ public GuidedActionsStylist onCreateButtonActionsStylist() {
+ return new GuidedActionsStylist();
+ }
+
+ /**
* Returns the theme used for styling the fragment. The default returns -1, indicating that the
* host Activity's theme should be used.
* @return The theme resource ID of the theme to use in this fragment, or -1 to use the
@@ -195,6 +288,16 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
}
/**
+ * Fills out the set of actions shown at right available to the user. This hook is called during
+ * {@link #onCreate}. The default leaves the list of actions empty; subclasses may override.
+ * @param actions A non-null, empty list ready to be populated.
+ * @param savedInstanceState The saved instance state from onCreate.
+ */
+ public void onCreateButtonActions(@NonNull List<GuidedAction> actions,
+ Bundle savedInstanceState) {
+ }
+
+ /**
* Callback invoked when an action is taken by the user. Subclasses should override in
* order to act on the user's decisions.
* @param action The chosen action.
@@ -211,8 +314,34 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
}
/**
+ * Callback invoked when an action's title or description has been edited.
+ * Override {@link #onGuidedActionEditedAndProceed(GuidedAction)} instead of app wants to
+ * control the next action to focus on.
+ */
+ public void onGuidedActionEdited(GuidedAction action) {
+ }
+
+ /**
+ * Callback invoked when an action's title or description has been edited. Default
+ * implementation calls {@link #onGuidedActionEdited(GuidedAction)} and returns
+ * {@link GuidedAction#ACTION_ID_NEXT}.
+ *
+ * @param action The action that has been edited.
+ * @return ID of the action will be focused or {@link GuidedAction#ACTION_ID_NEXT},
+ * {@link GuidedAction#ACTION_ID_CURRENT}.
+ */
+ public long onGuidedActionEditedAndProceed(GuidedAction action) {
+ onGuidedActionEdited(action);
+ return GuidedAction.ACTION_ID_NEXT;
+ }
+
+ /**
* Adds the specified GuidedStepFragment to the fragment stack, replacing any existing
- * GuidedStepFragments in the stack, and configuring the fragment-to-fragment custom animations.
+ * GuidedStepFragments in the stack, and configuring the fragment-to-fragment custom
+ * transitions. A backstack entry is added, so the fragment will be dismissed when BACK key
+ * is pressed.
+ * <li>If current fragment on stack is GuidedStepFragment: assign {@link #UI_STYLE_REPLACE}
+ * <li>If current fragment on stack is not GuidedStepFragment: assign {@link #UI_STYLE_ENTRANCE}
* <p>
* Note: currently fragments added using this method must be created programmatically rather
* than via XML.
@@ -224,19 +353,165 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
return add(fragmentManager, fragment, android.R.id.content);
}
- // Note, this method used to be public, but I haven't found a good way for a client
- // to specify an id.
- private static int add(FragmentManager fm, GuidedStepFragment f, int id) {
- boolean inGuidedStep = getCurrentGuidedStepFragment(fm) != null;
- FragmentTransaction ft = fm.beginTransaction();
+ /**
+ * Adds the specified GuidedStepFragment to the fragment stack, replacing any existing
+ * GuidedStepFragments in the stack, and configuring the fragment-to-fragment custom
+ * transitions. A backstack entry is added, so the fragment will be dismissed when BACK key
+ * is pressed.
+ * <li>If current fragment on stack is GuidedStepFragment: assign {@link #UI_STYLE_REPLACE} and
+ * {@link #onAddSharedElementTransition(FragmentTransaction, GuidedStepFragment)} will be called
+ * to perform shared element transition between GuidedStepFragments.
+ * <li>If current fragment on stack is not GuidedStepFragment: assign {@link #UI_STYLE_ENTRANCE}
+ * <p>
+ * Note: currently fragments added using this method must be created programmatically rather
+ * than via XML.
+ * @param fragmentManager The FragmentManager to be used in the transaction.
+ * @param fragment The GuidedStepFragment to be inserted into the fragment stack.
+ * @param id The id of container to add GuidedStepFragment, can be android.R.id.content.
+ * @return The ID returned by the call FragmentTransaction.replace.
+ */
+ public static int add(FragmentManager fragmentManager, GuidedStepFragment fragment, int id) {
+ GuidedStepFragment current = getCurrentGuidedStepFragment(fragmentManager);
+ boolean inGuidedStep = current != null;
+ FragmentTransaction ft = fragmentManager.beginTransaction();
+
+ fragment.setUiStyle(inGuidedStep ? UI_STYLE_REPLACE : UI_STYLE_ENTRANCE);
+ ft.addToBackStack(fragment.generateStackEntryName());
+ if (current != null) {
+ fragment.onAddSharedElementTransition(ft, current);
+ }
+ return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
+ }
+
+ /**
+ * Called when this fragment is added to FragmentTransaction with {@link #UI_STYLE_REPLACE} (aka
+ * when the GuidedStepFragment replacing an existing GuidedStepFragment). Default implementation
+ * establishes connections between action background views to morph action background bounds
+ * change from disappearing GuidedStepFragment into this GuidedStepFragment. The default
+ * implementation heavily relies on {@link GuidedActionsStylist}'s layout, app may override this
+ * method when modifying the default layout of {@link GuidedActionsStylist}.
+ *
+ * @see GuidedActionsStylist
+ * @see #onProvideFragmentTransitions()
+ * @param ft The FragmentTransaction to add shared element.
+ * @param disappearing The disappearing fragment.
+ */
+ protected void onAddSharedElementTransition(FragmentTransaction ft, GuidedStepFragment
+ disappearing) {
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.action_fragment_root), "action_fragment_root");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.action_fragment_background), "action_fragment_background");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.action_fragment), "action_fragment");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_root), "guidedactions_root");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_selector), "guidedactions_selector");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_content), "guidedactions_content");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_list_background), "guidedactions_list_background");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_root2), "guidedactions_root2");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_selector2), "guidedactions_selector2");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_content2), "guidedactions_content2");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_list_background2), "guidedactions_list_background2");
+ }
+
+ /**
+ * Returns BackStackEntry name for the GuidedStepFragment or empty String if no entry is
+ * associated. Note {@link #UI_STYLE_ACTIVITY_ROOT} will return empty String. The method
+ * returns undefined value if the fragment is not in FragmentManager.
+ * @return BackStackEntry name for the GuidedStepFragment or empty String if no entry is
+ * associated.
+ */
+ public String generateStackEntryName() {
+ return generateStackEntryName(getUiStyle(), getClass());
+ }
+
+ /**
+ * Generates BackStackEntry name for GuidedStepFragment class or empty String if no entry is
+ * associated. Note {@link #UI_STYLE_ACTIVITY_ROOT} is not allowed and returns empty String.
+ * @param uiStyle {@link #UI_STYLE_REPLACE} or {@link #UI_STYLE_ENTRANCE}
+ * @return BackStackEntry name for the GuidedStepFragment or empty String if no entry is
+ * associated.
+ */
+ public static String generateStackEntryName(int uiStyle, Class guidedStepFragmentClass) {
+ if (!GuidedStepFragment.class.isAssignableFrom(guidedStepFragmentClass)) {
+ return "";
+ }
+ switch (uiStyle) {
+ case UI_STYLE_REPLACE:
+ return ENTRY_NAME_REPLACE + guidedStepFragmentClass.getName();
+ case UI_STYLE_ENTRANCE:
+ return ENTRY_NAME_ENTRANCE + guidedStepFragmentClass.getName();
+ case UI_STYLE_ACTIVITY_ROOT:
+ default:
+ return "";
+ }
+ }
+
+ /**
+ * Returns true if the backstack represents GuidedStepFragment with {@link #UI_STYLE_ENTRANCE};
+ * false otherwise.
+ * @param backStackEntryName Name of BackStackEntry.
+ * @return True if the backstack represents GuidedStepFragment with {@link #UI_STYLE_ENTRANCE};
+ * false otherwise.
+ */
+ public static boolean isUiStyleEntrance(String backStackEntryName) {
+ return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE);
+ }
+
+ /**
+ * Returns true if the backstack represents GuidedStepFragment with {@link #UI_STYLE_REPLACE};
+ * false otherwise.
+ * @param backStackEntryName Name of BackStackEntry.
+ * @return True if the backstack represents GuidedStepFragment with {@link #UI_STYLE_REPLACE};
+ * false otherwise.
+ */
+ public static boolean isUiStyleDefault(String backStackEntryName) {
+ return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_REPLACE);
+ }
- if (inGuidedStep) {
- ft.setCustomAnimations(ANIMATION_FRAGMENT_ENTER,
- ANIMATION_FRAGMENT_EXIT, ANIMATION_FRAGMENT_ENTER_POP,
- ANIMATION_FRAGMENT_EXIT_POP);
- ft.addToBackStack(null);
+ /**
+ * Extract Class name from BackStackEntry name.
+ * @param backStackEntryName Name of BackStackEntry.
+ * @return Class name of GuidedStepFragment.
+ */
+ public static String getGuidedStepFragmentClassName(String backStackEntryName) {
+ if (backStackEntryName.startsWith(ENTRY_NAME_REPLACE)) {
+ return backStackEntryName.substring(ENTRY_NAME_REPLACE.length());
+ } else if (backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE)) {
+ return backStackEntryName.substring(ENTRY_NAME_ENTRANCE.length());
+ } else {
+ return "";
}
- return ft.replace(id, f, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
+ }
+
+ /**
+ * Adds the specified GuidedStepFragment as content of Activity; no backstack entry is added so
+ * the activity will be dismissed when BACK key is pressed.
+ * {@link #UI_STYLE_ACTIVITY_ROOT} is assigned.
+ *
+ * Note: currently fragments added using this method must be created programmatically rather
+ * than via XML.
+ * @param activity The Activity to be used to insert GuidedstepFragment.
+ * @param fragment The GuidedStepFragment to be inserted into the fragment stack.
+ * @param id The id of container to add GuidedStepFragment, can be android.R.id.content.
+ * @return The ID returned by the call FragmentTransaction.replace.
+ */
+ public static int addAsRoot(Activity activity, GuidedStepFragment fragment, int id) {
+ // Workaround b/23764120: call getDecorView() to force requestFeature of ActivityTransition.
+ activity.getWindow().getDecorView();
+
+ FragmentManager fragmentManager = activity.getFragmentManager();
+ FragmentTransaction ft = fragmentManager.beginTransaction();
+ fragment.setUiStyle(UI_STYLE_ACTIVITY_ROOT);
+ return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
}
/**
@@ -268,6 +543,99 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
}
/**
+ * Returns the list of button GuidedActions that the user may take in this fragment.
+ * @return The list of button GuidedActions for this fragment.
+ */
+ public List<GuidedAction> getButtonActions() {
+ return mButtonActions;
+ }
+
+ /**
+ * Find button GuidedAction by Id.
+ * @param id Id of the button action to search.
+ * @return GuidedAction object or null if not found.
+ */
+ public GuidedAction findButtonActionById(long id) {
+ int index = findButtonActionPositionById(id);
+ return index >= 0 ? mButtonActions.get(index) : null;
+ }
+
+ /**
+ * Find button GuidedAction position in array by Id.
+ * @param id Id of the button action to search.
+ * @return position of GuidedAction object in array or -1 if not found.
+ */
+ public int findButtonActionPositionById(long id) {
+ if (mButtonActions != null) {
+ for (int i = 0; i < mButtonActions.size(); i++) {
+ GuidedAction action = mButtonActions.get(i);
+ if (mButtonActions.get(i).getId() == id) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the GuidedActionsStylist that displays the button actions the user may take.
+ * @return The GuidedActionsStylist for this fragment.
+ */
+ public GuidedActionsStylist getGuidedButtonActionsStylist() {
+ return mButtonActionsStylist;
+ }
+
+ /**
+ * Sets the list of button GuidedActions that the user may take in this fragment.
+ * @param actions The list of button GuidedActions for this fragment.
+ */
+ public void setButtonActions(List<GuidedAction> actions) {
+ mButtonActions = actions;
+ if (mButtonAdapter != null) {
+ mButtonAdapter.setActions(mButtonActions);
+ }
+ }
+
+ /**
+ * Notify an button action has changed and update its UI.
+ * @param position Position of the button GuidedAction in array.
+ */
+ public void notifyButtonActionChanged(int position) {
+ if (mButtonAdapter != null) {
+ mButtonAdapter.notifyItemChanged(position);
+ }
+ }
+
+ /**
+ * Returns the view corresponding to the button action at the indicated position in the list of
+ * actions for this fragment.
+ * @param position The integer position of the button action of interest.
+ * @return The View corresponding to the button action at the indicated position, or null if
+ * that action is not currently onscreen.
+ */
+ public View getButtonActionItemView(int position) {
+ final RecyclerView.ViewHolder holder = mButtonActionsStylist.getActionsGridView()
+ .findViewHolderForPosition(position);
+ return holder == null ? null : holder.itemView;
+ }
+
+ /**
+ * Scrolls the action list to the position indicated, selecting that button action's view.
+ * @param position The integer position of the button action of interest.
+ */
+ public void setSelectedButtonActionPosition(int position) {
+ mButtonActionsStylist.getActionsGridView().setSelectedPosition(position);
+ }
+
+ /**
+ * Returns the position if the currently selected button GuidedAction.
+ * @return position The integer position of the currently selected button action.
+ */
+ public int getSelectedButtonActionPosition() {
+ return mButtonActionsStylist.getActionsGridView().getSelectedPosition();
+ }
+
+ /**
* Returns the list of GuidedActions that the user may take in this fragment.
* @return The list of GuidedActions for this fragment.
*/
@@ -276,6 +644,33 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
}
/**
+ * Find GuidedAction by Id.
+ * @param id Id of the action to search.
+ * @return GuidedAction object or null if not found.
+ */
+ public GuidedAction findActionById(long id) {
+ int index = findActionPositionById(id);
+ return index >= 0 ? mActions.get(index) : null;
+ }
+
+ /**
+ * Find GuidedAction position in array by Id.
+ * @param id Id of the action to search.
+ * @return position of GuidedAction object in array or -1 if not found.
+ */
+ public int findActionPositionById(long id) {
+ if (mActions != null) {
+ for (int i = 0; i < mActions.size(); i++) {
+ GuidedAction action = mActions.get(i);
+ if (mActions.get(i).getId() == id) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
* Sets the list of GuidedActions that the user may take in this fragment.
* @param actions The list of GuidedActions for this fragment.
*/
@@ -287,6 +682,16 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
}
/**
+ * Notify an action has changed and update its UI.
+ * @param position Position of the GuidedAction in array.
+ */
+ public void notifyActionChanged(int position) {
+ if (mAdapter != null) {
+ mAdapter.notifyItemChanged(position);
+ }
+ }
+
+ /**
* Returns the view corresponding to the action at the indicated position in the list of
* actions for this fragment.
* @param position The integer position of the action of interest.
@@ -294,7 +699,9 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
* action is not currently onscreen.
*/
public View getActionItemView(int position) {
- return mListView.findViewHolderForPosition(position).itemView;
+ final RecyclerView.ViewHolder holder = mActionsStylist.getActionsGridView()
+ .findViewHolderForPosition(position);
+ return holder == null ? null : holder.itemView;
}
/**
@@ -302,7 +709,7 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
* @param position The integer position of the action of interest.
*/
public void setSelectedActionPosition(int position) {
- mListView.setSelectedPosition(position);
+ mActionsStylist.getActionsGridView().setSelectedPosition(position);
}
/**
@@ -310,7 +717,126 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
* @return position The integer position of the currently selected action.
*/
public int getSelectedActionPosition() {
- return mListView.getSelectedPosition();
+ return mActionsStylist.getActionsGridView().getSelectedPosition();
+ }
+
+ /**
+ * Called by Constructor to provide fragment transitions. The default implementation assigns
+ * transitions based on {@link #getUiStyle()}:
+ * <ul>
+ * <li> {@link #UI_STYLE_REPLACE} Slide from/to end(right) for enter transition, slide from/to
+ * start(left) for exit transition, shared element enter transition is set to ChangeBounds.
+ * <li> {@link #UI_STYLE_ENTRANCE} Enter transition is set to slide from both sides, exit
+ * transition is same as {@link #UI_STYLE_REPLACE}, no shared element enter transition.
+ * <li> {@link #UI_STYLE_ACTIVITY_ROOT} Enter transition is set to null and app should rely on
+ * activity transition, exit transition is same as {@link #UI_STYLE_REPLACE}, no shared element
+ * enter transition.
+ * </ul>
+ * <p>
+ * The default implementation heavily relies on {@link GuidedActionsStylist} and
+ * {@link GuidanceStylist} layout, app may override this method when modifying the default
+ * layout of {@link GuidedActionsStylist} or {@link GuidanceStylist}.
+ * <p>
+ * TIP: because the fragment view is removed during fragment transition, in general app cannot
+ * use two Visibility transition together. Workaround is to create your own Visibility
+ * transition that controls multiple animators (e.g. slide and fade animation in one Transition
+ * class).
+ */
+ protected void onProvideFragmentTransitions() {
+ if (Build.VERSION.SDK_INT >= 21) {
+ final int uiStyle = getUiStyle();
+ if (uiStyle == UI_STYLE_REPLACE) {
+ Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END);
+ TransitionHelper.exclude(enterTransition, R.id.guidedstep_background, true);
+ TransitionHelper.setEnterTransition(this, enterTransition);
+
+ Object changeBounds = TransitionHelper.createChangeBounds(false);
+ TransitionHelper.setSharedElementEnterTransition(this, changeBounds);
+ } else if (uiStyle == UI_STYLE_ENTRANCE) {
+ Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN |
+ TransitionHelper.FADE_OUT);
+ TransitionHelper.include(fade, R.id.guidedstep_background);
+ Object slide = TransitionHelper.createFadeAndShortSlide(Gravity.END |
+ Gravity.START);
+ TransitionHelper.include(slide, R.id.content_fragment);
+ TransitionHelper.include(slide, R.id.action_fragment_root);
+ Object enterTransition = TransitionHelper.createTransitionSet(false);
+ TransitionHelper.addTransition(enterTransition, fade);
+ TransitionHelper.addTransition(enterTransition, slide);
+ TransitionHelper.setEnterTransition(this, enterTransition);
+
+ // No shared element transition
+ TransitionHelper.setSharedElementEnterTransition(this, null);
+ } else if (uiStyle == UI_STYLE_ACTIVITY_ROOT) {
+ // for Activity root, we dont need enter transition, use activity transition
+ TransitionHelper.setEnterTransition(this, null);
+ // No shared element transition
+ TransitionHelper.setSharedElementEnterTransition(this, null);
+ }
+ // exitTransition is same for all style
+ Object exitTransition = TransitionHelper.createFadeAndShortSlide(Gravity.START);
+ TransitionHelper.exclude(exitTransition, R.id.guidedstep_background, true);
+ TransitionHelper.setExitTransition(this, exitTransition);
+ }
+ }
+
+ /**
+ * Called by onCreateView to inflate background view. Default implementation loads view
+ * from {@link R.layout#lb_guidedstep_background} which holds a reference to
+ * guidedStepBackground.
+ * @param inflater LayoutInflater to load background view.
+ * @param container Parent view of background view.
+ * @param savedInstanceState
+ * @return Created background view or null if no background.
+ */
+ public View onCreateBackgroundView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.lb_guidedstep_background, container, false);
+ }
+
+ /**
+ * Set UI style to fragment arguments. Default value is {@link #UI_STYLE_ENTRANCE} when fragment
+ * is first initialized. UI style is used to choose different fragment transition animations and
+ * determine if this is the first GuidedStepFragment on backstack. In most cases app does not
+ * directly call this method, app calls helper function
+ * {@link #add(FragmentManager, GuidedStepFragment, int)}. However if the app creates Fragment
+ * transaction and controls backstack by itself, it would need call setUiStyle() to select the
+ * fragment transition to use.
+ *
+ * @param style {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
+ * {@link #UI_STYLE_ENTRANCE}.
+ */
+ public void setUiStyle(int style) {
+ int oldStyle = getUiStyle();
+ Bundle arguments = getArguments();
+ boolean isNew = false;
+ if (arguments == null) {
+ arguments = new Bundle();
+ isNew = true;
+ }
+ arguments.putInt(EXTRA_UI_STYLE, style);
+ // call setArgument() will validate if the fragment is already added.
+ if (isNew) {
+ setArguments(arguments);
+ }
+ if (style != oldStyle) {
+ onProvideFragmentTransitions();
+ }
+ }
+
+ /**
+ * Read UI style from fragment arguments. Default value is {@link #UI_STYLE_ENTRANCE} when
+ * fragment is first initialized. UI style is used to choose different fragment transition
+ * animations and determine if this is the first GuidedStepFragment on backstack.
+ *
+ * @return {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
+ * {@link #UI_STYLE_ENTRANCE}.
+ * @see #onProvideFragmentTransitions()
+ */
+ public int getUiStyle() {
+ Bundle b = getArguments();
+ if (b == null) return UI_STYLE_ENTRANCE;
+ return b.getInt(EXTRA_UI_STYLE, UI_STYLE_ENTRANCE);
}
/**
@@ -320,16 +846,34 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (DEBUG) Log.v(TAG, "onCreate");
+ // Set correct transition from saved arguments.
+ onProvideFragmentTransitions();
Bundle state = (savedInstanceState != null) ? savedInstanceState : getArguments();
if (state != null) {
if (mSelectedIndex == -1) {
mSelectedIndex = state.getInt(EXTRA_ACTION_SELECTED_INDEX, -1);
}
- mEntryTransitionEnabled = state.getBoolean(EXTRA_ACTION_ENTRY_TRANSITION_ENABLED, true);
- mEntryTransitionPerformed = state.getBoolean(EXTRA_ENTRY_TRANSITION_PERFORMED, false);
}
- mActions.clear();
- onCreateActions(mActions, savedInstanceState);
+ ArrayList<GuidedAction> actions = new ArrayList<GuidedAction>();
+ onCreateActions(actions, savedInstanceState);
+ setActions(actions);
+ ArrayList<GuidedAction> buttonActions = new ArrayList<GuidedAction>();
+ onCreateButtonActions(buttonActions, savedInstanceState);
+ setButtonActions(buttonActions);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onDestroyView() {
+ mGuidanceStylist.onDestroyView();
+ mActionsStylist.onDestroyView();
+ mButtonActionsStylist.onDestroyView();
+ mAdapter = null;
+ mButtonAdapter = null;
+ mAdapterGroup = null;
+ super.onDestroyView();
}
/**
@@ -343,9 +887,10 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
resolveTheme();
inflater = getThemeInflater(inflater);
- View v = inflater.inflate(R.layout.lb_guidedstep_fragment, container, false);
- ViewGroup guidanceContainer = (ViewGroup) v.findViewById(R.id.content_fragment);
- ViewGroup actionContainer = (ViewGroup) v.findViewById(R.id.action_fragment);
+ ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_guidedstep_fragment,
+ container, false);
+ ViewGroup guidanceContainer = (ViewGroup) root.findViewById(R.id.content_fragment);
+ ViewGroup actionContainer = (ViewGroup) root.findViewById(R.id.action_fragment);
Guidance guidance = onCreateGuidance(savedInstanceState);
View guidanceView = mGuidanceStylist.onCreateView(inflater, guidanceContainer, guidance);
@@ -354,15 +899,77 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
View actionsView = mActionsStylist.onCreateView(inflater, actionContainer);
actionContainer.addView(actionsView);
+ View buttonActionsView = mButtonActionsStylist.onCreateView(inflater, actionContainer);
+ mButtonActionsStylist.setAsButtonActions();
+ actionContainer.addView(buttonActionsView);
+
+ GuidedActionAdapter.EditListener editListener = new GuidedActionAdapter.EditListener() {
+
+ @Override
+ public void onImeOpen() {
+ runImeAnimations(true);
+ }
+
+ @Override
+ public void onImeClose() {
+ runImeAnimations(false);
+ }
+
+ @Override
+ public long onGuidedActionEdited(GuidedAction action) {
+ return GuidedStepFragment.this.onGuidedActionEditedAndProceed(action);
+ }
+ };
+
mAdapter = new GuidedActionAdapter(mActions, this, this, mActionsStylist);
+ mButtonAdapter = new GuidedActionAdapter(mButtonActions, this, this, mButtonActionsStylist);
+ mAdapterGroup = new GuidedActionAdapterGroup();
+ mAdapterGroup.addAdpter(mAdapter);
+ mAdapterGroup.addAdpter(mButtonAdapter);
+ mAdapterGroup.setEditListener(editListener);
+
+ mActionsStylist.getActionsGridView().setAdapter(mAdapter);
+ mButtonActionsStylist.getActionsGridView().setAdapter(mButtonAdapter);
+ if (mButtonActions.size() == 0) {
+ // when there is no button actions, we dont need show the second panel, but keep
+ // the width zero to run ChangeBounds transition.
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+ buttonActionsView.getLayoutParams();
+ lp.weight = 0;
+ buttonActionsView.setLayoutParams(lp);
+ } else {
+ // when there are two actions panel, we need adjust the weight of action to
+ // guidedActionContentWidthWeightTwoPanels.
+ Context ctx = mThemeWrapper != null ? mThemeWrapper : getActivity();
+ TypedValue typedValue = new TypedValue();
+ if (ctx.getTheme().resolveAttribute(R.attr.guidedActionContentWidthWeightTwoPanels,
+ typedValue, true)) {
+ View actionsRoot = root.findViewById(R.id.action_fragment_root);
+ float weight = typedValue.getFloat();
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) actionsRoot
+ .getLayoutParams();
+ lp.weight = weight;
+ actionsRoot.setLayoutParams(lp);
+ }
+ }
- mListView = mActionsStylist.getActionsGridView();
- mListView.setAdapter(mAdapter);
int pos = (mSelectedIndex >= 0 && mSelectedIndex < mActions.size()) ?
mSelectedIndex : getFirstCheckedAction();
- mListView.setSelectedPosition(pos);
+ setSelectedActionPosition(pos);
+
+ setSelectedButtonActionPosition(0);
- return v;
+ View backgroundView = onCreateBackgroundView(inflater, root, savedInstanceState);
+ if (backgroundView != null) {
+ root.addView(backgroundView, 0);
+ }
+ return root;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mActionsStylist.getActionsGridView().requestFocus();
}
/**
@@ -372,84 +979,70 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(EXTRA_ACTION_SELECTED_INDEX,
- (mListView != null) ? getSelectedActionPosition() : mSelectedIndex);
- outState.putBoolean(EXTRA_ACTION_ENTRY_TRANSITION_ENABLED, mEntryTransitionEnabled);
- outState.putBoolean(EXTRA_ENTRY_TRANSITION_PERFORMED, mEntryTransitionPerformed);
+ (mActionsStylist.getActionsGridView() != null) ?
+ getSelectedActionPosition() : mSelectedIndex);
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void onStart() {
- if (DEBUG) Log.v(TAG, "onStart");
- super.onStart();
- if (isEntryTransitionEnabled() && !mEntryTransitionPerformed) {
- mEntryTransitionPerformed = true;
- performEntryTransition();
- }
+ private static boolean isGuidedStepTheme(Context context) {
+ int resId = R.attr.guidedStepThemeFlag;
+ TypedValue typedValue = new TypedValue();
+ boolean found = context.getTheme().resolveAttribute(resId, typedValue, true);
+ if (DEBUG) Log.v(TAG, "Found guided step theme flag? " + found);
+ return found && typedValue.type == TypedValue.TYPE_INT_BOOLEAN && typedValue.data != 0;
}
/**
- * {@inheritDoc}
+ * Convenient method to close GuidedStepFragments on top of other content or finish Activity if
+ * GuidedStepFragments were started in a separate activity. Pops all stack entries including
+ * {@link #UI_STYLE_ENTRANCE}; if {@link #UI_STYLE_ENTRANCE} is not found, finish the activity.
+ * Note that this method must be paired with {@link #add(FragmentManager, GuidedStepFragment,
+ * int)} which sets up the stack entry name for finding which fragment we need to pop back to.
*/
- @Override
- public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
- if (DEBUG) Log.v(TAG, "onCreateAnimator: " + transit + " " + enter + " " + nextAnim);
- View mainView = getView();
-
- ArrayList<Animator> animators = new ArrayList<Animator>();
- switch (nextAnim) {
- case ANIMATION_FRAGMENT_ENTER:
- mGuidanceStylist.onFragmentEnter(animators);
- mActionsStylist.onFragmentEnter(animators);
- break;
- case ANIMATION_FRAGMENT_EXIT:
- mGuidanceStylist.onFragmentExit(animators);
- mActionsStylist.onFragmentExit(animators);
- break;
- case ANIMATION_FRAGMENT_ENTER_POP:
- mGuidanceStylist.onFragmentReenter(animators);
- mActionsStylist.onFragmentReenter(animators);
- break;
- case ANIMATION_FRAGMENT_EXIT_POP:
- mGuidanceStylist.onFragmentReturn(animators);
- mActionsStylist.onFragmentReturn(animators);
- break;
- default:
- return super.onCreateAnimator(transit, enter, nextAnim);
+ public void finishGuidedStepFragments() {
+ final FragmentManager fragmentManager = getFragmentManager();
+ final int entryCount = fragmentManager.getBackStackEntryCount();
+ if (entryCount > 0) {
+ for (int i = entryCount - 1; i >= 0; i--) {
+ BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
+ if (isUiStyleEntrance(entry.getName())) {
+ GuidedStepFragment top = getCurrentGuidedStepFragment(fragmentManager);
+ if (top != null) {
+ top.setUiStyle(UI_STYLE_ENTRANCE);
+ }
+ fragmentManager.popBackStack(entry.getId(),
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ return;
+ }
+ }
}
-
- mEntryTransitionPerformed = true;
- return createDummyAnimator(mainView, animators);
+ ActivityCompat.finishAfterTransition(getActivity());
}
/**
- * Returns whether entry transitions are enabled for this fragment.
- * @return Whether entry transitions are enabled for this fragment.
+ * Convenient method to pop to fragment with Given class.
+ * @param guidedStepFragmentClass Name of the Class of GuidedStepFragment to pop to.
+ * @param flags Either 0 or {@link FragmentManager#POP_BACK_STACK_INCLUSIVE}.
*/
- protected boolean isEntryTransitionEnabled() {
- return mEntryTransitionEnabled;
- }
-
- /**
- * Sets whether entry transitions are enabled for this fragment.
- * @param enabled Whether to enable entry transitions for this fragment.
- */
- protected void setEntryTransitionEnabled(boolean enabled) {
- mEntryTransitionEnabled = enabled;
- }
-
- private boolean isGuidedStepTheme(Context context) {
- int resId = R.attr.guidedStepThemeFlag;
- TypedValue typedValue = new TypedValue();
- boolean found = context.getTheme().resolveAttribute(resId, typedValue, true);
- if (DEBUG) Log.v(TAG, "Found guided step theme flag? " + found);
- return found && typedValue.type == TypedValue.TYPE_INT_BOOLEAN && typedValue.data != 0;
+ public void popBackStackToGuidedStepFragment(Class guidedStepFragmentClass, int flags) {
+ if (!GuidedStepFragment.class.isAssignableFrom(guidedStepFragmentClass)) {
+ return;
+ }
+ final FragmentManager fragmentManager = getFragmentManager();
+ final int entryCount = fragmentManager.getBackStackEntryCount();
+ String className = guidedStepFragmentClass.getName();
+ if (entryCount > 0) {
+ for (int i = entryCount - 1; i >= 0; i--) {
+ BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
+ String entryClassName = getGuidedStepFragmentClassName(entry.getName());
+ if (className.equals(entryClassName)) {
+ fragmentManager.popBackStack(entry.getId(), flags);
+ return;
+ }
+ }
+ }
}
private void resolveTheme() {
- boolean hasThemeReference = true;
// Look up the guidedStepTheme in the currently specified theme. If it exists,
// replace the theme with its value.
Activity activity = getActivity();
@@ -461,15 +1054,21 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
boolean found = activity.getTheme().resolveAttribute(resId, typedValue, true);
if (DEBUG) Log.v(TAG, "Found guided step theme reference? " + found);
if (found) {
- if (isGuidedStepTheme(new ContextThemeWrapper(activity, typedValue.resourceId))) {
+ ContextThemeWrapper themeWrapper =
+ new ContextThemeWrapper(activity, typedValue.resourceId);
+ if (isGuidedStepTheme(themeWrapper)) {
mTheme = typedValue.resourceId;
+ mThemeWrapper = themeWrapper;
} else {
found = false;
+ mThemeWrapper = null;
}
}
if (!found) {
Log.e(TAG, "GuidedStepFragment does not have an appropriate theme set.");
}
+ } else if (mTheme != -1) {
+ mThemeWrapper = new ContextThemeWrapper(activity, mTheme);
}
}
@@ -477,8 +1076,7 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
if (mTheme == -1) {
return inflater;
} else {
- Context ctw = new ContextThemeWrapper(getActivity(), mTheme);
- return inflater.cloneInContext(ctw);
+ return inflater.cloneInContext(mThemeWrapper);
}
}
@@ -491,41 +1089,20 @@ public class GuidedStepFragment extends Fragment implements GuidedActionAdapter.
return 0;
}
- private void performEntryTransition() {
- if (DEBUG) Log.v(TAG, "performEntryTransition");
- final View mainView = getView();
-
- mainView.setVisibility(View.INVISIBLE);
-
+ private void runImeAnimations(boolean entering) {
ArrayList<Animator> animators = new ArrayList<Animator>();
- mGuidanceStylist.onActivityEnter(animators);
- mActionsStylist.onActivityEnter(animators);
-
- final Animator animator = createDummyAnimator(mainView, animators);
-
- // We need to defer the animation until the first layout has occurred, as we don't yet
- // know the final locations of views.
- mainView.getViewTreeObserver().addOnGlobalLayoutListener(
- new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- mainView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
- if (!isAdded()) {
- // We have been detached before this could run,
- // so just bail
- return;
- }
-
- mainView.setVisibility(View.VISIBLE);
- animator.start();
- }
- });
- }
-
- private Animator createDummyAnimator(final View v, ArrayList<Animator> animators) {
- final AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(animators);
- return new UntargetableAnimatorSet(animatorSet);
+ if (entering) {
+ mGuidanceStylist.onImeAppearing(animators);
+ mActionsStylist.onImeAppearing(animators);
+ mButtonActionsStylist.onImeAppearing(animators);
+ } else {
+ mGuidanceStylist.onImeDisappearing(animators);
+ mActionsStylist.onImeDisappearing(animators);
+ mButtonActionsStylist.onImeDisappearing(animators);
+ }
+ AnimatorSet set = new AnimatorSet();
+ set.playTogether(animators);
+ set.start();
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
new file mode 100644
index 0000000000..ad186ff1b7
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
@@ -0,0 +1,1110 @@
+/* This file is auto-generated from GuidedStepFragment.java. DO NOT MODIFY. */
+
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.app;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentManager.BackStackEntry;
+import android.support.v4.app.FragmentTransaction;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v17.leanback.transition.TransitionHelper;
+import android.support.v17.leanback.R;
+import android.support.v17.leanback.widget.GuidanceStylist;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidedActionsStylist;
+import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v4.app.ActivityCompat;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A GuidedStepSupportFragment is used to guide the user through a decision or series of decisions.
+ * It is composed of a guidance view on the left and a view on the right containing a list of
+ * possible actions.
+ * <p>
+ * <h3>Basic Usage</h3>
+ * <p>
+ * Clients of GuidedStepSupportFragment must create a custom subclass to attach to their Activities.
+ * This custom subclass provides the information necessary to construct the user interface and
+ * respond to user actions. At a minimum, subclasses should override:
+ * <ul>
+ * <li>{@link #onCreateGuidance}, to provide instructions to the user</li>
+ * <li>{@link #onCreateActions}, to provide a set of {@link GuidedAction}s the user can take</li>
+ * <li>{@link #onGuidedActionClicked}, to respond to those actions</li>
+ * </ul>
+ * <p>
+ * Clients use following helper functions to add GuidedStepSupportFragment to Activity or FragmentManager:
+ * <ul>
+ * <li>{@link #addAsRoot(FragmentActivity, GuidedStepSupportFragment, int)}, to be called during Activity onCreate,
+ * adds GuidedStepSupportFragment as the first Fragment in activity.</li>
+ * <li>{@link #add(FragmentManager, GuidedStepSupportFragment)} or {@link #add(FragmentManager,
+ * GuidedStepSupportFragment, int)}, to add GuidedStepSupportFragment on top of existing Fragments or
+ * replacing existing GuidedStepSupportFragment when moving forward to next step.</li>
+ * <li>{@link #finishGuidedStepSupportFragments()} can either finish the activity or pop all
+ * GuidedStepSupportFragment from stack.
+ * <li>If app chooses not to use the helper function, it is the app's responsibility to call
+ * {@link #setUiStyle(int)} to select fragment transition and remember the stack entry where it
+ * need pops to.
+ * </ul>
+ * <h3>Theming and Stylists</h3>
+ * <p>
+ * GuidedStepSupportFragment delegates its visual styling to classes called stylists. The {@link
+ * GuidanceStylist} is responsible for the left guidance view, while the {@link
+ * GuidedActionsStylist} is responsible for the right actions view. The stylists use theme
+ * attributes to derive values associated with the presentation, such as colors, animations, etc.
+ * Most simple visual aspects of GuidanceStylist and GuidedActionsStylist can be customized
+ * via theming; see their documentation for more information.
+ * <p>
+ * GuidedStepSupportFragments must have access to an appropriate theme in order for the stylists to
+ * function properly. Specifically, the fragment must receive {@link
+ * android.support.v17.leanback.R.style#Theme_Leanback_GuidedStep}, or a theme whose parent is
+ * is set to that theme. Themes can be provided in one of three ways:
+ * <ul>
+ * <li>The simplest way is to set the theme for the host Activity to the GuidedStep theme or a
+ * theme that derives from it.</li>
+ * <li>If the Activity already has a theme and setting its parent theme is inconvenient, the
+ * existing Activity theme can have an entry added for the attribute {@link
+ * android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepTheme}. If present,
+ * this theme will be used by GuidedStepSupportFragment as an overlay to the Activity's theme.</li>
+ * <li>Finally, custom subclasses of GuidedStepSupportFragment may provide a theme through the {@link
+ * #onProvideTheme} method. This can be useful if a subclass is used across multiple
+ * Activities.</li>
+ * </ul>
+ * <p>
+ * If the theme is provided in multiple ways, the onProvideTheme override has priority, followed by
+ * the Activty's theme. (Themes whose parent theme is already set to the guided step theme do not
+ * need to set the guidedStepTheme attribute; if set, it will be ignored.)
+ * <p>
+ * If themes do not provide enough customizability, the stylists themselves may be subclassed and
+ * provided to the GuidedStepSupportFragment through the {@link #onCreateGuidanceStylist} and {@link
+ * #onCreateActionsStylist} methods. The stylists have simple hooks so that subclasses
+ * may override layout files; subclasses may also have more complex logic to determine styling.
+ * <p>
+ * <h3>Guided sequences</h3>
+ * <p>
+ * GuidedStepSupportFragments can be grouped together to provide a guided sequence. GuidedStepSupportFragments
+ * grouped as a sequence use custom animations provided by {@link GuidanceStylist} and
+ * {@link GuidedActionsStylist} (or subclasses) during transitions between steps. Clients
+ * should use {@link #add} to place subsequent GuidedFragments onto the fragment stack so that
+ * custom animations are properly configured. (Custom animations are triggered automatically when
+ * the fragment stack is subsequently popped by any normal mechanism.)
+ * <p>
+ * <i>Note: Currently GuidedStepSupportFragments grouped in this way must all be defined programmatically,
+ * rather than in XML. This restriction may be removed in the future.</i>
+ *
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepTheme
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepBackground
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidthWeight
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidthWeightTwoPanels
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsBackground
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsBackgroundDark
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsElevation
+ * @see GuidanceStylist
+ * @see GuidanceStylist.Guidance
+ * @see GuidedAction
+ * @see GuidedActionsStylist
+ */
+public class GuidedStepSupportFragment extends Fragment implements GuidedActionAdapter.ClickListener,
+ GuidedActionAdapter.FocusListener {
+
+ private static final String TAG_LEAN_BACK_ACTIONS_FRAGMENT = "leanBackGuidedStepSupportFragment";
+ private static final String EXTRA_ACTION_SELECTED_INDEX = "selectedIndex";
+
+ private static final String ENTRY_NAME_REPLACE = "GuidedStepDefault";
+
+ private static final String ENTRY_NAME_ENTRANCE = "GuidedStepEntrance";
+
+ /**
+ * Fragment argument name for UI style. The argument value is persisted in fragment state.
+ * The value is initially {@link #UI_STYLE_ENTRANCE} and might be changed in one of the three
+ * helper functions:
+ * <ul>
+ * <li>{@link #addAsRoot(FragmentActivity, GuidedStepSupportFragment, int)}</li>
+ * <li>{@link #add(FragmentManager, GuidedStepSupportFragment)} or {@link #add(FragmentManager,
+ * GuidedStepSupportFragment, int)}</li>
+ * </ul>
+ * <p>
+ * Argument value can be either:
+ * <ul>
+ * <li>{@link #UI_STYLE_REPLACE}</li>
+ * <li>{@link #UI_STYLE_ENTRANCE}</li>
+ * <li>{@link #UI_STYLE_ACTIVITY_ROOT}</li>
+ * </ul>
+ */
+ public static final String EXTRA_UI_STYLE = "uiStyle";
+
+ /**
+ * This is the case that we use GuidedStepSupportFragment to replace another existing
+ * GuidedStepSupportFragment when moving forward to next step. Default behavior of this style is:
+ * <ul>
+ * <li>Enter transition slides in from END(right), exit transition same as
+ * {@link #UI_STYLE_ENTRANCE}.
+ * </li>
+ * </ul>
+ */
+ public static final int UI_STYLE_REPLACE = 0;
+
+ /**
+ * Default value for argument {@link #EXTRA_UI_STYLE}. The default value is assigned in
+ * GuidedStepSupportFragment constructor. This is the case that we show GuidedStepSupportFragment on top of
+ * other content. The default behavior of this style:
+ * <ul>
+ * <li>Enter transition slides in from two sides, exit transition slide out to START(left).
+ * Background will be faded in. Note: Changing exit transition by UI style is not working
+ * because fragment transition asks for exit transition before UI style is restored in Fragment
+ * .onCreate().</li>
+ * </ul>
+ */
+ public static final int UI_STYLE_ENTRANCE = 1;
+
+ /**
+ * One possible value of argument {@link #EXTRA_UI_STYLE}. This is the case that we show first
+ * GuidedStepSupportFragment in a separate activity. The default behavior of this style:
+ * <ul>
+ * <li>Enter transition is assigned null (will rely on activity transition), exit transition is
+ * same as {@link #UI_STYLE_ENTRANCE}. Note: Changing exit transition by UI style is not working
+ * because fragment transition asks for exit transition before UI style is restored in
+ * Fragment.onCreate().</li>
+ * </ul>
+ */
+ public static final int UI_STYLE_ACTIVITY_ROOT = 2;
+
+ private static final String TAG = "GuidedStepSupportFragment";
+ private static final boolean DEBUG = false;
+
+ private int mTheme;
+ private ContextThemeWrapper mThemeWrapper;
+ private GuidanceStylist mGuidanceStylist;
+ private GuidedActionsStylist mActionsStylist;
+ private GuidedActionsStylist mButtonActionsStylist;
+ private GuidedActionAdapter mAdapter;
+ private GuidedActionAdapter mButtonAdapter;
+ private GuidedActionAdapterGroup mAdapterGroup;
+ private List<GuidedAction> mActions = new ArrayList<GuidedAction>();
+ private List<GuidedAction> mButtonActions = new ArrayList<GuidedAction>();
+ private int mSelectedIndex = -1;
+ private int mButtonSelectedIndex = -1;
+
+ public GuidedStepSupportFragment() {
+ // We need to supply the theme before any potential call to onInflate in order
+ // for the defaulting to work properly.
+ mTheme = onProvideTheme();
+ mGuidanceStylist = onCreateGuidanceStylist();
+ mActionsStylist = onCreateActionsStylist();
+ mButtonActionsStylist = onCreateButtonActionsStylist();
+ onProvideFragmentTransitions();
+ }
+
+ /**
+ * Creates the presenter used to style the guidance panel. The default implementation returns
+ * a basic GuidanceStylist.
+ * @return The GuidanceStylist used in this fragment.
+ */
+ public GuidanceStylist onCreateGuidanceStylist() {
+ return new GuidanceStylist();
+ }
+
+ /**
+ * Creates the presenter used to style the guided actions panel. The default implementation
+ * returns a basic GuidedActionsStylist.
+ * @return The GuidedActionsStylist used in this fragment.
+ */
+ public GuidedActionsStylist onCreateActionsStylist() {
+ return new GuidedActionsStylist();
+ }
+
+ /**
+ * Creates the presenter used to style a sided actions panel for button only.
+ * The default implementation returns a basic GuidedActionsStylist.
+ * @return The GuidedActionsStylist used in this fragment.
+ */
+ public GuidedActionsStylist onCreateButtonActionsStylist() {
+ return new GuidedActionsStylist();
+ }
+
+ /**
+ * Returns the theme used for styling the fragment. The default returns -1, indicating that the
+ * host Activity's theme should be used.
+ * @return The theme resource ID of the theme to use in this fragment, or -1 to use the
+ * host Activity's theme.
+ */
+ public int onProvideTheme() {
+ return -1;
+ }
+
+ /**
+ * Returns the information required to provide guidance to the user. This hook is called during
+ * {@link #onCreateView}. May be overridden to return a custom subclass of {@link
+ * GuidanceStylist.Guidance} for use in a subclass of {@link GuidanceStylist}. The default
+ * returns a Guidance object with empty fields; subclasses should override.
+ * @param savedInstanceState The saved instance state from onCreateView.
+ * @return The Guidance object representing the information used to guide the user.
+ */
+ public @NonNull Guidance onCreateGuidance(Bundle savedInstanceState) {
+ return new Guidance("", "", "", null);
+ }
+
+ /**
+ * Fills out the set of actions available to the user. This hook is called during {@link
+ * #onCreate}. The default leaves the list of actions empty; subclasses should override.
+ * @param actions A non-null, empty list ready to be populated.
+ * @param savedInstanceState The saved instance state from onCreate.
+ */
+ public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
+ }
+
+ /**
+ * Fills out the set of actions shown at right available to the user. This hook is called during
+ * {@link #onCreate}. The default leaves the list of actions empty; subclasses may override.
+ * @param actions A non-null, empty list ready to be populated.
+ * @param savedInstanceState The saved instance state from onCreate.
+ */
+ public void onCreateButtonActions(@NonNull List<GuidedAction> actions,
+ Bundle savedInstanceState) {
+ }
+
+ /**
+ * Callback invoked when an action is taken by the user. Subclasses should override in
+ * order to act on the user's decisions.
+ * @param action The chosen action.
+ */
+ @Override
+ public void onGuidedActionClicked(GuidedAction action) {
+ }
+
+ /**
+ * Callback invoked when an action is focused (made to be the current selection) by the user.
+ */
+ @Override
+ public void onGuidedActionFocused(GuidedAction action) {
+ }
+
+ /**
+ * Callback invoked when an action's title or description has been edited.
+ * Override {@link #onGuidedActionEditedAndProceed(GuidedAction)} instead of app wants to
+ * control the next action to focus on.
+ */
+ public void onGuidedActionEdited(GuidedAction action) {
+ }
+
+ /**
+ * Callback invoked when an action's title or description has been edited. Default
+ * implementation calls {@link #onGuidedActionEdited(GuidedAction)} and returns
+ * {@link GuidedAction#ACTION_ID_NEXT}.
+ *
+ * @param action The action that has been edited.
+ * @return ID of the action will be focused or {@link GuidedAction#ACTION_ID_NEXT},
+ * {@link GuidedAction#ACTION_ID_CURRENT}.
+ */
+ public long onGuidedActionEditedAndProceed(GuidedAction action) {
+ onGuidedActionEdited(action);
+ return GuidedAction.ACTION_ID_NEXT;
+ }
+
+ /**
+ * Adds the specified GuidedStepSupportFragment to the fragment stack, replacing any existing
+ * GuidedStepSupportFragments in the stack, and configuring the fragment-to-fragment custom
+ * transitions. A backstack entry is added, so the fragment will be dismissed when BACK key
+ * is pressed.
+ * <li>If current fragment on stack is GuidedStepSupportFragment: assign {@link #UI_STYLE_REPLACE}
+ * <li>If current fragment on stack is not GuidedStepSupportFragment: assign {@link #UI_STYLE_ENTRANCE}
+ * <p>
+ * Note: currently fragments added using this method must be created programmatically rather
+ * than via XML.
+ * @param fragmentManager The FragmentManager to be used in the transaction.
+ * @param fragment The GuidedStepSupportFragment to be inserted into the fragment stack.
+ * @return The ID returned by the call FragmentTransaction.replace.
+ */
+ public static int add(FragmentManager fragmentManager, GuidedStepSupportFragment fragment) {
+ return add(fragmentManager, fragment, android.R.id.content);
+ }
+
+ /**
+ * Adds the specified GuidedStepSupportFragment to the fragment stack, replacing any existing
+ * GuidedStepSupportFragments in the stack, and configuring the fragment-to-fragment custom
+ * transitions. A backstack entry is added, so the fragment will be dismissed when BACK key
+ * is pressed.
+ * <li>If current fragment on stack is GuidedStepSupportFragment: assign {@link #UI_STYLE_REPLACE} and
+ * {@link #onAddSharedElementTransition(FragmentTransaction, GuidedStepSupportFragment)} will be called
+ * to perform shared element transition between GuidedStepSupportFragments.
+ * <li>If current fragment on stack is not GuidedStepSupportFragment: assign {@link #UI_STYLE_ENTRANCE}
+ * <p>
+ * Note: currently fragments added using this method must be created programmatically rather
+ * than via XML.
+ * @param fragmentManager The FragmentManager to be used in the transaction.
+ * @param fragment The GuidedStepSupportFragment to be inserted into the fragment stack.
+ * @param id The id of container to add GuidedStepSupportFragment, can be android.R.id.content.
+ * @return The ID returned by the call FragmentTransaction.replace.
+ */
+ public static int add(FragmentManager fragmentManager, GuidedStepSupportFragment fragment, int id) {
+ GuidedStepSupportFragment current = getCurrentGuidedStepSupportFragment(fragmentManager);
+ boolean inGuidedStep = current != null;
+ FragmentTransaction ft = fragmentManager.beginTransaction();
+
+ fragment.setUiStyle(inGuidedStep ? UI_STYLE_REPLACE : UI_STYLE_ENTRANCE);
+ ft.addToBackStack(fragment.generateStackEntryName());
+ if (current != null) {
+ fragment.onAddSharedElementTransition(ft, current);
+ }
+ return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
+ }
+
+ /**
+ * Called when this fragment is added to FragmentTransaction with {@link #UI_STYLE_REPLACE} (aka
+ * when the GuidedStepSupportFragment replacing an existing GuidedStepSupportFragment). Default implementation
+ * establishes connections between action background views to morph action background bounds
+ * change from disappearing GuidedStepSupportFragment into this GuidedStepSupportFragment. The default
+ * implementation heavily relies on {@link GuidedActionsStylist}'s layout, app may override this
+ * method when modifying the default layout of {@link GuidedActionsStylist}.
+ *
+ * @see GuidedActionsStylist
+ * @see #onProvideFragmentTransitions()
+ * @param ft The FragmentTransaction to add shared element.
+ * @param disappearing The disappearing fragment.
+ */
+ protected void onAddSharedElementTransition(FragmentTransaction ft, GuidedStepSupportFragment
+ disappearing) {
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.action_fragment_root), "action_fragment_root");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.action_fragment_background), "action_fragment_background");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.action_fragment), "action_fragment");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_root), "guidedactions_root");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_selector), "guidedactions_selector");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_content), "guidedactions_content");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_list_background), "guidedactions_list_background");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_root2), "guidedactions_root2");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_selector2), "guidedactions_selector2");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_content2), "guidedactions_content2");
+ TransitionHelper.addSharedElement(ft, disappearing.getView().findViewById(
+ R.id.guidedactions_list_background2), "guidedactions_list_background2");
+ }
+
+ /**
+ * Returns BackStackEntry name for the GuidedStepSupportFragment or empty String if no entry is
+ * associated. Note {@link #UI_STYLE_ACTIVITY_ROOT} will return empty String. The method
+ * returns undefined value if the fragment is not in FragmentManager.
+ * @return BackStackEntry name for the GuidedStepSupportFragment or empty String if no entry is
+ * associated.
+ */
+ public String generateStackEntryName() {
+ return generateStackEntryName(getUiStyle(), getClass());
+ }
+
+ /**
+ * Generates BackStackEntry name for GuidedStepSupportFragment class or empty String if no entry is
+ * associated. Note {@link #UI_STYLE_ACTIVITY_ROOT} is not allowed and returns empty String.
+ * @param uiStyle {@link #UI_STYLE_REPLACE} or {@link #UI_STYLE_ENTRANCE}
+ * @return BackStackEntry name for the GuidedStepSupportFragment or empty String if no entry is
+ * associated.
+ */
+ public static String generateStackEntryName(int uiStyle, Class guidedStepFragmentClass) {
+ if (!GuidedStepSupportFragment.class.isAssignableFrom(guidedStepFragmentClass)) {
+ return "";
+ }
+ switch (uiStyle) {
+ case UI_STYLE_REPLACE:
+ return ENTRY_NAME_REPLACE + guidedStepFragmentClass.getName();
+ case UI_STYLE_ENTRANCE:
+ return ENTRY_NAME_ENTRANCE + guidedStepFragmentClass.getName();
+ case UI_STYLE_ACTIVITY_ROOT:
+ default:
+ return "";
+ }
+ }
+
+ /**
+ * Returns true if the backstack represents GuidedStepSupportFragment with {@link #UI_STYLE_ENTRANCE};
+ * false otherwise.
+ * @param backStackEntryName Name of BackStackEntry.
+ * @return True if the backstack represents GuidedStepSupportFragment with {@link #UI_STYLE_ENTRANCE};
+ * false otherwise.
+ */
+ public static boolean isUiStyleEntrance(String backStackEntryName) {
+ return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE);
+ }
+
+ /**
+ * Returns true if the backstack represents GuidedStepSupportFragment with {@link #UI_STYLE_REPLACE};
+ * false otherwise.
+ * @param backStackEntryName Name of BackStackEntry.
+ * @return True if the backstack represents GuidedStepSupportFragment with {@link #UI_STYLE_REPLACE};
+ * false otherwise.
+ */
+ public static boolean isUiStyleDefault(String backStackEntryName) {
+ return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_REPLACE);
+ }
+
+ /**
+ * Extract Class name from BackStackEntry name.
+ * @param backStackEntryName Name of BackStackEntry.
+ * @return Class name of GuidedStepSupportFragment.
+ */
+ public static String getGuidedStepSupportFragmentClassName(String backStackEntryName) {
+ if (backStackEntryName.startsWith(ENTRY_NAME_REPLACE)) {
+ return backStackEntryName.substring(ENTRY_NAME_REPLACE.length());
+ } else if (backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE)) {
+ return backStackEntryName.substring(ENTRY_NAME_ENTRANCE.length());
+ } else {
+ return "";
+ }
+ }
+
+ /**
+ * Adds the specified GuidedStepSupportFragment as content of Activity; no backstack entry is added so
+ * the activity will be dismissed when BACK key is pressed.
+ * {@link #UI_STYLE_ACTIVITY_ROOT} is assigned.
+ *
+ * Note: currently fragments added using this method must be created programmatically rather
+ * than via XML.
+ * @param activity The Activity to be used to insert GuidedstepFragment.
+ * @param fragment The GuidedStepSupportFragment to be inserted into the fragment stack.
+ * @param id The id of container to add GuidedStepSupportFragment, can be android.R.id.content.
+ * @return The ID returned by the call FragmentTransaction.replace.
+ */
+ public static int addAsRoot(FragmentActivity activity, GuidedStepSupportFragment fragment, int id) {
+ // Workaround b/23764120: call getDecorView() to force requestFeature of ActivityTransition.
+ activity.getWindow().getDecorView();
+
+ FragmentManager fragmentManager = activity.getSupportFragmentManager();
+ FragmentTransaction ft = fragmentManager.beginTransaction();
+ fragment.setUiStyle(UI_STYLE_ACTIVITY_ROOT);
+ return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
+ }
+
+ /**
+ * Returns the current GuidedStepSupportFragment on the fragment transaction stack.
+ * @return The current GuidedStepSupportFragment, if any, on the fragment transaction stack.
+ */
+ public static GuidedStepSupportFragment getCurrentGuidedStepSupportFragment(FragmentManager fm) {
+ Fragment f = fm.findFragmentByTag(TAG_LEAN_BACK_ACTIONS_FRAGMENT);
+ if (f instanceof GuidedStepSupportFragment) {
+ return (GuidedStepSupportFragment) f;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the GuidanceStylist that displays guidance information for the user.
+ * @return The GuidanceStylist for this fragment.
+ */
+ public GuidanceStylist getGuidanceStylist() {
+ return mGuidanceStylist;
+ }
+
+ /**
+ * Returns the GuidedActionsStylist that displays the actions the user may take.
+ * @return The GuidedActionsStylist for this fragment.
+ */
+ public GuidedActionsStylist getGuidedActionsStylist() {
+ return mActionsStylist;
+ }
+
+ /**
+ * Returns the list of button GuidedActions that the user may take in this fragment.
+ * @return The list of button GuidedActions for this fragment.
+ */
+ public List<GuidedAction> getButtonActions() {
+ return mButtonActions;
+ }
+
+ /**
+ * Find button GuidedAction by Id.
+ * @param id Id of the button action to search.
+ * @return GuidedAction object or null if not found.
+ */
+ public GuidedAction findButtonActionById(long id) {
+ int index = findButtonActionPositionById(id);
+ return index >= 0 ? mButtonActions.get(index) : null;
+ }
+
+ /**
+ * Find button GuidedAction position in array by Id.
+ * @param id Id of the button action to search.
+ * @return position of GuidedAction object in array or -1 if not found.
+ */
+ public int findButtonActionPositionById(long id) {
+ if (mButtonActions != null) {
+ for (int i = 0; i < mButtonActions.size(); i++) {
+ GuidedAction action = mButtonActions.get(i);
+ if (mButtonActions.get(i).getId() == id) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the GuidedActionsStylist that displays the button actions the user may take.
+ * @return The GuidedActionsStylist for this fragment.
+ */
+ public GuidedActionsStylist getGuidedButtonActionsStylist() {
+ return mButtonActionsStylist;
+ }
+
+ /**
+ * Sets the list of button GuidedActions that the user may take in this fragment.
+ * @param actions The list of button GuidedActions for this fragment.
+ */
+ public void setButtonActions(List<GuidedAction> actions) {
+ mButtonActions = actions;
+ if (mButtonAdapter != null) {
+ mButtonAdapter.setActions(mButtonActions);
+ }
+ }
+
+ /**
+ * Notify an button action has changed and update its UI.
+ * @param position Position of the button GuidedAction in array.
+ */
+ public void notifyButtonActionChanged(int position) {
+ if (mButtonAdapter != null) {
+ mButtonAdapter.notifyItemChanged(position);
+ }
+ }
+
+ /**
+ * Returns the view corresponding to the button action at the indicated position in the list of
+ * actions for this fragment.
+ * @param position The integer position of the button action of interest.
+ * @return The View corresponding to the button action at the indicated position, or null if
+ * that action is not currently onscreen.
+ */
+ public View getButtonActionItemView(int position) {
+ final RecyclerView.ViewHolder holder = mButtonActionsStylist.getActionsGridView()
+ .findViewHolderForPosition(position);
+ return holder == null ? null : holder.itemView;
+ }
+
+ /**
+ * Scrolls the action list to the position indicated, selecting that button action's view.
+ * @param position The integer position of the button action of interest.
+ */
+ public void setSelectedButtonActionPosition(int position) {
+ mButtonActionsStylist.getActionsGridView().setSelectedPosition(position);
+ }
+
+ /**
+ * Returns the position if the currently selected button GuidedAction.
+ * @return position The integer position of the currently selected button action.
+ */
+ public int getSelectedButtonActionPosition() {
+ return mButtonActionsStylist.getActionsGridView().getSelectedPosition();
+ }
+
+ /**
+ * Returns the list of GuidedActions that the user may take in this fragment.
+ * @return The list of GuidedActions for this fragment.
+ */
+ public List<GuidedAction> getActions() {
+ return mActions;
+ }
+
+ /**
+ * Find GuidedAction by Id.
+ * @param id Id of the action to search.
+ * @return GuidedAction object or null if not found.
+ */
+ public GuidedAction findActionById(long id) {
+ int index = findActionPositionById(id);
+ return index >= 0 ? mActions.get(index) : null;
+ }
+
+ /**
+ * Find GuidedAction position in array by Id.
+ * @param id Id of the action to search.
+ * @return position of GuidedAction object in array or -1 if not found.
+ */
+ public int findActionPositionById(long id) {
+ if (mActions != null) {
+ for (int i = 0; i < mActions.size(); i++) {
+ GuidedAction action = mActions.get(i);
+ if (mActions.get(i).getId() == id) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Sets the list of GuidedActions that the user may take in this fragment.
+ * @param actions The list of GuidedActions for this fragment.
+ */
+ public void setActions(List<GuidedAction> actions) {
+ mActions = actions;
+ if (mAdapter != null) {
+ mAdapter.setActions(mActions);
+ }
+ }
+
+ /**
+ * Notify an action has changed and update its UI.
+ * @param position Position of the GuidedAction in array.
+ */
+ public void notifyActionChanged(int position) {
+ if (mAdapter != null) {
+ mAdapter.notifyItemChanged(position);
+ }
+ }
+
+ /**
+ * Returns the view corresponding to the action at the indicated position in the list of
+ * actions for this fragment.
+ * @param position The integer position of the action of interest.
+ * @return The View corresponding to the action at the indicated position, or null if that
+ * action is not currently onscreen.
+ */
+ public View getActionItemView(int position) {
+ final RecyclerView.ViewHolder holder = mActionsStylist.getActionsGridView()
+ .findViewHolderForPosition(position);
+ return holder == null ? null : holder.itemView;
+ }
+
+ /**
+ * Scrolls the action list to the position indicated, selecting that action's view.
+ * @param position The integer position of the action of interest.
+ */
+ public void setSelectedActionPosition(int position) {
+ mActionsStylist.getActionsGridView().setSelectedPosition(position);
+ }
+
+ /**
+ * Returns the position if the currently selected GuidedAction.
+ * @return position The integer position of the currently selected action.
+ */
+ public int getSelectedActionPosition() {
+ return mActionsStylist.getActionsGridView().getSelectedPosition();
+ }
+
+ /**
+ * Called by Constructor to provide fragment transitions. The default implementation assigns
+ * transitions based on {@link #getUiStyle()}:
+ * <ul>
+ * <li> {@link #UI_STYLE_REPLACE} Slide from/to end(right) for enter transition, slide from/to
+ * start(left) for exit transition, shared element enter transition is set to ChangeBounds.
+ * <li> {@link #UI_STYLE_ENTRANCE} Enter transition is set to slide from both sides, exit
+ * transition is same as {@link #UI_STYLE_REPLACE}, no shared element enter transition.
+ * <li> {@link #UI_STYLE_ACTIVITY_ROOT} Enter transition is set to null and app should rely on
+ * activity transition, exit transition is same as {@link #UI_STYLE_REPLACE}, no shared element
+ * enter transition.
+ * </ul>
+ * <p>
+ * The default implementation heavily relies on {@link GuidedActionsStylist} and
+ * {@link GuidanceStylist} layout, app may override this method when modifying the default
+ * layout of {@link GuidedActionsStylist} or {@link GuidanceStylist}.
+ * <p>
+ * TIP: because the fragment view is removed during fragment transition, in general app cannot
+ * use two Visibility transition together. Workaround is to create your own Visibility
+ * transition that controls multiple animators (e.g. slide and fade animation in one Transition
+ * class).
+ */
+ protected void onProvideFragmentTransitions() {
+ if (Build.VERSION.SDK_INT >= 21) {
+ final int uiStyle = getUiStyle();
+ if (uiStyle == UI_STYLE_REPLACE) {
+ Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END);
+ TransitionHelper.exclude(enterTransition, R.id.guidedstep_background, true);
+ TransitionHelper.setEnterTransition(this, enterTransition);
+
+ Object changeBounds = TransitionHelper.createChangeBounds(false);
+ TransitionHelper.setSharedElementEnterTransition(this, changeBounds);
+ } else if (uiStyle == UI_STYLE_ENTRANCE) {
+ Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN |
+ TransitionHelper.FADE_OUT);
+ TransitionHelper.include(fade, R.id.guidedstep_background);
+ Object slide = TransitionHelper.createFadeAndShortSlide(Gravity.END |
+ Gravity.START);
+ TransitionHelper.include(slide, R.id.content_fragment);
+ TransitionHelper.include(slide, R.id.action_fragment_root);
+ Object enterTransition = TransitionHelper.createTransitionSet(false);
+ TransitionHelper.addTransition(enterTransition, fade);
+ TransitionHelper.addTransition(enterTransition, slide);
+ TransitionHelper.setEnterTransition(this, enterTransition);
+
+ // No shared element transition
+ TransitionHelper.setSharedElementEnterTransition(this, null);
+ } else if (uiStyle == UI_STYLE_ACTIVITY_ROOT) {
+ // for Activity root, we dont need enter transition, use activity transition
+ TransitionHelper.setEnterTransition(this, null);
+ // No shared element transition
+ TransitionHelper.setSharedElementEnterTransition(this, null);
+ }
+ // exitTransition is same for all style
+ Object exitTransition = TransitionHelper.createFadeAndShortSlide(Gravity.START);
+ TransitionHelper.exclude(exitTransition, R.id.guidedstep_background, true);
+ TransitionHelper.setExitTransition(this, exitTransition);
+ }
+ }
+
+ /**
+ * Called by onCreateView to inflate background view. Default implementation loads view
+ * from {@link R.layout#lb_guidedstep_background} which holds a reference to
+ * guidedStepBackground.
+ * @param inflater LayoutInflater to load background view.
+ * @param container Parent view of background view.
+ * @param savedInstanceState
+ * @return Created background view or null if no background.
+ */
+ public View onCreateBackgroundView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.lb_guidedstep_background, container, false);
+ }
+
+ /**
+ * Set UI style to fragment arguments. Default value is {@link #UI_STYLE_ENTRANCE} when fragment
+ * is first initialized. UI style is used to choose different fragment transition animations and
+ * determine if this is the first GuidedStepSupportFragment on backstack. In most cases app does not
+ * directly call this method, app calls helper function
+ * {@link #add(FragmentManager, GuidedStepSupportFragment, int)}. However if the app creates Fragment
+ * transaction and controls backstack by itself, it would need call setUiStyle() to select the
+ * fragment transition to use.
+ *
+ * @param style {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
+ * {@link #UI_STYLE_ENTRANCE}.
+ */
+ public void setUiStyle(int style) {
+ int oldStyle = getUiStyle();
+ Bundle arguments = getArguments();
+ boolean isNew = false;
+ if (arguments == null) {
+ arguments = new Bundle();
+ isNew = true;
+ }
+ arguments.putInt(EXTRA_UI_STYLE, style);
+ // call setArgument() will validate if the fragment is already added.
+ if (isNew) {
+ setArguments(arguments);
+ }
+ if (style != oldStyle) {
+ onProvideFragmentTransitions();
+ }
+ }
+
+ /**
+ * Read UI style from fragment arguments. Default value is {@link #UI_STYLE_ENTRANCE} when
+ * fragment is first initialized. UI style is used to choose different fragment transition
+ * animations and determine if this is the first GuidedStepSupportFragment on backstack.
+ *
+ * @return {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
+ * {@link #UI_STYLE_ENTRANCE}.
+ * @see #onProvideFragmentTransitions()
+ */
+ public int getUiStyle() {
+ Bundle b = getArguments();
+ if (b == null) return UI_STYLE_ENTRANCE;
+ return b.getInt(EXTRA_UI_STYLE, UI_STYLE_ENTRANCE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (DEBUG) Log.v(TAG, "onCreate");
+ // Set correct transition from saved arguments.
+ onProvideFragmentTransitions();
+ Bundle state = (savedInstanceState != null) ? savedInstanceState : getArguments();
+ if (state != null) {
+ if (mSelectedIndex == -1) {
+ mSelectedIndex = state.getInt(EXTRA_ACTION_SELECTED_INDEX, -1);
+ }
+ }
+ ArrayList<GuidedAction> actions = new ArrayList<GuidedAction>();
+ onCreateActions(actions, savedInstanceState);
+ setActions(actions);
+ ArrayList<GuidedAction> buttonActions = new ArrayList<GuidedAction>();
+ onCreateButtonActions(buttonActions, savedInstanceState);
+ setButtonActions(buttonActions);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onDestroyView() {
+ mGuidanceStylist.onDestroyView();
+ mActionsStylist.onDestroyView();
+ mButtonActionsStylist.onDestroyView();
+ mAdapter = null;
+ mButtonAdapter = null;
+ mAdapterGroup = null;
+ super.onDestroyView();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ if (DEBUG) Log.v(TAG, "onCreateView");
+
+ resolveTheme();
+ inflater = getThemeInflater(inflater);
+
+ ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_guidedstep_fragment,
+ container, false);
+ ViewGroup guidanceContainer = (ViewGroup) root.findViewById(R.id.content_fragment);
+ ViewGroup actionContainer = (ViewGroup) root.findViewById(R.id.action_fragment);
+
+ Guidance guidance = onCreateGuidance(savedInstanceState);
+ View guidanceView = mGuidanceStylist.onCreateView(inflater, guidanceContainer, guidance);
+ guidanceContainer.addView(guidanceView);
+
+ View actionsView = mActionsStylist.onCreateView(inflater, actionContainer);
+ actionContainer.addView(actionsView);
+
+ View buttonActionsView = mButtonActionsStylist.onCreateView(inflater, actionContainer);
+ mButtonActionsStylist.setAsButtonActions();
+ actionContainer.addView(buttonActionsView);
+
+ GuidedActionAdapter.EditListener editListener = new GuidedActionAdapter.EditListener() {
+
+ @Override
+ public void onImeOpen() {
+ runImeAnimations(true);
+ }
+
+ @Override
+ public void onImeClose() {
+ runImeAnimations(false);
+ }
+
+ @Override
+ public long onGuidedActionEdited(GuidedAction action) {
+ return GuidedStepSupportFragment.this.onGuidedActionEditedAndProceed(action);
+ }
+ };
+
+ mAdapter = new GuidedActionAdapter(mActions, this, this, mActionsStylist);
+ mButtonAdapter = new GuidedActionAdapter(mButtonActions, this, this, mButtonActionsStylist);
+ mAdapterGroup = new GuidedActionAdapterGroup();
+ mAdapterGroup.addAdpter(mAdapter);
+ mAdapterGroup.addAdpter(mButtonAdapter);
+ mAdapterGroup.setEditListener(editListener);
+
+ mActionsStylist.getActionsGridView().setAdapter(mAdapter);
+ mButtonActionsStylist.getActionsGridView().setAdapter(mButtonAdapter);
+ if (mButtonActions.size() == 0) {
+ // when there is no button actions, we dont need show the second panel, but keep
+ // the width zero to run ChangeBounds transition.
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+ buttonActionsView.getLayoutParams();
+ lp.weight = 0;
+ buttonActionsView.setLayoutParams(lp);
+ } else {
+ // when there are two actions panel, we need adjust the weight of action to
+ // guidedActionContentWidthWeightTwoPanels.
+ Context ctx = mThemeWrapper != null ? mThemeWrapper : getActivity();
+ TypedValue typedValue = new TypedValue();
+ if (ctx.getTheme().resolveAttribute(R.attr.guidedActionContentWidthWeightTwoPanels,
+ typedValue, true)) {
+ View actionsRoot = root.findViewById(R.id.action_fragment_root);
+ float weight = typedValue.getFloat();
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) actionsRoot
+ .getLayoutParams();
+ lp.weight = weight;
+ actionsRoot.setLayoutParams(lp);
+ }
+ }
+
+ int pos = (mSelectedIndex >= 0 && mSelectedIndex < mActions.size()) ?
+ mSelectedIndex : getFirstCheckedAction();
+ setSelectedActionPosition(pos);
+
+ setSelectedButtonActionPosition(0);
+
+ View backgroundView = onCreateBackgroundView(inflater, root, savedInstanceState);
+ if (backgroundView != null) {
+ root.addView(backgroundView, 0);
+ }
+ return root;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mActionsStylist.getActionsGridView().requestFocus();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(EXTRA_ACTION_SELECTED_INDEX,
+ (mActionsStylist.getActionsGridView() != null) ?
+ getSelectedActionPosition() : mSelectedIndex);
+ }
+
+ private static boolean isGuidedStepTheme(Context context) {
+ int resId = R.attr.guidedStepThemeFlag;
+ TypedValue typedValue = new TypedValue();
+ boolean found = context.getTheme().resolveAttribute(resId, typedValue, true);
+ if (DEBUG) Log.v(TAG, "Found guided step theme flag? " + found);
+ return found && typedValue.type == TypedValue.TYPE_INT_BOOLEAN && typedValue.data != 0;
+ }
+
+ /**
+ * Convenient method to close GuidedStepSupportFragments on top of other content or finish Activity if
+ * GuidedStepSupportFragments were started in a separate activity. Pops all stack entries including
+ * {@link #UI_STYLE_ENTRANCE}; if {@link #UI_STYLE_ENTRANCE} is not found, finish the activity.
+ * Note that this method must be paired with {@link #add(FragmentManager, GuidedStepSupportFragment,
+ * int)} which sets up the stack entry name for finding which fragment we need to pop back to.
+ */
+ public void finishGuidedStepSupportFragments() {
+ final FragmentManager fragmentManager = getFragmentManager();
+ final int entryCount = fragmentManager.getBackStackEntryCount();
+ if (entryCount > 0) {
+ for (int i = entryCount - 1; i >= 0; i--) {
+ BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
+ if (isUiStyleEntrance(entry.getName())) {
+ GuidedStepSupportFragment top = getCurrentGuidedStepSupportFragment(fragmentManager);
+ if (top != null) {
+ top.setUiStyle(UI_STYLE_ENTRANCE);
+ }
+ fragmentManager.popBackStack(entry.getId(),
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ return;
+ }
+ }
+ }
+ ActivityCompat.finishAfterTransition(getActivity());
+ }
+
+ /**
+ * Convenient method to pop to fragment with Given class.
+ * @param guidedStepFragmentClass Name of the Class of GuidedStepSupportFragment to pop to.
+ * @param flags Either 0 or {@link FragmentManager#POP_BACK_STACK_INCLUSIVE}.
+ */
+ public void popBackStackToGuidedStepSupportFragment(Class guidedStepFragmentClass, int flags) {
+ if (!GuidedStepSupportFragment.class.isAssignableFrom(guidedStepFragmentClass)) {
+ return;
+ }
+ final FragmentManager fragmentManager = getFragmentManager();
+ final int entryCount = fragmentManager.getBackStackEntryCount();
+ String className = guidedStepFragmentClass.getName();
+ if (entryCount > 0) {
+ for (int i = entryCount - 1; i >= 0; i--) {
+ BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
+ String entryClassName = getGuidedStepSupportFragmentClassName(entry.getName());
+ if (className.equals(entryClassName)) {
+ fragmentManager.popBackStack(entry.getId(), flags);
+ return;
+ }
+ }
+ }
+ }
+
+ private void resolveTheme() {
+ // Look up the guidedStepTheme in the currently specified theme. If it exists,
+ // replace the theme with its value.
+ FragmentActivity activity = getActivity();
+ if (mTheme == -1 && !isGuidedStepTheme(activity)) {
+ // Look up the guidedStepTheme in the activity's currently specified theme. If it
+ // exists, replace the theme with its value.
+ int resId = R.attr.guidedStepTheme;
+ TypedValue typedValue = new TypedValue();
+ boolean found = activity.getTheme().resolveAttribute(resId, typedValue, true);
+ if (DEBUG) Log.v(TAG, "Found guided step theme reference? " + found);
+ if (found) {
+ ContextThemeWrapper themeWrapper =
+ new ContextThemeWrapper(activity, typedValue.resourceId);
+ if (isGuidedStepTheme(themeWrapper)) {
+ mTheme = typedValue.resourceId;
+ mThemeWrapper = themeWrapper;
+ } else {
+ found = false;
+ mThemeWrapper = null;
+ }
+ }
+ if (!found) {
+ Log.e(TAG, "GuidedStepSupportFragment does not have an appropriate theme set.");
+ }
+ } else if (mTheme != -1) {
+ mThemeWrapper = new ContextThemeWrapper(activity, mTheme);
+ }
+ }
+
+ private LayoutInflater getThemeInflater(LayoutInflater inflater) {
+ if (mTheme == -1) {
+ return inflater;
+ } else {
+ return inflater.cloneInContext(mThemeWrapper);
+ }
+ }
+
+ private int getFirstCheckedAction() {
+ for (int i = 0, size = mActions.size(); i < size; i++) {
+ if (mActions.get(i).isChecked()) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ private void runImeAnimations(boolean entering) {
+ ArrayList<Animator> animators = new ArrayList<Animator>();
+ if (entering) {
+ mGuidanceStylist.onImeAppearing(animators);
+ mActionsStylist.onImeAppearing(animators);
+ mButtonActionsStylist.onImeAppearing(animators);
+ } else {
+ mGuidanceStylist.onImeDisappearing(animators);
+ mActionsStylist.onImeDisappearing(animators);
+ mButtonActionsStylist.onImeDisappearing(animators);
+ }
+ AnimatorSet set = new AnimatorSet();
+ set.playTogether(animators);
+ set.start();
+ }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/HeadersFragment.java b/v17/leanback/src/android/support/v17/leanback/app/HeadersFragment.java
index b2c9b1ccdb..219bb9898d 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/HeadersFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/HeadersFragment.java
@@ -138,8 +138,10 @@ public class HeadersFragment extends BaseRowFragment {
if (getBridgeAdapter() != null) {
FocusHighlightHelper.setupHeaderItemFocusHighlight(listView);
}
- view.setBackgroundColor(getBackgroundColor());
- updateFadingEdgeToBrandColor(getBackgroundColor());
+ if (mBackgroundColorSet) {
+ view.setBackgroundColor(mBackgroundColor);
+ updateFadingEdgeToBrandColor(mBackgroundColor);
+ }
updateListViewVisibility();
}
@@ -228,22 +230,6 @@ public class HeadersFragment extends BaseRowFragment {
}
}
- int getBackgroundColor() {
- if (getActivity() == null) {
- throw new IllegalStateException("Activity must be attached");
- }
-
- if (mBackgroundColorSet) {
- return mBackgroundColor;
- }
-
- TypedValue outValue = new TypedValue();
- if (getActivity().getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true)) {
- return getResources().getColor(outValue.resourceId);
- }
- return getResources().getColor(R.color.lb_default_brand_color);
- }
-
@Override
void onTransitionStart() {
super.onTransitionStart();
diff --git a/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java
index 9c66714810..ecf04d87ee 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java
@@ -140,8 +140,10 @@ public class HeadersSupportFragment extends BaseRowSupportFragment {
if (getBridgeAdapter() != null) {
FocusHighlightHelper.setupHeaderItemFocusHighlight(listView);
}
- view.setBackgroundColor(getBackgroundColor());
- updateFadingEdgeToBrandColor(getBackgroundColor());
+ if (mBackgroundColorSet) {
+ view.setBackgroundColor(mBackgroundColor);
+ updateFadingEdgeToBrandColor(mBackgroundColor);
+ }
updateListViewVisibility();
}
@@ -230,22 +232,6 @@ public class HeadersSupportFragment extends BaseRowSupportFragment {
}
}
- int getBackgroundColor() {
- if (getActivity() == null) {
- throw new IllegalStateException("Activity must be attached");
- }
-
- if (mBackgroundColorSet) {
- return mBackgroundColor;
- }
-
- TypedValue outValue = new TypedValue();
- if (getActivity().getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true)) {
- return getResources().getColor(outValue.resourceId);
- }
- return getResources().getColor(R.color.lb_default_brand_color);
- }
-
@Override
void onTransitionStart() {
super.onTransitionStart();
diff --git a/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java
index 8c56925298..e3af40320d 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java
@@ -74,7 +74,7 @@ import android.view.View;
*/
public abstract class PlaybackControlGlue implements OnActionClickedListener, View.OnKeyListener {
/**
- * The adapter key for the first custom control on the right side
+ * The adapter key for the first custom control on the left side
* of the predefined primary controls.
*/
public static final int ACTION_CUSTOM_LEFT_FIRST = 0x1;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlSupportGlue.java b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlSupportGlue.java
new file mode 100644
index 0000000000..5857e65dce
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlSupportGlue.java
@@ -0,0 +1,858 @@
+/* This file is auto-generated from PlaybackControlGlue.java. DO NOT MODIFY. */
+
+package android.support.v17.leanback.app;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.ControlButtonPresenterSelector;
+import android.support.v17.leanback.widget.OnActionClickedListener;
+import android.support.v17.leanback.widget.OnItemViewClickedListener;
+import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.RowPresenter;
+import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
+import android.util.Log;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.View;
+
+
+/**
+ * A helper class for managing a {@link android.support.v17.leanback.widget.PlaybackControlsRow} and
+ * {@link PlaybackOverlaySupportFragment} that implements a recommended approach to handling standard
+ * playback control actions such as play/pause, fast forward/rewind at progressive speed levels,
+ * and skip to next/previous. This helper class is a glue layer in that it manages the
+ * configuration of and interaction between the leanback UI components by defining a functional
+ * interface to the media player.
+ *
+ * <p>You can instantiate a concrete subclass such as {@link MediaControllerGlue} or you must
+ * subclass this abstract helper. To create a subclass you must implement all of the
+ * abstract methods and the subclass must invoke {@link #onMetadataChanged()} and
+ * {@link #onStateChanged()} appropriately.
+ * </p>
+ *
+ * <p>To use an instance of the glue layer, first construct an instance. Constructor parameters
+ * inform the glue what speed levels are supported for fast forward/rewind. Providing a
+ * {@link android.support.v17.leanback.app.PlaybackOverlaySupportFragment} is optional.
+ * </p>
+ *
+ * <p>If you have your own controls row you must pass it to {@link #setControlsRow}.
+ * The row will be updated by the glue layer based on the media metadata and playback state.
+ * Alternatively, you may call {@link #createControlsRowAndPresenter()} which will set a controls
+ * row and return a row presenter you can use to present the row.
+ * </p>
+ *
+ * <p>The helper sets a {@link android.support.v17.leanback.widget.SparseArrayObjectAdapter}
+ * on the controls row as the primary actions adapter, and adds actions to it. You can provide
+ * additional actions by overriding {@link #createPrimaryActionsAdapter}. This helper does not
+ * deal in secondary actions so those you may add separately.
+ * </p>
+ *
+ * <p>Provide a click listener on your fragment and if an action is clicked, call
+ * {@link #onActionClicked}. There is no need to call {@link #setOnItemViewClickedListener}
+ * but if you do a click listener will be installed on the fragment and recognized action clicks
+ * will be handled. Your listener will be called only for unhandled actions.
+ * </p>
+ *
+ * <p>The helper implements a key event handler. If you pass a
+ * {@link android.support.v17.leanback.app.PlaybackOverlaySupportFragment} the fragment's input event
+ * handler will be set. Otherwise, you should set the glue object as key event handler to the
+ * ViewHolder when bound by your row presenter; see
+ * {@link RowPresenter.ViewHolder#setOnKeyListener(android.view.View.OnKeyListener)}.
+ * </p>
+ *
+ * <p>To update the controls row progress during playback, override {@link #enableProgressUpdating}
+ * to manage the lifecycle of a periodic callback to {@link #updateProgress()}.
+ * {@link #getUpdatePeriod()} provides a recommended update period.
+ * </p>
+ *
+ */
+public abstract class PlaybackControlSupportGlue implements OnActionClickedListener, View.OnKeyListener {
+ /**
+ * The adapter key for the first custom control on the left side
+ * of the predefined primary controls.
+ */
+ public static final int ACTION_CUSTOM_LEFT_FIRST = 0x1;
+
+ /**
+ * The adapter key for the skip to previous control.
+ */
+ public static final int ACTION_SKIP_TO_PREVIOUS = 0x10;
+
+ /**
+ * The adapter key for the rewind control.
+ */
+ public static final int ACTION_REWIND = 0x20;
+
+ /**
+ * The adapter key for the play/pause control.
+ */
+ public static final int ACTION_PLAY_PAUSE = 0x40;
+
+ /**
+ * The adapter key for the fast forward control.
+ */
+ public static final int ACTION_FAST_FORWARD = 0x80;
+
+ /**
+ * The adapter key for the skip to next control.
+ */
+ public static final int ACTION_SKIP_TO_NEXT = 0x100;
+
+ /**
+ * The adapter key for the first custom control on the right side
+ * of the predefined primary controls.
+ */
+ public static final int ACTION_CUSTOM_RIGHT_FIRST = 0x1000;
+
+ /**
+ * Invalid playback speed.
+ */
+ public static final int PLAYBACK_SPEED_INVALID = -1;
+
+ /**
+ * Speed representing playback state that is paused.
+ */
+ public static final int PLAYBACK_SPEED_PAUSED = 0;
+
+ /**
+ * Speed representing playback state that is playing normally.
+ */
+ public static final int PLAYBACK_SPEED_NORMAL = 1;
+
+ /**
+ * The initial (level 0) fast forward playback speed.
+ * The negative of this value is for rewind at the same speed.
+ */
+ public static final int PLAYBACK_SPEED_FAST_L0 = 10;
+
+ /**
+ * The level 1 fast forward playback speed.
+ * The negative of this value is for rewind at the same speed.
+ */
+ public static final int PLAYBACK_SPEED_FAST_L1 = 11;
+
+ /**
+ * The level 2 fast forward playback speed.
+ * The negative of this value is for rewind at the same speed.
+ */
+ public static final int PLAYBACK_SPEED_FAST_L2 = 12;
+
+ /**
+ * The level 3 fast forward playback speed.
+ * The negative of this value is for rewind at the same speed.
+ */
+ public static final int PLAYBACK_SPEED_FAST_L3 = 13;
+
+ /**
+ * The level 4 fast forward playback speed.
+ * The negative of this value is for rewind at the same speed.
+ */
+ public static final int PLAYBACK_SPEED_FAST_L4 = 14;
+
+ private static final String TAG = "PlaybackControlSupportGlue";
+ private static final boolean DEBUG = false;
+
+ private static final int MSG_UPDATE_PLAYBACK_STATE = 100;
+ private static final int UPDATE_PLAYBACK_STATE_DELAY_MS = 2000;
+ private static final int NUMBER_OF_SEEK_SPEEDS = PLAYBACK_SPEED_FAST_L4 -
+ PLAYBACK_SPEED_FAST_L0 + 1;
+
+ private final PlaybackOverlaySupportFragment mFragment;
+ private final Context mContext;
+ private final int[] mFastForwardSpeeds;
+ private final int[] mRewindSpeeds;
+ private PlaybackControlsRow mControlsRow;
+ private SparseArrayObjectAdapter mPrimaryActionsAdapter;
+ private PlaybackControlsRow.PlayPauseAction mPlayPauseAction;
+ private PlaybackControlsRow.SkipNextAction mSkipNextAction;
+ private PlaybackControlsRow.SkipPreviousAction mSkipPreviousAction;
+ private PlaybackControlsRow.FastForwardAction mFastForwardAction;
+ private PlaybackControlsRow.RewindAction mRewindAction;
+ private OnItemViewClickedListener mExternalOnItemViewClickedListener;
+ private int mPlaybackSpeed = PLAYBACK_SPEED_NORMAL;
+ private boolean mFadeWhenPlaying = true;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_UPDATE_PLAYBACK_STATE) {
+ updatePlaybackState();
+ }
+ }
+ };
+
+ private final OnItemViewClickedListener mOnItemViewClickedListener =
+ new OnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder viewHolder, Object object,
+ RowPresenter.ViewHolder viewHolder2, Row row) {
+ if (DEBUG) Log.v(TAG, "onItemClicked " + object);
+ boolean handled = false;
+ if (object instanceof Action) {
+ handled = dispatchAction((Action) object, null);
+ }
+ if (!handled && mExternalOnItemViewClickedListener != null) {
+ mExternalOnItemViewClickedListener.onItemClicked(viewHolder, object,
+ viewHolder2, row);
+ }
+ }
+ };
+
+ /**
+ * Constructor for the glue.
+ *
+ * @param context
+ * @param seekSpeeds Array of seek speeds for fast forward and rewind.
+ */
+ public PlaybackControlSupportGlue(Context context, int[] seekSpeeds) {
+ this(context, null, seekSpeeds, seekSpeeds);
+ }
+
+ /**
+ * Constructor for the glue.
+ *
+ * @param context
+ * @param fastForwardSpeeds Array of seek speeds for fast forward.
+ * @param rewindSpeeds Array of seek speeds for rewind.
+ */
+ public PlaybackControlSupportGlue(Context context,
+ int[] fastForwardSpeeds,
+ int[] rewindSpeeds) {
+ this(context, null, fastForwardSpeeds, rewindSpeeds);
+ }
+
+ /**
+ * Constructor for the glue.
+ *
+ * @param context
+ * @param fragment Optional; if using a {@link PlaybackOverlaySupportFragment}, pass it in.
+ * @param seekSpeeds Array of seek speeds for fast forward and rewind.
+ */
+ public PlaybackControlSupportGlue(Context context,
+ PlaybackOverlaySupportFragment fragment,
+ int[] seekSpeeds) {
+ this(context, fragment, seekSpeeds, seekSpeeds);
+ }
+
+ /**
+ * Constructor for the glue.
+ *
+ * @param context
+ * @param fragment Optional; if using a {@link PlaybackOverlaySupportFragment}, pass it in.
+ * @param fastForwardSpeeds Array of seek speeds for fast forward.
+ * @param rewindSpeeds Array of seek speeds for rewind.
+ */
+ public PlaybackControlSupportGlue(Context context,
+ PlaybackOverlaySupportFragment fragment,
+ int[] fastForwardSpeeds,
+ int[] rewindSpeeds) {
+ mContext = context;
+ mFragment = fragment;
+ if (fragment != null) {
+ attachToFragment();
+ }
+ if (fastForwardSpeeds.length == 0 || fastForwardSpeeds.length > NUMBER_OF_SEEK_SPEEDS) {
+ throw new IllegalStateException("invalid fastForwardSpeeds array size");
+ }
+ mFastForwardSpeeds = fastForwardSpeeds;
+ if (rewindSpeeds.length == 0 || rewindSpeeds.length > NUMBER_OF_SEEK_SPEEDS) {
+ throw new IllegalStateException("invalid rewindSpeeds array size");
+ }
+ mRewindSpeeds = rewindSpeeds;
+ }
+
+ private final PlaybackOverlaySupportFragment.InputEventHandler mOnInputEventHandler =
+ new PlaybackOverlaySupportFragment.InputEventHandler() {
+ @Override
+ public boolean handleInputEvent(InputEvent event) {
+ if (event instanceof KeyEvent) {
+ KeyEvent keyEvent = (KeyEvent) event;
+ return onKey(null, keyEvent.getKeyCode(), keyEvent);
+ }
+ return false;
+ }
+ };
+
+ private void attachToFragment() {
+ mFragment.setInputEventHandler(mOnInputEventHandler);
+ }
+
+ /**
+ * Helper method for instantiating a
+ * {@link android.support.v17.leanback.widget.PlaybackControlsRow} and corresponding
+ * {@link android.support.v17.leanback.widget.PlaybackControlsRowPresenter}.
+ */
+ public PlaybackControlsRowPresenter createControlsRowAndPresenter() {
+ PlaybackControlsRow controlsRow = new PlaybackControlsRow(this);
+ setControlsRow(controlsRow);
+
+ AbstractDetailsDescriptionPresenter detailsPresenter =
+ new AbstractDetailsDescriptionPresenter() {
+ @Override
+ protected void onBindDescription(AbstractDetailsDescriptionPresenter.ViewHolder
+ viewHolder, Object object) {
+ PlaybackControlSupportGlue glue = (PlaybackControlSupportGlue) object;
+ if (glue.hasValidMedia()) {
+ viewHolder.getTitle().setText(glue.getMediaTitle());
+ viewHolder.getSubtitle().setText(glue.getMediaSubtitle());
+ } else {
+ viewHolder.getTitle().setText("");
+ viewHolder.getSubtitle().setText("");
+ }
+ }
+ };
+ return new PlaybackControlsRowPresenter(detailsPresenter) {
+ @Override
+ protected void onBindRowViewHolder(RowPresenter.ViewHolder vh, Object item) {
+ super.onBindRowViewHolder(vh, item);
+ vh.setOnKeyListener(PlaybackControlSupportGlue.this);
+ }
+ @Override
+ protected void onUnbindRowViewHolder(RowPresenter.ViewHolder vh) {
+ super.onUnbindRowViewHolder(vh);
+ vh.setOnKeyListener(null);
+ }
+ };
+ }
+
+ /**
+ * Returns the fragment.
+ */
+ public PlaybackOverlaySupportFragment getFragment() {
+ return mFragment;
+ }
+
+ /**
+ * Returns the context.
+ */
+ public Context getContext() {
+ return mContext;
+ }
+
+ /**
+ * Returns the fast forward speeds.
+ */
+ public int[] getFastForwardSpeeds() {
+ return mFastForwardSpeeds;
+ }
+
+ /**
+ * Returns the rewind speeds.
+ */
+ public int[] getRewindSpeeds() {
+ return mRewindSpeeds;
+ }
+
+ /**
+ * Sets the controls to fade after a timeout when media is playing.
+ */
+ public void setFadingEnabled(boolean enable) {
+ mFadeWhenPlaying = enable;
+ if (!mFadeWhenPlaying && mFragment != null) {
+ mFragment.setFadingEnabled(false);
+ }
+ }
+
+ /**
+ * Returns true if controls are set to fade when media is playing.
+ */
+ public boolean isFadingEnabled() {
+ return mFadeWhenPlaying;
+ }
+
+ /**
+ * Set the {@link OnItemViewClickedListener} to be called if the click event
+ * is not handled internally.
+ * @param listener
+ * @deprecated Don't call this. Instead set the listener on the fragment yourself,
+ * and call {@link #onActionClicked} to handle clicks.
+ */
+ public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
+ mExternalOnItemViewClickedListener = listener;
+ if (mFragment != null) {
+ mFragment.setOnItemViewClickedListener(mOnItemViewClickedListener);
+ }
+ }
+
+ /**
+ * Returns the {@link OnItemViewClickedListener}.
+ */
+ public OnItemViewClickedListener getOnItemViewClickedListener() {
+ return mExternalOnItemViewClickedListener;
+ }
+
+ /**
+ * Sets the controls row to be managed by the glue layer.
+ * The primary actions and playback state related aspects of the row
+ * are updated by the glue.
+ */
+ public void setControlsRow(PlaybackControlsRow controlsRow) {
+ mControlsRow = controlsRow;
+ mPrimaryActionsAdapter = createPrimaryActionsAdapter(
+ new ControlButtonPresenterSelector());
+ mControlsRow.setPrimaryActionsAdapter(mPrimaryActionsAdapter);
+ updateControlsRow();
+ }
+
+ /**
+ * Returns the playback controls row managed by the glue layer.
+ */
+ public PlaybackControlsRow getControlsRow() {
+ return mControlsRow;
+ }
+
+ /**
+ * Override this to start/stop a runnable to call {@link #updateProgress} at
+ * an interval such as {@link #getUpdatePeriod}.
+ */
+ public void enableProgressUpdating(boolean enable) {
+ }
+
+ /**
+ * Returns the time period in milliseconds that should be used
+ * to update the progress. See {@link #updateProgress()}.
+ */
+ public int getUpdatePeriod() {
+ // TODO: calculate a better update period based on total duration and screen size
+ return 500;
+ }
+
+ /**
+ * Updates the progress bar based on the current media playback position.
+ */
+ public void updateProgress() {
+ int position = getCurrentPosition();
+ if (DEBUG) Log.v(TAG, "updateProgress " + position);
+ mControlsRow.setCurrentTime(position);
+ }
+
+ /**
+ * Handles action clicks. A subclass may override this add support for additional actions.
+ */
+ @Override
+ public void onActionClicked(Action action) {
+ dispatchAction(action, null);
+ }
+
+ /**
+ * Handles key events and returns true if handled. A subclass may override this to provide
+ * additional support.
+ */
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_BACK:
+ case KeyEvent.KEYCODE_ESCAPE:
+ boolean abortSeek = mPlaybackSpeed >= PLAYBACK_SPEED_FAST_L0 ||
+ mPlaybackSpeed <= -PLAYBACK_SPEED_FAST_L0;
+ if (abortSeek) {
+ mPlaybackSpeed = PLAYBACK_SPEED_NORMAL;
+ startPlayback(mPlaybackSpeed);
+ updatePlaybackStatusAfterUserAction();
+ return keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE;
+ }
+ return false;
+ }
+ Action action = mControlsRow.getActionForKeyCode(mPrimaryActionsAdapter, keyCode);
+ if (action != null) {
+ if (action == mPrimaryActionsAdapter.lookup(ACTION_PLAY_PAUSE) ||
+ action == mPrimaryActionsAdapter.lookup(ACTION_REWIND) ||
+ action == mPrimaryActionsAdapter.lookup(ACTION_FAST_FORWARD) ||
+ action == mPrimaryActionsAdapter.lookup(ACTION_SKIP_TO_PREVIOUS) ||
+ action == mPrimaryActionsAdapter.lookup(ACTION_SKIP_TO_NEXT)) {
+ if (((KeyEvent) event).getAction() == KeyEvent.ACTION_DOWN) {
+ dispatchAction(action, (KeyEvent) event);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called when the given action is invoked, either by click or keyevent.
+ */
+ private boolean dispatchAction(Action action, KeyEvent keyEvent) {
+ boolean handled = false;
+ if (action == mPlayPauseAction) {
+ boolean canPlay = keyEvent == null ||
+ keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
+ keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY;
+ boolean canPause = keyEvent == null ||
+ keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
+ keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PAUSE;
+ if (mPlaybackSpeed != PLAYBACK_SPEED_NORMAL) {
+ if (canPlay) {
+ mPlaybackSpeed = PLAYBACK_SPEED_NORMAL;
+ startPlayback(mPlaybackSpeed);
+ }
+ } else if (canPause) {
+ mPlaybackSpeed = PLAYBACK_SPEED_PAUSED;
+ pausePlayback();
+ }
+ updatePlaybackStatusAfterUserAction();
+ handled = true;
+ } else if (action == mSkipNextAction) {
+ skipToNext();
+ handled = true;
+ } else if (action == mSkipPreviousAction) {
+ skipToPrevious();
+ handled = true;
+ } else if (action == mFastForwardAction) {
+ if (mPlaybackSpeed < getMaxForwardSpeedId()) {
+ switch (mPlaybackSpeed) {
+ case PLAYBACK_SPEED_FAST_L0:
+ case PLAYBACK_SPEED_FAST_L1:
+ case PLAYBACK_SPEED_FAST_L2:
+ case PLAYBACK_SPEED_FAST_L3:
+ mPlaybackSpeed++;
+ break;
+ default:
+ mPlaybackSpeed = PLAYBACK_SPEED_FAST_L0;
+ break;
+ }
+ startPlayback(mPlaybackSpeed);
+ updatePlaybackStatusAfterUserAction();
+ }
+ handled = true;
+ } else if (action == mRewindAction) {
+ if (mPlaybackSpeed > -getMaxRewindSpeedId()) {
+ switch (mPlaybackSpeed) {
+ case -PLAYBACK_SPEED_FAST_L0:
+ case -PLAYBACK_SPEED_FAST_L1:
+ case -PLAYBACK_SPEED_FAST_L2:
+ case -PLAYBACK_SPEED_FAST_L3:
+ mPlaybackSpeed--;
+ break;
+ default:
+ mPlaybackSpeed = -PLAYBACK_SPEED_FAST_L0;
+ break;
+ }
+ startPlayback(mPlaybackSpeed);
+ updatePlaybackStatusAfterUserAction();
+ }
+ handled = true;
+ }
+ return handled;
+ }
+
+ private int getMaxForwardSpeedId() {
+ return PLAYBACK_SPEED_FAST_L0 + (mFastForwardSpeeds.length - 1);
+ }
+
+ private int getMaxRewindSpeedId() {
+ return PLAYBACK_SPEED_FAST_L0 + (mRewindSpeeds.length - 1);
+ }
+
+ private void updateControlsRow() {
+ updateRowMetadata();
+ mHandler.removeMessages(MSG_UPDATE_PLAYBACK_STATE);
+ updatePlaybackState();
+ }
+
+ private void updatePlaybackStatusAfterUserAction() {
+ updatePlaybackState(mPlaybackSpeed);
+ // Sync playback state after a delay
+ mHandler.removeMessages(MSG_UPDATE_PLAYBACK_STATE);
+ mHandler.sendEmptyMessageDelayed(MSG_UPDATE_PLAYBACK_STATE,
+ UPDATE_PLAYBACK_STATE_DELAY_MS);
+ }
+
+ private void updateRowMetadata() {
+ if (mControlsRow == null) {
+ return;
+ }
+
+ if (DEBUG) Log.v(TAG, "updateRowMetadata hasValidMedia " + hasValidMedia());
+
+ if (!hasValidMedia()) {
+ mControlsRow.setImageDrawable(null);
+ mControlsRow.setTotalTime(0);
+ mControlsRow.setCurrentTime(0);
+ } else {
+ mControlsRow.setImageDrawable(getMediaArt());
+ mControlsRow.setTotalTime(getMediaDuration());
+ mControlsRow.setCurrentTime(getCurrentPosition());
+ }
+
+ onRowChanged(mControlsRow);
+ }
+
+ private void updatePlaybackState() {
+ if (hasValidMedia()) {
+ mPlaybackSpeed = getCurrentSpeedId();
+ updatePlaybackState(mPlaybackSpeed);
+ }
+ }
+
+ private void updatePlaybackState(int playbackSpeed) {
+ if (mControlsRow == null) {
+ return;
+ }
+
+ final long actions = getSupportedActions();
+ if ((actions & ACTION_SKIP_TO_PREVIOUS) != 0) {
+ if (mSkipPreviousAction == null) {
+ mSkipPreviousAction = new PlaybackControlsRow.SkipPreviousAction(mContext);
+ }
+ mPrimaryActionsAdapter.set(ACTION_SKIP_TO_PREVIOUS, mSkipPreviousAction);
+ } else {
+ mPrimaryActionsAdapter.clear(ACTION_SKIP_TO_PREVIOUS);
+ mSkipPreviousAction = null;
+ }
+ if ((actions & ACTION_REWIND) != 0) {
+ if (mRewindAction == null) {
+ mRewindAction = new PlaybackControlsRow.RewindAction(mContext,
+ mRewindSpeeds.length);
+ }
+ mPrimaryActionsAdapter.set(ACTION_REWIND, mRewindAction);
+ } else {
+ mPrimaryActionsAdapter.clear(ACTION_REWIND);
+ mRewindAction = null;
+ }
+ if ((actions & ACTION_PLAY_PAUSE) != 0) {
+ if (mPlayPauseAction == null) {
+ mPlayPauseAction = new PlaybackControlsRow.PlayPauseAction(mContext);
+ }
+ mPrimaryActionsAdapter.set(ACTION_PLAY_PAUSE, mPlayPauseAction);
+ } else {
+ mPrimaryActionsAdapter.clear(ACTION_PLAY_PAUSE);
+ mPlayPauseAction = null;
+ }
+ if ((actions & ACTION_FAST_FORWARD) != 0) {
+ if (mFastForwardAction == null) {
+ mFastForwardAction = new PlaybackControlsRow.FastForwardAction(mContext,
+ mFastForwardSpeeds.length);
+ }
+ mPrimaryActionsAdapter.set(ACTION_FAST_FORWARD, mFastForwardAction);
+ } else {
+ mPrimaryActionsAdapter.clear(ACTION_FAST_FORWARD);
+ mFastForwardAction = null;
+ }
+ if ((actions & ACTION_SKIP_TO_NEXT) != 0) {
+ if (mSkipNextAction == null) {
+ mSkipNextAction = new PlaybackControlsRow.SkipNextAction(mContext);
+ }
+ mPrimaryActionsAdapter.set(ACTION_SKIP_TO_NEXT, mSkipNextAction);
+ } else {
+ mPrimaryActionsAdapter.clear(ACTION_SKIP_TO_NEXT);
+ mSkipNextAction = null;
+ }
+
+ if (mFastForwardAction != null) {
+ int index = 0;
+ if (playbackSpeed >= PLAYBACK_SPEED_FAST_L0) {
+ index = playbackSpeed - PLAYBACK_SPEED_FAST_L0;
+ if (playbackSpeed < getMaxForwardSpeedId()) {
+ index++;
+ }
+ }
+ if (mFastForwardAction.getIndex() != index) {
+ mFastForwardAction.setIndex(index);
+ notifyItemChanged(mPrimaryActionsAdapter, mFastForwardAction);
+ }
+ }
+ if (mRewindAction != null) {
+ int index = 0;
+ if (playbackSpeed <= -PLAYBACK_SPEED_FAST_L0) {
+ index = -playbackSpeed - PLAYBACK_SPEED_FAST_L0;
+ if (-playbackSpeed < getMaxRewindSpeedId()) {
+ index++;
+ }
+ }
+ if (mRewindAction.getIndex() != index) {
+ mRewindAction.setIndex(index);
+ notifyItemChanged(mPrimaryActionsAdapter, mRewindAction);
+ }
+ }
+
+ if (playbackSpeed == PLAYBACK_SPEED_PAUSED) {
+ updateProgress();
+ enableProgressUpdating(false);
+ } else {
+ enableProgressUpdating(true);
+ }
+
+ if (mFadeWhenPlaying && mFragment != null) {
+ mFragment.setFadingEnabled(playbackSpeed == PLAYBACK_SPEED_NORMAL);
+ }
+
+ if (mPlayPauseAction != null) {
+ int index = playbackSpeed == PLAYBACK_SPEED_PAUSED ?
+ PlaybackControlsRow.PlayPauseAction.PLAY :
+ PlaybackControlsRow.PlayPauseAction.PAUSE;
+ if (mPlayPauseAction.getIndex() != index) {
+ mPlayPauseAction.setIndex(index);
+ notifyItemChanged(mPrimaryActionsAdapter, mPlayPauseAction);
+ }
+ }
+ }
+
+ private static void notifyItemChanged(SparseArrayObjectAdapter adapter, Object object) {
+ int index = adapter.indexOf(object);
+ if (index >= 0) {
+ adapter.notifyArrayItemRangeChanged(index, 1);
+ }
+ }
+
+ private static String getSpeedString(int speed) {
+ switch (speed) {
+ case PLAYBACK_SPEED_INVALID:
+ return "PLAYBACK_SPEED_INVALID";
+ case PLAYBACK_SPEED_PAUSED:
+ return "PLAYBACK_SPEED_PAUSED";
+ case PLAYBACK_SPEED_NORMAL:
+ return "PLAYBACK_SPEED_NORMAL";
+ case PLAYBACK_SPEED_FAST_L0:
+ return "PLAYBACK_SPEED_FAST_L0";
+ case PLAYBACK_SPEED_FAST_L1:
+ return "PLAYBACK_SPEED_FAST_L1";
+ case PLAYBACK_SPEED_FAST_L2:
+ return "PLAYBACK_SPEED_FAST_L2";
+ case PLAYBACK_SPEED_FAST_L3:
+ return "PLAYBACK_SPEED_FAST_L3";
+ case PLAYBACK_SPEED_FAST_L4:
+ return "PLAYBACK_SPEED_FAST_L4";
+ case -PLAYBACK_SPEED_FAST_L0:
+ return "-PLAYBACK_SPEED_FAST_L0";
+ case -PLAYBACK_SPEED_FAST_L1:
+ return "-PLAYBACK_SPEED_FAST_L1";
+ case -PLAYBACK_SPEED_FAST_L2:
+ return "-PLAYBACK_SPEED_FAST_L2";
+ case -PLAYBACK_SPEED_FAST_L3:
+ return "-PLAYBACK_SPEED_FAST_L3";
+ case -PLAYBACK_SPEED_FAST_L4:
+ return "-PLAYBACK_SPEED_FAST_L4";
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if there is a valid media item.
+ */
+ public abstract boolean hasValidMedia();
+
+ /**
+ * Returns true if media is currently playing.
+ */
+ public abstract boolean isMediaPlaying();
+
+ /**
+ * Returns the title of the media item.
+ */
+ public abstract CharSequence getMediaTitle();
+
+ /**
+ * Returns the subtitle of the media item.
+ */
+ public abstract CharSequence getMediaSubtitle();
+
+ /**
+ * Returns the duration of the media item in milliseconds.
+ */
+ public abstract int getMediaDuration();
+
+ /**
+ * Returns a bitmap of the art for the media item.
+ */
+ public abstract Drawable getMediaArt();
+
+ /**
+ * Returns a bitmask of actions supported by the media player.
+ */
+ public abstract long getSupportedActions();
+
+ /**
+ * Returns the current playback speed. When playing normally,
+ * {@link #PLAYBACK_SPEED_NORMAL} should be returned.
+ */
+ public abstract int getCurrentSpeedId();
+
+ /**
+ * Returns the current position of the media item in milliseconds.
+ */
+ public abstract int getCurrentPosition();
+
+ /**
+ * Start playback at the given speed.
+ * @param speed The desired playback speed. For normal playback this will be
+ * {@link #PLAYBACK_SPEED_NORMAL}; higher positive values for fast forward,
+ * and negative values for rewind.
+ */
+ protected abstract void startPlayback(int speed);
+
+ /**
+ * Pause playback.
+ */
+ protected abstract void pausePlayback();
+
+ /**
+ * Skip to the next track.
+ */
+ protected abstract void skipToNext();
+
+ /**
+ * Skip to the previous track.
+ */
+ protected abstract void skipToPrevious();
+
+ /**
+ * Invoked when the playback controls row has changed. The adapter containing this row
+ * should be notified.
+ */
+ protected abstract void onRowChanged(PlaybackControlsRow row);
+
+ /**
+ * Creates the primary action adapter. May be overridden to add additional primary
+ * actions to the adapter.
+ */
+ protected SparseArrayObjectAdapter createPrimaryActionsAdapter(
+ PresenterSelector presenterSelector) {
+ return new SparseArrayObjectAdapter(presenterSelector);
+ }
+
+ /**
+ * Must be called appropriately by a subclass when the playback state has changed.
+ */
+ protected void onStateChanged() {
+ if (DEBUG) Log.v(TAG, "onStateChanged");
+ // If a pending control button update is present, delay
+ // the update until the state settles.
+ if (!hasValidMedia()) {
+ return;
+ }
+ if (mHandler.hasMessages(MSG_UPDATE_PLAYBACK_STATE)) {
+ mHandler.removeMessages(MSG_UPDATE_PLAYBACK_STATE);
+ if (getCurrentSpeedId() != mPlaybackSpeed) {
+ if (DEBUG) Log.v(TAG, "Status expectation mismatch, delaying update");
+ mHandler.sendEmptyMessageDelayed(MSG_UPDATE_PLAYBACK_STATE,
+ UPDATE_PLAYBACK_STATE_DELAY_MS);
+ } else {
+ if (DEBUG) Log.v(TAG, "Update state matches expectation");
+ updatePlaybackState();
+ }
+ } else {
+ updatePlaybackState();
+ }
+ }
+
+ /**
+ * Must be called appropriately by a subclass when the metadata state has changed.
+ */
+ protected void onMetadataChanged() {
+ if (DEBUG) Log.v(TAG, "onMetadataChanged");
+ updateRowMetadata();
+ }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/RowsFragment.java b/v17/leanback/src/android/support/v17/leanback/app/RowsFragment.java
index 71a95e8223..a5a7ccd891 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/RowsFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/RowsFragment.java
@@ -448,6 +448,10 @@ public class RowsFragment extends BaseRowFragment {
@Override
public boolean onPreDraw() {
+ if (getView() == null || getActivity() == null) {
+ mVerticalView.getViewTreeObserver().removeOnPreDrawListener(this);
+ return true;
+ }
if (mState == STATE_INIT) {
setExpand(true);
mState = STATE_FIRST_DRAW;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java
index 7f12aacbc5..7390acfc7f 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java
@@ -450,6 +450,10 @@ public class RowsSupportFragment extends BaseRowSupportFragment {
@Override
public boolean onPreDraw() {
+ if (getView() == null || getActivity() == null) {
+ mVerticalView.getViewTreeObserver().removeOnPreDrawListener(this);
+ return true;
+ }
if (mState == STATE_INIT) {
setExpand(true);
mState = STATE_FIRST_DRAW;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/SearchFragment.java b/v17/leanback/src/android/support/v17/leanback/app/SearchFragment.java
index fc93625f4d..d828963cf4 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/SearchFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/SearchFragment.java
@@ -34,6 +34,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.inputmethod.CompletionInfo;
import android.widget.FrameLayout;
import android.support.v17.leanback.R;
@@ -478,6 +479,17 @@ public class SearchFragment extends Fragment {
}
/**
+ * Displays the completions shown by the IME. An application may provide
+ * a list of query completions that the system will show in the IME.
+ *
+ * @param completions A list of completions to show in the IME. Setting to
+ * null or empty will clear the list.
+ */
+ public void displayCompletions(CompletionInfo[] completions) {
+ mSearchBar.displayCompletions(completions);
+ }
+
+ /**
* Sets this callback to have the fragment pass speech recognition requests
* to the activity rather than using an internal recognizer.
*/
diff --git a/v17/leanback/src/android/support/v17/leanback/app/SearchSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/SearchSupportFragment.java
index e06f7e8da9..7ff364e478 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/SearchSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/SearchSupportFragment.java
@@ -36,6 +36,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.inputmethod.CompletionInfo;
import android.widget.FrameLayout;
import android.support.v17.leanback.R;
@@ -480,6 +481,17 @@ public class SearchSupportFragment extends Fragment {
}
/**
+ * Displays the completions shown by the IME. An application may provide
+ * a list of query completions that the system will show in the IME.
+ *
+ * @param completions A list of completions to show in the IME. Setting to
+ * null or empty will clear the list.
+ */
+ public void displayCompletions(CompletionInfo[] completions) {
+ mSearchBar.displayCompletions(completions);
+ }
+
+ /**
* Sets this callback to have the fragment pass speech recognition requests
* to the activity rather than using an internal recognizer.
*/
diff --git a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java
index 6b6cc2e273..3e51989e31 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java
@@ -15,6 +15,7 @@ package android.support.v17.leanback.app;
import android.support.annotation.ColorInt;
import android.support.v17.leanback.R;
+import android.support.v17.leanback.transition.TransitionHelper;
import android.support.v17.leanback.widget.BrowseFrameLayout;
import android.support.v17.leanback.widget.OnChildLaidOutListener;
import android.support.v17.leanback.widget.OnItemViewClickedListener;
@@ -38,7 +39,7 @@ import android.view.ViewGroup;
* <p>Renders a vertical grid of objects given a {@link VerticalGridPresenter} and
* an {@link ObjectAdapter}.
*/
-public class VerticalGridFragment extends BrandedFragment {
+public class VerticalGridFragment extends BaseFragment {
private static final String TAG = "VerticalGridFragment";
private static boolean DEBUG = false;
@@ -47,6 +48,7 @@ public class VerticalGridFragment extends BrandedFragment {
private VerticalGridPresenter.ViewHolder mGridViewHolder;
private OnItemViewSelectedListener mOnItemViewSelectedListener;
private OnItemViewClickedListener mOnItemViewClickedListener;
+ private Object mSceneAfterEntranceTransition;
private int mSelectedPosition = -1;
/**
@@ -170,6 +172,13 @@ public class VerticalGridFragment extends BrandedFragment {
gridDock.addView(mGridViewHolder.view);
mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener);
+ mSceneAfterEntranceTransition = TransitionHelper.createScene(gridDock, new Runnable() {
+ @Override
+ public void run() {
+ setEntranceTransitionState(true);
+ }
+ });
+
updateAdapter();
}
@@ -183,7 +192,9 @@ public class VerticalGridFragment extends BrandedFragment {
public void onStart() {
super.onStart();
setupFocusSearchListener();
- mGridViewHolder.getGridView().requestFocus();
+ if (isEntranceTransitionEnabled()) {
+ setEntranceTransitionState(false);
+ }
}
@Override
@@ -210,4 +221,19 @@ public class VerticalGridFragment extends BrandedFragment {
}
}
}
+
+ @Override
+ protected Object createEntranceTransition() {
+ return TransitionHelper.loadTransition(getActivity(),
+ R.transition.lb_vertical_grid_entrance_transition);
+ }
+
+ @Override
+ protected void runEntranceTransition(Object entranceTransition) {
+ TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
+ }
+
+ void setEntranceTransitionState(boolean afterTransition) {
+ mGridPresenter.setEntranceTransitionState(mGridViewHolder, afterTransition);
+ }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java
index 0770761399..eb0b3372d6 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java
@@ -17,6 +17,7 @@ package android.support.v17.leanback.app;
import android.support.annotation.ColorInt;
import android.support.v17.leanback.R;
+import android.support.v17.leanback.transition.TransitionHelper;
import android.support.v17.leanback.widget.BrowseFrameLayout;
import android.support.v17.leanback.widget.OnChildLaidOutListener;
import android.support.v17.leanback.widget.OnItemViewClickedListener;
@@ -40,7 +41,7 @@ import android.view.ViewGroup;
* <p>Renders a vertical grid of objects given a {@link VerticalGridPresenter} and
* an {@link ObjectAdapter}.
*/
-public class VerticalGridSupportFragment extends BrandedSupportFragment {
+public class VerticalGridSupportFragment extends BaseSupportFragment {
private static final String TAG = "VerticalGridSupportFragment";
private static boolean DEBUG = false;
@@ -49,6 +50,7 @@ public class VerticalGridSupportFragment extends BrandedSupportFragment {
private VerticalGridPresenter.ViewHolder mGridViewHolder;
private OnItemViewSelectedListener mOnItemViewSelectedListener;
private OnItemViewClickedListener mOnItemViewClickedListener;
+ private Object mSceneAfterEntranceTransition;
private int mSelectedPosition = -1;
/**
@@ -172,6 +174,13 @@ public class VerticalGridSupportFragment extends BrandedSupportFragment {
gridDock.addView(mGridViewHolder.view);
mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener);
+ mSceneAfterEntranceTransition = TransitionHelper.createScene(gridDock, new Runnable() {
+ @Override
+ public void run() {
+ setEntranceTransitionState(true);
+ }
+ });
+
updateAdapter();
}
@@ -185,7 +194,9 @@ public class VerticalGridSupportFragment extends BrandedSupportFragment {
public void onStart() {
super.onStart();
setupFocusSearchListener();
- mGridViewHolder.getGridView().requestFocus();
+ if (isEntranceTransitionEnabled()) {
+ setEntranceTransitionState(false);
+ }
}
@Override
@@ -212,4 +223,19 @@ public class VerticalGridSupportFragment extends BrandedSupportFragment {
}
}
}
+
+ @Override
+ protected Object createEntranceTransition() {
+ return TransitionHelper.loadTransition(getActivity(),
+ R.transition.lb_vertical_grid_entrance_transition);
+ }
+
+ @Override
+ protected void runEntranceTransition(Object entranceTransition) {
+ TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
+ }
+
+ void setEntranceTransitionState(boolean afterTransition) {
+ mGridPresenter.setEntranceTransitionState(mGridViewHolder, afterTransition);
+ }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/transition/LeanbackTransitionHelper.java b/v17/leanback/src/android/support/v17/leanback/transition/LeanbackTransitionHelper.java
index f7451d426a..47495cb866 100644
--- a/v17/leanback/src/android/support/v17/leanback/transition/LeanbackTransitionHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/transition/LeanbackTransitionHelper.java
@@ -30,9 +30,9 @@ public class LeanbackTransitionHelper {
static interface LeanbackTransitionHelperVersion {
- public Object loadTitleInTransition(Context context, TransitionHelper helper);
+ public Object loadTitleInTransition(Context context);
- public Object loadTitleOutTransition(Context context, TransitionHelper helper);
+ public Object loadTitleOutTransition(Context context);
}
/*
@@ -42,12 +42,12 @@ public class LeanbackTransitionHelper {
static class LeanbackTransitionHelperKitKatImpl implements LeanbackTransitionHelperVersion {
@Override
- public Object loadTitleInTransition(Context context, TransitionHelper helper) {
+ public Object loadTitleInTransition(Context context) {
return LeanbackTransitionHelperKitKat.loadTitleInTransition(context);
}
@Override
- public Object loadTitleOutTransition(Context context, TransitionHelper helper) {
+ public Object loadTitleOutTransition(Context context) {
return LeanbackTransitionHelperKitKat.loadTitleOutTransition(context);
}
}
@@ -58,13 +58,13 @@ public class LeanbackTransitionHelper {
static class LeanbackTransitionHelperDefault implements LeanbackTransitionHelperVersion {
@Override
- public Object loadTitleInTransition(Context context, TransitionHelper helper) {
- return helper.loadTransition(context, R.transition.lb_title_in);
+ public Object loadTitleInTransition(Context context) {
+ return TransitionHelper.loadTransition(context, R.transition.lb_title_in);
}
@Override
- public Object loadTitleOutTransition(Context context, TransitionHelper helper) {
- return helper.loadTransition(context, R.transition.lb_title_out);
+ public Object loadTitleOutTransition(Context context) {
+ return TransitionHelper.loadTransition(context, R.transition.lb_title_out);
}
}
@@ -81,11 +81,11 @@ public class LeanbackTransitionHelper {
}
}
- static public Object loadTitleInTransition(Context context, TransitionHelper helper) {
- return sImpl.loadTitleInTransition(context, helper);
+ static public Object loadTitleInTransition(Context context) {
+ return sImpl.loadTitleInTransition(context);
}
- static public Object loadTitleOutTransition(Context context, TransitionHelper helper) {
- return sImpl.loadTitleOutTransition(context, helper);
+ static public Object loadTitleOutTransition(Context context) {
+ return sImpl.loadTitleOutTransition(context);
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/transition/TransitionHelper.java b/v17/leanback/src/android/support/v17/leanback/transition/TransitionHelper.java
index 1c66d0309b..9420154f7c 100644
--- a/v17/leanback/src/android/support/v17/leanback/transition/TransitionHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/transition/TransitionHelper.java
@@ -20,6 +20,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
+import java.util.ArrayList;
+
/**
* Helper for view transitions.
* @hide
@@ -34,8 +36,7 @@ public final class TransitionHelper {
public static final int SLIDE_RIGHT = Gravity.RIGHT;
public static final int SLIDE_BOTTOM = Gravity.BOTTOM;
- private final static TransitionHelper sHelper = new TransitionHelper();
- TransitionHelperVersionImpl mImpl;
+ private static TransitionHelperVersionImpl sImpl;
/**
* Gets whether the system supports Transition animations.
@@ -62,6 +63,16 @@ public final class TransitionHelper {
*/
static interface TransitionHelperVersionImpl {
+ public void setEnterTransition(android.app.Fragment fragment, Object transition);
+
+ public void setExitTransition(android.app.Fragment fragment, Object transition);
+
+ public void setSharedElementEnterTransition(android.app.Fragment fragment,
+ Object transition);
+
+ public void addSharedElement(android.app.FragmentTransaction ft,
+ View view, String transitionName);
+
public Object getSharedElementEnterTransition(Window window);
public Object getSharedElementReturnTransition(Window window);
@@ -90,6 +101,8 @@ public final class TransitionHelper {
public Object createChangeBounds(boolean reparent);
+ public Object createFadeAndShortSlide(int edge);
+
public void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay);
public void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay);
@@ -103,7 +116,9 @@ public final class TransitionHelper {
public void addTransition(Object transitionSet, Object transition);
- public void setTransitionListener(Object transition, TransitionListener listener);
+ public void addTransitionListener(Object transition, TransitionListener listener);
+
+ public void removeTransitionListener(Object transition, TransitionListener listener);
public void runTransition(Object scene, Object transition);
@@ -130,15 +145,31 @@ public final class TransitionHelper {
public Object createDefaultInterpolator(Context context);
public Object loadTransition(Context context, int resId);
+
+ public void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup);
}
/**
* Interface used when we do not support Transition animations.
*/
- private static final class TransitionHelperStubImpl implements TransitionHelperVersionImpl {
+ static class TransitionHelperStubImpl implements TransitionHelperVersionImpl {
private static class TransitionStub {
- TransitionListener mTransitionListener;
+ ArrayList<TransitionListener> mTransitionListeners;
+ }
+
+ public void setEnterTransition(android.app.Fragment fragment, Object transition) {
+ }
+
+ public void setExitTransition(android.app.Fragment fragment, Object transition) {
+ }
+
+ public void setSharedElementEnterTransition(android.app.Fragment fragment,
+ Object transition) {
+ }
+
+ public void addSharedElement(android.app.FragmentTransaction ft,
+ View view, String transitionName) {
}
@Override
@@ -202,6 +233,11 @@ public final class TransitionHelper {
}
@Override
+ public Object createFadeAndShortSlide(int edge) {
+ return new TransitionStub();
+ }
+
+ @Override
public Object createSlide(int slideEdge) {
return new TransitionStub();
}
@@ -270,22 +306,38 @@ public final class TransitionHelper {
}
@Override
- public void setTransitionListener(Object transition, TransitionListener listener) {
- ((TransitionStub) transition).mTransitionListener = listener;
+ public void addTransitionListener(Object transition, TransitionListener listener) {
+ TransitionStub stub = (TransitionStub) transition;
+ if (stub.mTransitionListeners == null) {
+ stub.mTransitionListeners = new ArrayList<TransitionListener>();
+ }
+ stub.mTransitionListeners.add(listener);
+ }
+
+ @Override
+ public void removeTransitionListener(Object transition, TransitionListener listener) {
+ TransitionStub stub = (TransitionStub) transition;
+ if (stub.mTransitionListeners != null) {
+ stub.mTransitionListeners.remove(listener);
+ }
}
@Override
public void runTransition(Object scene, Object transition) {
TransitionStub transitionStub = (TransitionStub) transition;
- if (transitionStub != null && transitionStub.mTransitionListener != null) {
- transitionStub.mTransitionListener.onTransitionStart(transition);
+ if (transitionStub != null && transitionStub.mTransitionListeners != null) {
+ for (int i = 0, size = transitionStub.mTransitionListeners.size(); i < size; i++) {
+ transitionStub.mTransitionListeners.get(i).onTransitionStart(transition);
+ }
}
Runnable r = ((Runnable) scene);
if (r != null) {
r.run();
}
- if (transitionStub != null && transitionStub.mTransitionListener != null) {
- transitionStub.mTransitionListener.onTransitionEnd(transition);
+ if (transitionStub != null && transitionStub.mTransitionListeners != null) {
+ for (int i = 0, size = transitionStub.mTransitionListeners.size(); i < size; i++) {
+ transitionStub.mTransitionListeners.get(i).onTransitionEnd(transition);
+ }
}
}
@@ -306,52 +358,16 @@ public final class TransitionHelper {
public Object loadTransition(Context context, int resId) {
return new TransitionStub();
}
+
+ @Override
+ public void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
+ }
}
/**
* Implementation used on KitKat (and above).
*/
- private static class TransitionHelperKitkatImpl implements TransitionHelperVersionImpl {
-
- @Override
- public Object getSharedElementEnterTransition(Window window) {
- return null;
- }
-
- @Override
- public Object getSharedElementReturnTransition(Window window) {
- return null;
- }
-
- @Override
- public Object getSharedElementExitTransition(Window window) {
- return null;
- }
-
- @Override
- public Object getSharedElementReenterTransition(Window window) {
- return null;
- }
-
- @Override
- public Object getEnterTransition(Window window) {
- return null;
- }
-
- @Override
- public Object getReturnTransition(Window window) {
- return null;
- }
-
- @Override
- public Object getExitTransition(Window window) {
- return null;
- }
-
- @Override
- public Object getReenterTransition(Window window) {
- return null;
- }
+ static class TransitionHelperKitkatImpl extends TransitionHelperStubImpl {
@Override
public Object createScene(ViewGroup sceneRoot, Runnable r) {
@@ -455,8 +471,13 @@ public final class TransitionHelper {
}
@Override
- public void setTransitionListener(Object transition, TransitionListener listener) {
- TransitionHelperKitkat.setTransitionListener(transition, listener);
+ public void addTransitionListener(Object transition, TransitionListener listener) {
+ TransitionHelperKitkat.addTransitionListener(transition, listener);
+ }
+
+ @Override
+ public void removeTransitionListener(Object transition, TransitionListener listener) {
+ TransitionHelperKitkat.removeTransitionListener(transition, listener);
}
@Override
@@ -485,7 +506,25 @@ public final class TransitionHelper {
}
}
- private static final class TransitionHelperApi21Impl extends TransitionHelperKitkatImpl {
+ static final class TransitionHelperApi21Impl extends TransitionHelperKitkatImpl {
+
+ public void setEnterTransition(android.app.Fragment fragment, Object transition) {
+ TransitionHelperApi21.setEnterTransition(fragment, transition);
+ }
+
+ public void setExitTransition(android.app.Fragment fragment, Object transition) {
+ TransitionHelperApi21.setExitTransition(fragment, transition);
+ }
+
+ public void setSharedElementEnterTransition(android.app.Fragment fragment,
+ Object transition) {
+ TransitionHelperApi21.setSharedElementEnterTransition(fragment, transition);
+ }
+
+ public void addSharedElement(android.app.FragmentTransaction ft,
+ View view, String transitionName) {
+ TransitionHelperApi21.addSharedElement(ft, view, transitionName);
+ }
@Override
public Object getSharedElementEnterTransition(Window window) {
@@ -508,6 +547,11 @@ public final class TransitionHelper {
}
@Override
+ public Object createFadeAndShortSlide(int edge) {
+ return TransitionHelperApi21.createFadeAndShortSlide(edge);
+ }
+
+ @Override
public Object getEnterTransition(Window window) {
return TransitionHelperApi21.getEnterTransition(window);
}
@@ -536,159 +580,207 @@ public final class TransitionHelper {
public Object createDefaultInterpolator(Context context) {
return TransitionHelperApi21.createDefaultInterpolator(context);
}
- }
- /**
- * Returns the TransitionHelper that can be used to perform Transition
- * animations.
- */
- public static TransitionHelper getInstance() {
- return sHelper;
+ @Override
+ public void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
+ TransitionHelperApi21.setTransitionGroup(viewGroup, transitionGroup);
+ }
}
- private TransitionHelper() {
+ static {
if (Build.VERSION.SDK_INT >= 21) {
- mImpl = new TransitionHelperApi21Impl();
+ sImpl = new TransitionHelperApi21Impl();
} else if (systemSupportsTransitions()) {
- mImpl = new TransitionHelperKitkatImpl();
+ sImpl = new TransitionHelperKitkatImpl();
} else {
- mImpl = new TransitionHelperStubImpl();
+ sImpl = new TransitionHelperStubImpl();
}
}
- public Object getSharedElementEnterTransition(Window window) {
- return mImpl.getSharedElementEnterTransition(window);
+ public static Object getSharedElementEnterTransition(Window window) {
+ return sImpl.getSharedElementEnterTransition(window);
+ }
+
+ public static Object getSharedElementReturnTransition(Window window) {
+ return sImpl.getSharedElementReturnTransition(window);
+ }
+
+ public static Object getSharedElementExitTransition(Window window) {
+ return sImpl.getSharedElementExitTransition(window);
+ }
+
+ public static Object getSharedElementReenterTransition(Window window) {
+ return sImpl.getSharedElementReenterTransition(window);
+ }
+
+ public static Object getEnterTransition(Window window) {
+ return sImpl.getEnterTransition(window);
+ }
+
+ public static Object getReturnTransition(Window window) {
+ return sImpl.getReturnTransition(window);
+ }
+
+ public static Object getExitTransition(Window window) {
+ return sImpl.getExitTransition(window);
+ }
+
+ public static Object getReenterTransition(Window window) {
+ return sImpl.getReenterTransition(window);
+ }
+
+ public static Object createScene(ViewGroup sceneRoot, Runnable r) {
+ return sImpl.createScene(sceneRoot, r);
+ }
+
+ public static Object createChangeBounds(boolean reparent) {
+ return sImpl.createChangeBounds(reparent);
+ }
+
+ public static void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) {
+ sImpl.setChangeBoundsStartDelay(changeBounds, view, startDelay);
+ }
+
+ public static void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) {
+ sImpl.setChangeBoundsStartDelay(changeBounds, viewId, startDelay);
}
- public Object getSharedElementReturnTransition(Window window) {
- return mImpl.getSharedElementReturnTransition(window);
+ public static void setChangeBoundsStartDelay(Object changeBounds, String className,
+ int startDelay) {
+ sImpl.setChangeBoundsStartDelay(changeBounds, className, startDelay);
}
- public Object getSharedElementExitTransition(Window window) {
- return mImpl.getSharedElementExitTransition(window);
+ public static void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) {
+ sImpl.setChangeBoundsDefaultStartDelay(changeBounds, startDelay);
}
- public Object getSharedElementReenterTransition(Window window) {
- return mImpl.getSharedElementReenterTransition(window);
+ public static Object createTransitionSet(boolean sequential) {
+ return sImpl.createTransitionSet(sequential);
}
- public Object getEnterTransition(Window window) {
- return mImpl.getEnterTransition(window);
+ public static Object createSlide(int slideEdge) {
+ return sImpl.createSlide(slideEdge);
}
- public Object getReturnTransition(Window window) {
- return mImpl.getReturnTransition(window);
+ public static Object createScale() {
+ return sImpl.createScale();
}
- public Object getExitTransition(Window window) {
- return mImpl.getExitTransition(window);
+ public static void addTransition(Object transitionSet, Object transition) {
+ sImpl.addTransition(transitionSet, transition);
}
- public Object getReenterTransition(Window window) {
- return mImpl.getReenterTransition(window);
+ public static void exclude(Object transition, int targetId, boolean exclude) {
+ sImpl.exclude(transition, targetId, exclude);
}
- public Object createScene(ViewGroup sceneRoot, Runnable r) {
- return mImpl.createScene(sceneRoot, r);
+ public static void exclude(Object transition, View targetView, boolean exclude) {
+ sImpl.exclude(transition, targetView, exclude);
}
- public Object createChangeBounds(boolean reparent) {
- return mImpl.createChangeBounds(reparent);
+ public static void excludeChildren(Object transition, int targetId, boolean exclude) {
+ sImpl.excludeChildren(transition, targetId, exclude);
}
- public void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) {
- mImpl.setChangeBoundsStartDelay(changeBounds, view, startDelay);
+ public static void excludeChildren(Object transition, View targetView, boolean exclude) {
+ sImpl.excludeChildren(transition, targetView, exclude);
}
- public void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) {
- mImpl.setChangeBoundsStartDelay(changeBounds, viewId, startDelay);
+ public static void include(Object transition, int targetId) {
+ sImpl.include(transition, targetId);
}
- public void setChangeBoundsStartDelay(Object changeBounds, String className, int startDelay) {
- mImpl.setChangeBoundsStartDelay(changeBounds, className, startDelay);
+ public static void include(Object transition, View targetView) {
+ sImpl.include(transition, targetView);
}
- public void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) {
- mImpl.setChangeBoundsDefaultStartDelay(changeBounds, startDelay);
+ public static void setStartDelay(Object transition, long startDelay) {
+ sImpl.setStartDelay(transition, startDelay);
}
- public Object createTransitionSet(boolean sequential) {
- return mImpl.createTransitionSet(sequential);
+ public static void setDuration(Object transition, long duration) {
+ sImpl.setDuration(transition, duration);
}
- public Object createSlide(int slideEdge) {
- return mImpl.createSlide(slideEdge);
+ public static Object createAutoTransition() {
+ return sImpl.createAutoTransition();
}
- public Object createScale() {
- return mImpl.createScale();
+ public static Object createFadeTransition(int fadeMode) {
+ return sImpl.createFadeTransition(fadeMode);
}
- public void addTransition(Object transitionSet, Object transition) {
- mImpl.addTransition(transitionSet, transition);
+ public static void addTransitionListener(Object transition, TransitionListener listener) {
+ sImpl.addTransitionListener(transition, listener);
}
- public void exclude(Object transition, int targetId, boolean exclude) {
- mImpl.exclude(transition, targetId, exclude);
+ public static void removeTransitionListener(Object transition, TransitionListener listener) {
+ sImpl.removeTransitionListener(transition, listener);
}
- public void exclude(Object transition, View targetView, boolean exclude) {
- mImpl.exclude(transition, targetView, exclude);
+ public static void runTransition(Object scene, Object transition) {
+ sImpl.runTransition(scene, transition);
}
- public void excludeChildren(Object transition, int targetId, boolean exclude) {
- mImpl.excludeChildren(transition, targetId, exclude);
+ public static void setInterpolator(Object transition, Object timeInterpolator) {
+ sImpl.setInterpolator(transition, timeInterpolator);
}
- public void excludeChildren(Object transition, View targetView, boolean exclude) {
- mImpl.excludeChildren(transition, targetView, exclude);
+ public static void addTarget(Object transition, View view) {
+ sImpl.addTarget(transition, view);
}
- public void include(Object transition, int targetId) {
- mImpl.include(transition, targetId);
+ public static Object createDefaultInterpolator(Context context) {
+ return sImpl.createDefaultInterpolator(context);
}
- public void include(Object transition, View targetView) {
- mImpl.include(transition, targetView);
+ public static Object loadTransition(Context context, int resId) {
+ return sImpl.loadTransition(context, resId);
}
- public void setStartDelay(Object transition, long startDelay) {
- mImpl.setStartDelay(transition, startDelay);
+ public static void setEnterTransition(android.app.Fragment fragment, Object transition) {
+ sImpl.setEnterTransition(fragment, transition);
}
- public void setDuration(Object transition, long duration) {
- mImpl.setDuration(transition, duration);
+ public static void setExitTransition(android.app.Fragment fragment, Object transition) {
+ sImpl.setExitTransition(fragment, transition);
}
- public Object createAutoTransition() {
- return mImpl.createAutoTransition();
+ public static void setSharedElementEnterTransition(android.app.Fragment fragment,
+ Object transition) {
+ sImpl.setSharedElementEnterTransition(fragment, transition);
}
- public Object createFadeTransition(int fadeMode) {
- return mImpl.createFadeTransition(fadeMode);
+ public static void addSharedElement(android.app.FragmentTransaction ft,
+ View view, String transitionName) {
+ sImpl.addSharedElement(ft, view, transitionName);
}
- public void setTransitionListener(Object transition, TransitionListener listener) {
- mImpl.setTransitionListener(transition, listener);
+ public static void setEnterTransition(android.support.v4.app.Fragment fragment,
+ Object transition) {
+ fragment.setEnterTransition(transition);
}
- public void runTransition(Object scene, Object transition) {
- mImpl.runTransition(scene, transition);
+ public static void setExitTransition(android.support.v4.app.Fragment fragment,
+ Object transition) {
+ fragment.setExitTransition(transition);
}
- public void setInterpolator(Object transition, Object timeInterpolator) {
- mImpl.setInterpolator(transition, timeInterpolator);
+ public static void setSharedElementEnterTransition(android.support.v4.app.Fragment fragment,
+ Object transition) {
+ fragment.setSharedElementEnterTransition(transition);
}
- public void addTarget(Object transition, View view) {
- mImpl.addTarget(transition, view);
+ public static void addSharedElement(android.support.v4.app.FragmentTransaction ft,
+ View view, String transitionName) {
+ ft.addSharedElement(view, transitionName);
}
- public Object createDefaultInterpolator(Context context) {
- return mImpl.createDefaultInterpolator(context);
+ public static Object createFadeAndShortSlide(int edge) {
+ return sImpl.createFadeAndShortSlide(edge);
}
- public Object loadTransition(Context context, int resId) {
- return mImpl.loadTransition(context, resId);
+ public static void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
+ sImpl.setTransitionGroup(viewGroup, transitionGroup);
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java b/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java
index 614f12b4dc..085aac3399 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java
@@ -18,6 +18,7 @@ package android.support.v17.leanback.widget;
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.support.v17.leanback.R;
import android.util.AttributeSet;
import android.util.Log;
@@ -154,6 +155,14 @@ public class BaseCardView extends FrameLayout {
try {
mCardType = a.getInteger(R.styleable.lbBaseCardView_cardType, CARD_TYPE_MAIN_ONLY);
+ Drawable cardForeground = a.getDrawable(R.styleable.lbBaseCardView_cardForeground);
+ if (cardForeground != null) {
+ setForeground(cardForeground);
+ }
+ Drawable cardBackground = a.getDrawable(R.styleable.lbBaseCardView_cardBackground);
+ if (cardBackground != null) {
+ setBackground(cardBackground);
+ }
mInfoVisibility = a.getInteger(R.styleable.lbBaseCardView_infoVisibility,
CARD_REGION_VISIBLE_ACTIVATED);
mExtraVisibility = a.getInteger(R.styleable.lbBaseCardView_extraVisibility,
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/BaseGridView.java b/v17/leanback/src/android/support/v17/leanback/widget/BaseGridView.java
index 93a454e3a0..73e5b4071c 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/BaseGridView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/BaseGridView.java
@@ -23,6 +23,7 @@ import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.support.v7.widget.SimpleItemAnimator;
/**
* An abstract base class for vertically and horizontally scrolling lists. The items come
@@ -201,7 +202,7 @@ abstract class BaseGridView extends RecyclerView {
// Disable change animation by default on leanback.
// Change animation will create a new view and cause undesired
// focus animation between the old view and new view.
- getItemAnimator().setSupportsChangeAnimations(false);
+ ((SimpleItemAnimator)getItemAnimator()).setSupportsChangeAnimations(false);
super.setRecyclerListener(new RecyclerView.RecyclerListener() {
@Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/CheckableImageView.java b/v17/leanback/src/android/support/v17/leanback/widget/CheckableImageView.java
new file mode 100644
index 0000000000..627bbd4fc8
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/CheckableImageView.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.Checkable;
+import android.widget.ImageView;
+
+/**
+ * ImageView that supports Checkable states.
+ */
+class CheckableImageView extends ImageView implements Checkable {
+
+ private boolean mChecked;
+
+ private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };
+
+ public CheckableImageView(Context context) {
+ this(context, null);
+ }
+
+ public CheckableImageView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public CheckableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public int[] onCreateDrawableState(final int extraSpace) {
+ final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
+ if (isChecked()) {
+ mergeDrawableStates(drawableState, CHECKED_STATE_SET);
+ }
+ return drawableState;
+ }
+
+ @Override
+ public void toggle() {
+ setChecked(!mChecked);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mChecked;
+ }
+
+ @Override
+ public void setChecked(final boolean checked) {
+ if (mChecked != checked) {
+ mChecked = checked;
+ refreshDrawableState();
+ }
+ }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper.java
index 410aa28d65..cac7d9eb41 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper.java
@@ -232,11 +232,10 @@ final class DetailsOverviewSharedElementHelper extends SharedElementCallback {
Log.d(TAG, "setTransitionName "+mViewHolder.mOverviewFrame);
}
ViewCompat.setTransitionName(mViewHolder.mOverviewFrame, mSharedElementName);
- final TransitionHelper transitionHelper = TransitionHelper.getInstance();
- Object transition = transitionHelper.getSharedElementEnterTransition(
+ Object transition = TransitionHelper.getSharedElementEnterTransition(
mActivityToRunTransition.getWindow());
if (transition != null) {
- transitionHelper.setTransitionListener(transition, new TransitionListener() {
+ TransitionHelper.addTransitionListener(transition, new TransitionListener() {
@Override
public void onTransitionEnd(Object transition) {
if (DEBUG) {
@@ -247,7 +246,7 @@ final class DetailsOverviewSharedElementHelper extends SharedElementCallback {
if (mViewHolder.mActionsRow.isFocused()) {
mViewHolder.mActionsRow.requestFocus();
}
- transitionHelper.setTransitionListener(transition, null);
+ TransitionHelper.removeTransitionListener(transition, this);
}
});
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java
index 48829eb72f..87bbbd47af 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java
@@ -85,7 +85,7 @@ public class FocusHighlightHelper {
mWrapper = null;
}
mAnimator.setTimeListener(this);
- if (mWrapper != null && useDimmer) {
+ if (useDimmer) {
mDimmer = ColorOverlayDimmer.createDefault(view.getContext());
} else {
mDimmer = null;
@@ -99,9 +99,16 @@ public class FocusHighlightHelper {
mView.setScaleY(scale);
if (mWrapper != null) {
mWrapper.setShadowFocusLevel(level);
- if (mDimmer != null) {
- mDimmer.setActiveLevel(level);
- mWrapper.setOverlayColor(mDimmer.getPaint().getColor());
+ } else {
+ ShadowOverlayHelper.setNoneWrapperShadowFocusLevel(mView, level);
+ }
+ if (mDimmer != null) {
+ mDimmer.setActiveLevel(level);
+ int color = mDimmer.getPaint().getColor();
+ if (mWrapper != null) {
+ mWrapper.setOverlayColor(color);
+ } else {
+ ShadowOverlayHelper.setNoneWrapperOverlayColor(mView, color);
}
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java
new file mode 100644
index 0000000000..c9bed58c4c
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java
@@ -0,0 +1,78 @@
+package android.support.v17.leanback.widget;
+
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.view.View;
+import android.view.ViewGroup;
+
+final class ForegroundHelper {
+
+ final static ForegroundHelper sInstance = new ForegroundHelper();
+ ForegroundHelperVersionImpl mImpl;
+
+ /**
+ * Interface implemented by classes that support Shadow.
+ */
+ static interface ForegroundHelperVersionImpl {
+
+ public void setForeground(View view, Drawable drawable);
+
+ public Drawable getForeground(View view);
+ }
+
+ /**
+ * Implementation used on api 23 (and above).
+ */
+ private static final class ForegroundHelperApi23Impl implements ForegroundHelperVersionImpl {
+ @Override
+ public void setForeground(View view, Drawable drawable) {
+ ForegroundHelperApi23.setForeground(view, drawable);
+ }
+
+ @Override
+ public Drawable getForeground(View view) {
+ return ForegroundHelperApi23.getForeground(view);
+ }
+ }
+
+ /**
+ * Stub implementation
+ */
+ private static final class ForegroundHelperStubImpl implements ForegroundHelperVersionImpl {
+ @Override
+ public void setForeground(View view, Drawable drawable) {
+ }
+
+ @Override
+ public Drawable getForeground(View view) {
+ return null;
+ }
+ }
+
+ private ForegroundHelper() {
+ if (supportsForeground()) {
+ mImpl = new ForegroundHelperApi23Impl();
+ } else {
+ mImpl = new ForegroundHelperStubImpl();
+ }
+ }
+
+ public static ForegroundHelper getInstance() {
+ return sInstance;
+ }
+
+ /**
+ * Returns true if view.setForeground() is supported.
+ */
+ public static boolean supportsForeground() {
+ return Build.VERSION.SDK_INT >= 23;
+ }
+
+ public Drawable getForeground(View view) {
+ return mImpl.getForeground(view);
+ }
+
+ public void setForeground(View view, Drawable drawable) {
+ mImpl.setForeground(view, drawable);
+ }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java b/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java
index 8bd0007c59..1c5dcb5f42 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java
@@ -26,47 +26,15 @@ import java.util.List;
public interface FragmentAnimationProvider {
/**
- * Animates the entry of the fragment in the case where the activity is first being presented.
+ * Animates the fragment in response to the IME appearing.
* @param animators A list of animations to which this provider's animations should be added.
*/
- public abstract void onActivityEnter(@NonNull List<Animator> animators);
+ public abstract void onImeAppearing(@NonNull List<Animator> animators);
/**
- * Animates the exit of the fragment in the case where the activity is about to pause.
+ * Animates the fragment in response to the IME disappearing.
* @param animators A list of animations to which this provider's animations should be added.
*/
- public abstract void onActivityExit(@NonNull List<Animator> animators);
-
- /**
- * Animates the entry of the fragment in the case where there is a previous step fragment
- * participating in the animation. Entry occurs when the fragment is preparing to be shown
- * as it is pushed onto the back stack.
- * @param animators A list of animations to which this provider's animations should be added.
- */
- public abstract void onFragmentEnter(@NonNull List<Animator> animators);
-
- /**
- * Animates the exit of the fragment in the case where there is a previous step fragment
- * participating in the animation. Exit occurs when the fragment is preparing to be removed,
- * hidden, or detached due to pushing another fragment onto the back stack.
- * @param animators A list of animations to which this provider's animations should be added.
- */
- public abstract void onFragmentExit(@NonNull List<Animator> animators);
-
- /**
- * Animates the re-entry of the fragment in the case where there is a previous step fragment
- * participating in the animation. Re-entry occurs when the fragment is preparing to be shown
- * due to popping the back stack.
- * @param animators A list of animations to which this provider's animations should be added.
- */
- public abstract void onFragmentReenter(@NonNull List<Animator> animators);
-
- /**
- * Animates the return of the fragment in the case where there is a previous step fragment
- * participating in the animation. Return occurs when the fragment is preparing to be removed,
- * hidden, or detached due to popping the back stack.
- * @param animators A list of animations to which this provider's animations should be added.
- */
- public abstract void onFragmentReturn(@NonNull List<Animator> animators);
+ public abstract void onImeDisappearing(@NonNull List<Animator> animators);
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter.java
index c4418c1644..7c9d5db2ff 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter.java
@@ -528,19 +528,6 @@ public class FullWidthDetailsOverviewRowPresenter extends RowPresenter {
mListener = listener;
}
- private int getDefaultBackgroundColor(Context context) {
- TypedValue outValue = new TypedValue();
- if (context.getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true)) {
- return context.getResources().getColor(outValue.resourceId);
- }
- return context.getResources().getColor(R.color.lb_default_brand_color);
- }
-
- private int getDefaultActionsBackgroundColor(Context context) {
- int c = getDefaultBackgroundColor(context);
- return Color.argb(Color.alpha(c), Color.red(c) / 2, Color.green(c) / 2, Color.blue(c) / 2);
- }
-
/**
* Get resource id to inflate the layout. The layout must match {@link #STATE_HALF}
*/
@@ -558,13 +545,13 @@ public class FullWidthDetailsOverviewRowPresenter extends RowPresenter {
vh.mActionBridgeAdapter = new ActionsItemBridgeAdapter(vh);
final View overview = vh.mOverviewFrame;
- final int bgColor = mBackgroundColorSet ? mBackgroundColor :
- getDefaultBackgroundColor(overview.getContext());
- overview.setBackgroundColor(bgColor);
- final int actionBgColor = mActionsBackgroundColorSet ? mActionsBackgroundColor :
- getDefaultActionsBackgroundColor(overview.getContext());
- overview.findViewById(R.id.details_overview_actions_background)
- .setBackgroundColor(actionBgColor);
+ if (mBackgroundColorSet) {
+ overview.setBackgroundColor(mBackgroundColor);
+ }
+ if (mActionsBackgroundColorSet) {
+ overview.findViewById(R.id.details_overview_actions_background)
+ .setBackgroundColor(mActionsBackgroundColor);
+ }
RoundedRectHelper.getInstance().setClipToRoundedOutline(overview, true);
if (!getSelectEffectEnabled()) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper.java
index 857c4d922c..a9fe9ecd2a 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper.java
@@ -76,8 +76,7 @@ public class FullWidthDetailsOverviewSharedElementHelper extends
if (DEBUG) {
Log.d(TAG, "postponeEnterTransition " + mActivityToRunTransition);
}
- Object transition = TransitionHelper.getInstance()
- .getSharedElementEnterTransition(activity.getWindow());
+ Object transition = TransitionHelper.getSharedElementEnterTransition(activity.getWindow());
setAutoStartSharedElementTransition(transition != null);
ActivityCompat.postponeEnterTransition(mActivityToRunTransition);
if (timeoutMs > 0) {
@@ -140,11 +139,10 @@ public class FullWidthDetailsOverviewSharedElementHelper extends
}
ViewCompat.setTransitionName(mViewHolder.getLogoViewHolder().view,
mSharedElementName);
- final TransitionHelper transitionHelper = TransitionHelper.getInstance();
- Object transition = transitionHelper.getSharedElementEnterTransition(
+ Object transition = TransitionHelper.getSharedElementEnterTransition(
mActivityToRunTransition.getWindow());
if (transition != null) {
- transitionHelper.setTransitionListener(transition, new TransitionListener() {
+ TransitionHelper.addTransitionListener(transition, new TransitionListener() {
@Override
public void onTransitionEnd(Object transition) {
if (DEBUG) {
@@ -155,7 +153,7 @@ public class FullWidthDetailsOverviewSharedElementHelper extends
if (mViewHolder.getActionsRow().isFocused()) {
mViewHolder.getActionsRow().requestFocus();
}
- transitionHelper.setTransitionListener(transition, null);
+ TransitionHelper.removeTransitionListener(transition, this);
}
});
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
index 10c7e3efd6..20d54e24bb 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -58,7 +58,7 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
* - Saves optical bounds insets.
* - Caches focus align view center.
*/
- static class LayoutParams extends RecyclerView.LayoutParams {
+ final static class LayoutParams extends RecyclerView.LayoutParams {
// For placement
private int mLeftInset;
@@ -128,6 +128,32 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
return view.getHeight() - mTopInset - mBottomInset;
}
+ int getDecoratedOpticalLeftWithMargin(RecyclerView.LayoutManager lm, View view) {
+ return lm.getDecoratedLeft(view) + mLeftInset - leftMargin;
+ }
+
+ int getDecoratedOpticalTopWithMargin(RecyclerView.LayoutManager lm, View view) {
+ return lm.getDecoratedTop(view) + mTopInset - topMargin;
+ }
+
+ int getDecoratedOpticalRightWithMargin(RecyclerView.LayoutManager lm, View view) {
+ return lm.getDecoratedRight(view) - mRightInset + rightMargin;
+ }
+
+ int getDecoratedOpticalBottomWithMargin(RecyclerView.LayoutManager lm, View view) {
+ return lm.getDecoratedBottom(view) - mBottomInset + bottomMargin;
+ }
+
+ int getDecoratedOpticalWidthWithMargin(RecyclerView.LayoutManager lm, View view) {
+ return lm.getDecoratedRight(view) - lm.getDecoratedLeft(view)
+ - mLeftInset - mRightInset + leftMargin + rightMargin;
+ }
+
+ int getDecoratedOpticalHeightWithMargin(RecyclerView.LayoutManager lm, View view) {
+ return lm.getDecoratedBottom(view) - lm.getDecoratedTop(view)
+ - mTopInset - mBottomInset + topMargin + bottomMargin;
+ }
+
int getOpticalLeftInset() {
return mLeftInset;
}
@@ -199,9 +225,18 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
@Override
protected void onStop() {
- // onTargetFound() may not be called if we hit the "wall" first.
+ // onTargetFound() may not be called if we hit the "wall" first or get cancelled.
View targetView = findViewByPosition(getTargetPosition());
- if (hasFocus() && targetView != null) {
+ if (targetView == null) {
+ if (getTargetPosition() >= 0) {
+ // if smooth scroller is stopped without target, immediately jumps
+ // to the target position.
+ scrollToSelection(mBaseGridView, getTargetPosition(), 0, false, 0);
+ }
+ super.onStop();
+ return;
+ }
+ if (hasFocus()) {
mInSelection = true;
targetView.requestFocus();
mInSelection = false;
@@ -391,6 +426,8 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
private RecyclerView.State mState;
private RecyclerView.Recycler mRecycler;
+ private static final Rect sTempRect = new Rect();
+
private boolean mInLayout;
private boolean mInScroll;
private boolean mInFastRelayout;
@@ -913,16 +950,21 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
}
private int getViewMin(View v) {
- return (mOrientation == HORIZONTAL) ? getOpticalLeft(v) : getOpticalTop(v);
+ LayoutParams lp = (LayoutParams) v.getLayoutParams();
+ return (mOrientation == HORIZONTAL) ? lp.getDecoratedOpticalLeftWithMargin(this, v)
+ : lp.getDecoratedOpticalTopWithMargin(this, v);
}
private int getViewMax(View v) {
- return (mOrientation == HORIZONTAL) ? getOpticalRight(v) : getOpticalBottom(v);
+ LayoutParams lp = (LayoutParams) v.getLayoutParams();
+ return (mOrientation == HORIZONTAL) ? lp.getDecoratedOpticalRightWithMargin(this, v)
+ : lp.getDecoratedOpticalBottomWithMargin(this, v);
}
private int getViewPrimarySize(View view) {
LayoutParams p = (LayoutParams) view.getLayoutParams();
- return mOrientation == HORIZONTAL ? p.getOpticalWidth(view) : p.getOpticalHeight(view);
+ return mOrientation == HORIZONTAL ? p.getDecoratedOpticalWidthWithMargin(this, view)
+ : p.getDecoratedOpticalHeightWithMargin(this, view);
}
private int getViewCenter(View view) {
@@ -1056,18 +1098,33 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
return getRowStartSecondary(rightmostIndex) + getRowSizeSecondary(rightmostIndex);
}
+ int getDecoratedMeasuredWidthWithMargin(View v) {
+ final LayoutParams lp = (LayoutParams) v.getLayoutParams();
+ return getDecoratedMeasuredWidth(v) + lp.leftMargin + lp.rightMargin;
+ }
+
+ int getDecoratedMeasuredHeightWithMargin(View v) {
+ final LayoutParams lp = (LayoutParams) v.getLayoutParams();
+ return getDecoratedMeasuredHeight(v) + lp.topMargin + lp.bottomMargin;
+ }
+
private void measureScrapChild(int position, int widthSpec, int heightSpec,
int[] measuredDimension) {
View view = mRecycler.getViewForPosition(position);
if (view != null) {
- LayoutParams p = (LayoutParams) view.getLayoutParams();
+ final LayoutParams p = (LayoutParams) view.getLayoutParams();
+ calculateItemDecorationsForChild(view, sTempRect);
+ int widthUsed = p.leftMargin + p.rightMargin + sTempRect.left + sTempRect.right;
+ int heightUsed = p.topMargin + p.bottomMargin + sTempRect.top + sTempRect.bottom;
+
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
- getPaddingLeft() + getPaddingRight(), p.width);
+ getPaddingLeft() + getPaddingRight() + widthUsed, p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
- getPaddingTop() + getPaddingBottom(), p.height);
+ getPaddingTop() + getPaddingBottom() + heightUsed, p.height);
view.measure(childWidthSpec, childHeightSpec);
- measuredDimension[0] = view.getMeasuredWidth();
- measuredDimension[1] = view.getMeasuredHeight();
+
+ measuredDimension[0] = getDecoratedMeasuredWidthWithMargin(view);
+ measuredDimension[1] = getDecoratedMeasuredHeightWithMargin(view);
mRecycler.recycleView(view);
}
}
@@ -1100,7 +1157,8 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
measureChild(view);
}
final int secondarySize = mOrientation == HORIZONTAL ?
- view.getMeasuredHeight() : view.getMeasuredWidth();
+ getDecoratedMeasuredHeightWithMargin(view)
+ : getDecoratedMeasuredWidthWithMargin(view);
if (secondarySize > rowSize) {
rowSize = secondarySize;
}
@@ -1229,14 +1287,8 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
} else {
switch (modeSecondary) {
case MeasureSpec.UNSPECIFIED:
- if (mRowSizeSecondaryRequested == 0) {
- if (mOrientation == HORIZONTAL) {
- throw new IllegalStateException("Must specify rowHeight or view height");
- } else {
- throw new IllegalStateException("Must specify columnWidth or view width");
- }
- }
- mFixedRowSizeSecondary = mRowSizeSecondaryRequested;
+ mFixedRowSizeSecondary = mRowSizeSecondaryRequested == 0 ?
+ sizeSecondary - paddingSecondary: mRowSizeSecondaryRequested;
mNumRows = mNumRowsRequested == 0 ? 1 : mNumRowsRequested;
measuredSizeSecondary = mFixedRowSizeSecondary * mNumRows + mMarginSecondary
* (mNumRows - 1) + paddingSecondary;
@@ -1287,7 +1339,11 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
private void measureChild(View child) {
if (TRACE) TraceHelper.beginSection("measureChild");
- final ViewGroup.LayoutParams lp = child.getLayoutParams();
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ calculateItemDecorationsForChild(child, sTempRect);
+ int widthUsed = lp.leftMargin + lp.rightMargin + sTempRect.left + sTempRect.right;
+ int heightUsed = lp.topMargin + lp.bottomMargin + sTempRect.top + sTempRect.bottom;
+
final int secondarySpec = (mRowSizeSecondaryRequested == ViewGroup.LayoutParams.WRAP_CONTENT) ?
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) :
MeasureSpec.makeMeasureSpec(mFixedRowSizeSecondary, MeasureSpec.EXACTLY);
@@ -1295,14 +1351,12 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
if (mOrientation == HORIZONTAL) {
widthSpec = ViewGroup.getChildMeasureSpec(
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- 0, lp.width);
- heightSpec = ViewGroup.getChildMeasureSpec(secondarySpec, 0, lp.height);
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), widthUsed, lp.width);
+ heightSpec = ViewGroup.getChildMeasureSpec(secondarySpec, heightUsed, lp.height);
} else {
heightSpec = ViewGroup.getChildMeasureSpec(
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- 0, lp.height);
- widthSpec = ViewGroup.getChildMeasureSpec(secondarySpec, 0, lp.width);
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), heightUsed, lp.height);
+ widthSpec = ViewGroup.getChildMeasureSpec(secondarySpec, widthUsed, lp.width);
}
child.measure(widthSpec, heightSpec);
if (DEBUG) Log.v(getTag(), "measureChild secondarySpec " + Integer.toHexString(secondarySpec) +
@@ -1395,7 +1449,8 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
measureChild(v);
}
item[0] = v;
- return mOrientation == HORIZONTAL ? v.getMeasuredWidth() : v.getMeasuredHeight();
+ return mOrientation == HORIZONTAL ? getDecoratedMeasuredWidthWithMargin(v)
+ : getDecoratedMeasuredHeightWithMargin(v);
}
@Override
@@ -1476,8 +1531,8 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
private void layoutChild(int rowIndex, View v, int start, int end, int startSecondary) {
if (TRACE) TraceHelper.beginSection("layoutChild");
- int sizeSecondary = mOrientation == HORIZONTAL ? v.getMeasuredHeight()
- : v.getMeasuredWidth();
+ int sizeSecondary = mOrientation == HORIZONTAL ? getDecoratedMeasuredHeightWithMargin(v)
+ : getDecoratedMeasuredWidthWithMargin(v);
if (mFixedRowSizeSecondary > 0) {
sizeSecondary = Math.min(sizeSecondary, mFixedRowSizeSecondary);
}
@@ -1507,7 +1562,9 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
bottom = end;
right = startSecondary + sizeSecondary;
}
- v.layout(left, top, right, bottom);
+ LayoutParams params = (LayoutParams) v.getLayoutParams();
+ layoutDecorated(v, left + params.leftMargin, top + params.topMargin,
+ right - params.rightMargin, bottom - params.bottomMargin);
updateChildOpticalInsets(v, left, top, right, bottom);
updateChildAlignments(v);
if (TRACE) TraceHelper.endSection();
@@ -1624,10 +1681,10 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
measureChild(view);
}
if (mOrientation == HORIZONTAL) {
- primarySize = view.getMeasuredWidth();
+ primarySize = getDecoratedMeasuredWidthWithMargin(view);
end = start + primarySize;
} else {
- primarySize = view.getMeasuredHeight();
+ primarySize = getDecoratedMeasuredHeightWithMargin(view);
end = start + primarySize;
}
layoutChild(location.row, view, start, end, startSecondary);
@@ -1716,6 +1773,11 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
mFocusPositionOffset = 0;
saveContext(recycler, state);
+ View savedFocusView = findViewByPosition(mFocusPosition);
+ int savedFocusPos = mFocusPosition;
+ int savedSubFocusPos = mSubFocusPosition;
+ boolean hadFocus = mBaseGridView.hasFocus();
+
// Track the old focus view so we can adjust our system scroll position
// so that any scroll animations happening now will remain valid.
// We must use same delta in Pre Layout (if prelayout exists) and second layout.
@@ -1724,17 +1786,14 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
if (mFocusPosition != NO_POSITION && scrollToFocus
&& mBaseGridView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
// FIXME: we should get the remaining scroll animation offset from RecyclerView
- View focusView = findViewByPosition(mFocusPosition);
- if (focusView != null) {
- if (getScrollPosition(focusView, focusView.findFocus(), sTwoInts)) {
+ if (savedFocusView != null) {
+ if (getScrollPosition(savedFocusView, savedFocusView.findFocus(), sTwoInts)) {
delta = sTwoInts[0];
deltaSecondary = sTwoInts[1];
}
}
}
- boolean hadFocus = mBaseGridView.hasFocus();
- int savedFocusPos = mFocusPosition;
if (mInFastRelayout = layoutInit()) {
fastRelayout();
// appends items till focus position.
@@ -1802,7 +1861,8 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
}
// For fastRelayout, only dispatch event when focus position changes.
- if (mInFastRelayout && mFocusPosition != savedFocusPos) {
+ if (mInFastRelayout && (mFocusPosition != savedFocusPos || mSubFocusPosition !=
+ savedFocusPos || findViewByPosition(mFocusPosition) != savedFocusView)) {
dispatchChildSelected();
} else if (!mInFastRelayout && mInLayoutSearchFocus) {
// For full layout we dispatchChildSelected() in createItem() unless searched all
@@ -1968,7 +2028,7 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
int pos = sTwoInts[1];
int savedMaxEdge = mWindowAlignment.mainAxis().getMaxEdge();
mWindowAlignment.mainAxis().setMaxEdge(maxEdge);
- int maxScroll = getPrimarySystemScrollPosition(findViewByPosition(pos));
+ int maxScroll = getPrimarySystemScrollPositionOfChildMax(findViewByPosition(pos));
mWindowAlignment.mainAxis().setMaxEdge(savedMaxEdge);
if (highAvailable) {
@@ -2319,6 +2379,16 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
return mWindowAlignment.mainAxis().getSystemScrollPos(viewCenterPrimary, isMin, isMax);
}
+ private int getPrimarySystemScrollPositionOfChildMax(View view) {
+ int scrollPosition = getPrimarySystemScrollPosition(view);
+ final LayoutParams lp = (LayoutParams) view.getLayoutParams();
+ int[] multipleAligns = lp.getAlignMultiple();
+ if (multipleAligns != null && multipleAligns.length > 0) {
+ scrollPosition += multipleAligns[multipleAligns.length - 1] - multipleAligns[0];
+ }
+ return scrollPosition;
+ }
+
/**
* Get adjusted primary position for a given childView (if there is multiple ItemAlignment defined
* on the view).
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
index 8d125102f0..3fcdbba524 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
@@ -54,11 +54,8 @@ import java.util.List;
* </ul><p>
* View IDs are allowed to be missing, in which case the corresponding views will be null.
*
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceEntryAnimation
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepEntryAnimation
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepExitAnimation
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReentryAnimation
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReturnAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeAppearingAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeDisappearingAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceContainerStyle
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceTitleStyle
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceDescriptionStyle
@@ -176,6 +173,16 @@ public class GuidanceStylist implements FragmentAnimationProvider {
}
/**
+ * Called when destroy the View created by GuidanceStylist.
+ */
+ public void onDestroyView() {
+ mBreadcrumbView = null;
+ mDescriptionView = null;
+ mIconView = null;
+ mTitleView = null;
+ }
+
+ /**
* Provides the resource ID of the layout defining the guidance view. Subclasses may override
* to provide their own customized layouts. The base implementation returns
* {@link android.support.v17.leanback.R.layout#lb_guidance}. If overridden, the substituted
@@ -223,61 +230,22 @@ public class GuidanceStylist implements FragmentAnimationProvider {
* {@inheritDoc}
*/
@Override
- public void onActivityEnter(@NonNull List<Animator> animators) {
- addAnimator(animators, mTitleView, R.attr.guidanceEntryAnimation);
- addAnimator(animators, mBreadcrumbView, R.attr.guidanceEntryAnimation);
- addAnimator(animators, mDescriptionView, R.attr.guidanceEntryAnimation);
- addAnimator(animators, mIconView, R.attr.guidanceEntryAnimation);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onActivityExit(@NonNull List<Animator> animators) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onFragmentEnter(@NonNull List<Animator> animators) {
- addAnimator(animators, mTitleView, R.attr.guidedStepEntryAnimation);
- addAnimator(animators, mBreadcrumbView, R.attr.guidedStepEntryAnimation);
- addAnimator(animators, mDescriptionView, R.attr.guidedStepEntryAnimation);
- addAnimator(animators, mIconView, R.attr.guidedStepEntryAnimation);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onFragmentExit(@NonNull List<Animator> animators) {
- addAnimator(animators, mTitleView, R.attr.guidedStepExitAnimation);
- addAnimator(animators, mBreadcrumbView, R.attr.guidedStepExitAnimation);
- addAnimator(animators, mDescriptionView, R.attr.guidedStepExitAnimation);
- addAnimator(animators, mIconView, R.attr.guidedStepExitAnimation);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onFragmentReenter(@NonNull List<Animator> animators) {
- addAnimator(animators, mTitleView, R.attr.guidedStepReentryAnimation);
- addAnimator(animators, mBreadcrumbView, R.attr.guidedStepReentryAnimation);
- addAnimator(animators, mDescriptionView, R.attr.guidedStepReentryAnimation);
- addAnimator(animators, mIconView, R.attr.guidedStepReentryAnimation);
+ public void onImeAppearing(@NonNull List<Animator> animators) {
+ addAnimator(animators, mTitleView, R.attr.guidedStepImeAppearingAnimation);
+ addAnimator(animators, mBreadcrumbView, R.attr.guidedStepImeAppearingAnimation);
+ addAnimator(animators, mDescriptionView, R.attr.guidedStepImeAppearingAnimation);
+ addAnimator(animators, mIconView, R.attr.guidedStepImeAppearingAnimation);
}
/**
* {@inheritDoc}
*/
@Override
- public void onFragmentReturn(@NonNull List<Animator> animators) {
- addAnimator(animators, mTitleView, R.attr.guidedStepReturnAnimation);
- addAnimator(animators, mBreadcrumbView, R.attr.guidedStepReturnAnimation);
- addAnimator(animators, mDescriptionView, R.attr.guidedStepReturnAnimation);
- addAnimator(animators, mIconView, R.attr.guidedStepReturnAnimation);
+ public void onImeDisappearing(@NonNull List<Animator> animators) {
+ addAnimator(animators, mTitleView, R.attr.guidedStepImeDisappearingAnimation);
+ addAnimator(animators, mBreadcrumbView, R.attr.guidedStepImeDisappearingAnimation);
+ addAnimator(animators, mDescriptionView, R.attr.guidedStepImeDisappearingAnimation);
+ addAnimator(animators, mIconView, R.attr.guidedStepImeDisappearingAnimation);
}
private void addAnimator(List<Animator> animators, View v, int attrId) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
index e4db2eba68..21986d51e0 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
@@ -13,9 +13,12 @@
*/
package android.support.v17.leanback.widget;
+import android.support.v17.leanback.R;
+
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
+import android.text.InputType;
import android.util.Log;
/**
@@ -34,47 +37,189 @@ public class GuidedAction extends Action {
private static final String TAG = "GuidedAction";
- public static final int NO_DRAWABLE = 0;
+ /**
+ * Special check set Id that is neither checkbox nor radio.
+ */
public static final int NO_CHECK_SET = 0;
+ /**
+ * Default checkset Id for radio.
+ */
public static final int DEFAULT_CHECK_SET_ID = 1;
+ /**
+ * Checkset Id for checkbox.
+ */
+ public static final int CHECKBOX_CHECK_SET_ID = -1;
+
+ /**
+ * When finishing editing, goes to next action.
+ */
+ public static final long ACTION_ID_NEXT = -2;
+ /**
+ * When finishing editing, stay on current action.
+ */
+ public static final long ACTION_ID_CURRENT = -3;
+
+ /**
+ * Id of standard OK action.
+ */
+ public static final long ACTION_ID_OK = -4;
+
+ /**
+ * Id of standard Cancel action.
+ */
+ public static final long ACTION_ID_CANCEL = -5;
+
+ /**
+ * Id of standard Finish action.
+ */
+ public static final long ACTION_ID_FINISH = -6;
+
+ /**
+ * Id of standard Finish action.
+ */
+ public static final long ACTION_ID_CONTINUE = -7;
+
+ /**
+ * Id of standard Yes action.
+ */
+ public static final long ACTION_ID_YES = -8;
/**
- * Builds a {@link GuidedAction} object.
+ * Id of standard No action.
+ */
+ public static final long ACTION_ID_NO = -9;
+
+ /**
+ * Builds a {@link GuidedAction} object. When subclass GuidedAction, you may override this
+ * Builder class and call {@link #applyValues(GuidedAction)}.
*/
public static class Builder {
private long mId;
- private String mTitle;
- private String mDescription;
+ private CharSequence mTitle;
+ private CharSequence mEditTitle;
+ private CharSequence mDescription;
+ private CharSequence mEditDescription;
private Drawable mIcon;
private boolean mChecked;
private boolean mMultilineDescription;
private boolean mHasNext;
private boolean mInfoOnly;
+ private boolean mEditable = false;
+ private boolean mDescriptionEditable = false;
+ private int mInputType = InputType.TYPE_CLASS_TEXT;
+ private int mDescriptionInputType = InputType.TYPE_CLASS_TEXT;
+ private int mEditInputType = InputType.TYPE_CLASS_TEXT;
+ private int mDescriptionEditInputType = InputType.TYPE_CLASS_TEXT;
private int mCheckSetId = NO_CHECK_SET;
private boolean mEnabled = true;
+ private boolean mFocusable = true;
private Intent mIntent;
/**
* Builds the GuidedAction corresponding to this Builder.
* @return the GuidedAction as configured through this Builder.
*/
- public GuidedAction build() {
+ public final GuidedAction build() {
GuidedAction action = new GuidedAction();
+ applyValues(action);
+ return action;
+ }
+
+ /**
+ * Subclass Builder may call this function to apply values.
+ * @param action GuidedAction to apply Builder values.
+ */
+ protected final void applyValues(GuidedAction action) {
// Base Action values
action.setId(mId);
action.setLabel1(mTitle);
+ action.setEditTitle(mEditTitle);
action.setLabel2(mDescription);
+ action.setEditDescription(mEditDescription);
action.setIcon(mIcon);
// Subclass values
action.mIntent = mIntent;
+ action.mEditable = mEditable;
+ action.mDescriptionEditable = mDescriptionEditable;
+ action.mInputType = mInputType;
+ action.mDescriptionInputType = mDescriptionInputType;
+ action.mEditInputType = mEditInputType;
+ action.mDescriptionEditInputType = mDescriptionEditInputType;
action.mChecked = mChecked;
action.mCheckSetId = mCheckSetId;
action.mMultilineDescription = mMultilineDescription;
action.mHasNext = mHasNext;
action.mInfoOnly = mInfoOnly;
action.mEnabled = mEnabled;
- return action;
+ action.mFocusable = mFocusable;
+ }
+
+ /**
+ * Construct a standard "OK" action with {@link GuidedAction#ACTION_ID_OK}.
+ * @param context Context for loading action title.
+ * @return The same Builder object.
+ */
+ public Builder constructOK(Context context) {
+ mId = ACTION_ID_OK;
+ mTitle = context.getString(android.R.string.ok);
+ return this;
+ }
+
+ /**
+ * Construct a standard "Cancel" action with {@link GuidedAction#ACTION_ID_CANCEL}.
+ * @param context Context for loading action title.
+ * @return The same Builder object.
+ */
+ public Builder constructCancel(Context context) {
+ mId = ACTION_ID_CANCEL;
+ mTitle = context.getString(android.R.string.cancel);
+ return this;
+ }
+
+ /**
+ * Construct a standard "Finish" action with {@link GuidedAction#ACTION_ID_FINISH}.
+ * @param context Context for loading action title.
+ * @return The same Builder object.
+ */
+ public Builder constructFinish(Context context) {
+ mId = ACTION_ID_FINISH;
+ mTitle = context.getString(R.string.lb_guidedaction_finish_title);
+ return this;
+ }
+
+ /**
+ * Construct a standard "Continue" action with {@link GuidedAction#ACTION_ID_CONTINUE}.
+ * @param context Context for loading action title.
+ * @return The same Builder object.
+ */
+ public Builder constructContinue(Context context) {
+ mId = ACTION_ID_CONTINUE;
+ mHasNext = true;
+ mTitle = context.getString(R.string.lb_guidedaction_continue_title);
+ return this;
+ }
+
+ /**
+ * Construct a standard "Yes" action with {@link GuidedAction#ACTION_ID_YES}.
+ * @param context Context for loading action title.
+ * @return The same Builder object.
+ */
+ public Builder constructYes(Context context) {
+ mId = ACTION_ID_YES;
+ mTitle = context.getString(android.R.string.yes);
+ return this;
+ }
+
+ /**
+ * Construct a standard "No" action with {@link GuidedAction#ACTION_ID_NO}.
+ * @param context Context for loading action title.
+ * @return The same Builder object.
+ */
+ public Builder constructNo(Context context) {
+ mId = ACTION_ID_NO;
+ mTitle = context.getString(android.R.string.no);
+ return this;
}
/**
@@ -92,22 +237,41 @@ public class GuidedAction extends Action {
* action to be taken on click, e.g. "Continue" or "Cancel".
* @param title The title for this action.
*/
- public Builder title(String title) {
+ public Builder title(CharSequence title) {
mTitle = title;
return this;
}
/**
+ * Sets the optional title text to edit. When TextView is activated, the edit title
+ * replaces the string of title.
+ */
+ public Builder editTitle(CharSequence editTitle) {
+ mEditTitle = editTitle;
+ return this;
+ }
+
+ /**
* Sets the description for this action. The description is typically a longer string
* providing extra information on what the action will do.
* @param description The description for this action.
*/
- public Builder description(String description) {
+ public Builder description(CharSequence description) {
mDescription = description;
return this;
}
/**
+ * Sets the optional description text to edit. When TextView is activated, the edit
+ * description replaces the string of description.
+ * @param description The description to edit for this action.
+ */
+ public Builder editDescription(CharSequence description) {
+ mEditDescription = description;
+ return this;
+ }
+
+ /**
* Sets the intent associated with this action. Clients would typically fire this intent
* directly when the action is clicked.
* @param intent The intent associated with this action.
@@ -138,22 +302,96 @@ public class GuidedAction extends Action {
}
/**
+ * Indicates whether this action title is editable. Note: Editable actions cannot also be
+ * checked, or belong to a check set.
+ * @param editable Whether this action is editable.
+ */
+ public Builder editable(boolean editable) {
+ mEditable = editable;
+ if (mChecked || mCheckSetId != NO_CHECK_SET) {
+ throw new IllegalArgumentException("Editable actions cannot also be checked");
+ }
+ return this;
+ }
+
+ /**
+ * Indicates whether this action's description is editable
+ * @param editable Whether this action description is editable.
+ */
+ public Builder descriptionEditable(boolean editable) {
+ mDescriptionEditable = editable;
+ if (mChecked || mCheckSetId != NO_CHECK_SET) {
+ throw new IllegalArgumentException("Editable actions cannot also be checked");
+ }
+ return this;
+ }
+
+ /**
+ * Sets {@link InputType} of this action title not in editing.
+ *
+ * @param inputType InputType for the action title not in editing.
+ */
+ public Builder inputType(int inputType) {
+ mInputType = inputType;
+ return this;
+ }
+
+ /**
+ * Sets {@link InputType} of this action description not in editing.
+ *
+ * @param inputType InputType for the action description not in editing.
+ */
+ public Builder descriptionInputType(int inputType) {
+ mDescriptionInputType = inputType;
+ return this;
+ }
+
+
+ /**
+ * Sets {@link InputType} of this action title in editing.
+ *
+ * @param inputType InputType for the action title in editing.
+ */
+ public Builder editInputType(int inputType) {
+ mEditInputType = inputType;
+ return this;
+ }
+
+ /**
+ * Sets {@link InputType} of this action description in editing.
+ *
+ * @param inputType InputType for the action description in editing.
+ */
+ public Builder descriptionEditInputType(int inputType) {
+ mDescriptionEditInputType = inputType;
+ return this;
+ }
+
+
+ /**
* Indicates whether this action is initially checked.
* @param checked Whether this action is checked.
*/
public Builder checked(boolean checked) {
mChecked = checked;
+ if (mEditable || mDescriptionEditable) {
+ throw new IllegalArgumentException("Editable actions cannot also be checked");
+ }
return this;
}
/**
- * Indicates whether this action is part of a single-select group similar to radio buttons.
- * When one item in a check set is checked, all others with the same check set ID will be
- * unchecked automatically.
- * @param checkSetId The check set ID, or {@link #NO_CHECK_SET) to indicate no check set.
+ * Indicates whether this action is part of a single-select group similar to radio buttons
+ * or this action is a checkbox. When one item in a check set is checked, all others with
+ * the same check set ID will be nchecked automatically.
+ * @param checkSetId The check set ID, or {@link GuidedAction#NO_CHECK_SET} to indicate not
+ * radio or checkbox, or {@link GuidedAction#CHECKBOX_CHECK_SET_ID} to indicate a checkbox.
*/
public Builder checkSetId(int checkSetId) {
mCheckSetId = checkSetId;
+ if (mEditable || mDescriptionEditable) {
+ throw new IllegalArgumentException("Editable actions cannot also be in check sets");
+ }
return this;
}
@@ -193,18 +431,37 @@ public class GuidedAction extends Action {
mEnabled = enabled;
return this;
}
+
+ /**
+ * Indicates whether this action can take focus.
+ * @param focusable
+ * @return The same Builder object.
+ */
+ public Builder focusable(boolean focusable) {
+ mFocusable = focusable;
+ return this;
+ }
}
- private boolean mChecked;
+ private CharSequence mEditTitle;
+ private CharSequence mEditDescription;
+ private boolean mEditable;
+ private boolean mDescriptionEditable;
+ private int mInputType;
+ private int mDescriptionInputType;
+ private int mEditInputType;
+ private int mDescriptionEditInputType;
private boolean mMultilineDescription;
private boolean mHasNext;
+ private boolean mChecked;
private boolean mInfoOnly;
private int mCheckSetId;
private boolean mEnabled;
+ private boolean mFocusable;
private Intent mIntent;
- private GuidedAction() {
+ protected GuidedAction() {
super(0);
}
@@ -217,14 +474,74 @@ public class GuidedAction extends Action {
}
/**
+ * Sets the title of this action.
+ * @param title The title set when this action was built.
+ */
+ public void setTitle(CharSequence title) {
+ setLabel1(title);
+ }
+
+ /**
+ * Returns the optional title text to edit. When not null, it is being edited instead of
+ * {@link #getTitle()}.
+ * @return Optional title text to edit instead of {@link #getTitle()}.
+ */
+ public CharSequence getEditTitle() {
+ return mEditTitle;
+ }
+
+ /**
+ * Sets the optional title text to edit instead of {@link #setTitle(CharSequence)}.
+ * @param editTitle Optional title text to edit instead of {@link #setTitle(CharSequence)}.
+ */
+ public void setEditTitle(CharSequence editTitle) {
+ mEditTitle = editTitle;
+ }
+
+ /**
+ * Returns the optional description text to edit. When not null, it is being edited instead of
+ * {@link #getDescription()}.
+ * @return Optional description text to edit instead of {@link #getDescription()}.
+ */
+ public CharSequence getEditDescription() {
+ return mEditDescription;
+ }
+
+ /**
+ * Sets the optional description text to edit instead of {@link #setDescription(CharSequence)}.
+ * @param editDescription Optional description text to edit instead of
+ * {@link #setDescription(CharSequence)}.
+ */
+ public void setEditDescription(CharSequence editDescription) {
+ mEditDescription = editDescription;
+ }
+
+ /**
+ * Returns true if {@link #getEditTitle()} is not null. When true, the {@link #getEditTitle()}
+ * is being edited instead of {@link #getTitle()}.
+ * @return true if {@link #getEditTitle()} is not null.
+ */
+ public boolean isEditTitleUsed() {
+ return mEditTitle != null;
+ }
+
+ /**
* Returns the description of this action.
- * @return The description set when this action was built.
+ * @return The description of this action.
*/
public CharSequence getDescription() {
return getLabel2();
}
/**
+ * Sets the description of this action.
+ * @param description The description of the action.
+ */
+ public void setDescription(CharSequence description) {
+ setLabel2(description);
+ }
+
+ /**
* Returns the intent associated with this action.
* @return The intent set when this action was built.
*/
@@ -233,6 +550,55 @@ public class GuidedAction extends Action {
}
/**
+ * Returns whether this action title is editable.
+ * @return true if the action title is editable, false otherwise.
+ */
+ public boolean isEditable() {
+ return mEditable;
+ }
+
+ /**
+ * Returns whether this action description is editable.
+ * @return true if the action description is editable, false otherwise.
+ */
+ public boolean isDescriptionEditable() {
+ return mDescriptionEditable;
+ }
+
+ /**
+ * Returns InputType of action title in editing; only valid when {@link #isEditable()} is true.
+ * @return InputType of action title in editing.
+ */
+ public int getEditInputType() {
+ return mEditInputType;
+ }
+
+ /**
+ * Returns InputType of action description in editing; only valid when
+ * {@link #isDescriptionEditable()} is true.
+ * @return InputType of action description in editing.
+ */
+ public int getDescriptionEditInputType() {
+ return mDescriptionEditInputType;
+ }
+
+ /**
+ * Returns InputType of action title not in editing.
+ * @return InputType of action title not in editing.
+ */
+ public int getInputType() {
+ return mInputType;
+ }
+
+ /**
+ * Returns InputType of action description not in editing.
+ * @return InputType of action description not in editing.
+ */
+ public int getDescriptionInputType() {
+ return mDescriptionInputType;
+ }
+
+ /**
* Returns whether this action is checked.
* @return true if the action is currently checked, false otherwise.
*/
@@ -249,13 +615,13 @@ public class GuidedAction extends Action {
}
/**
- * Returns the check set id this action is a part of. All actions in the
- * same list with the same check set id are considered linked. When one
- * of the actions within that set is selected, that action becomes
- * checked, while all the other actions become unchecked.
+ * Returns the check set id this action is a part of. All actions in the same list with the same
+ * check set id are considered linked. When one of the actions within that set is selected, that
+ * action becomes checked, while all the other actions become unchecked.
*
* @return an integer representing the check set this action is a part of, or
- * {@link #NO_CHECK_SET} if this action isn't a part of a check set.
+ * {@link #CHECKBOX_CHECK_SET_ID} if this is a checkbox, or {@link #NO_CHECK_SET} if
+ * this action is not a checkbox or radiobutton.
*/
public int getCheckSetId() {
return mCheckSetId;
@@ -287,6 +653,22 @@ public class GuidedAction extends Action {
}
/**
+ * Returns whether this action is focusable.
+ * @return true if the action is currently focusable, false otherwise.
+ */
+ public boolean isFocusable() {
+ return mFocusable;
+ }
+
+ /**
+ * Sets whether this action is focusable.
+ * @param focusable Whether this action should be focusable.
+ */
+ public void setFocusable(boolean focusable) {
+ mFocusable = focusable;
+ }
+
+ /**
* Returns whether this action will request further user input when selected, such as showing
* another GuidedStepFragment or launching a new activity. Configured during construction.
* @return true if the action will request further user input when selected, false otherwise.
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionEditText.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionEditText.java
new file mode 100644
index 0000000000..8e052fb248
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionEditText.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 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 android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.support.v17.leanback.widget.ImeKeyMonitor.ImeKeyListener;
+import android.util.AttributeSet;
+import android.widget.EditText;
+import android.view.KeyEvent;
+
+/**
+ * A custom EditText that satisfies the IME key monitoring requirements of GuidedStepFragment.
+ */
+public class GuidedActionEditText extends EditText implements ImeKeyMonitor {
+
+ private ImeKeyListener mKeyListener;
+
+ public GuidedActionEditText(Context ctx) {
+ this(ctx, null);
+ }
+
+ public GuidedActionEditText(Context ctx, AttributeSet attrs) {
+ this(ctx, attrs, android.R.attr.editTextStyle);
+ }
+
+ public GuidedActionEditText(Context ctx, AttributeSet attrs, int defStyleAttr) {
+ super(ctx, attrs, defStyleAttr);
+ }
+
+ @Override
+ public void setImeKeyListener(ImeKeyListener listener) {
+ mKeyListener = listener;
+ }
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ boolean result = false;
+ if (mKeyListener != null) {
+ result = mKeyListener.onKeyPreIme(this, keyCode, event);
+ }
+ if (!result) {
+ result = super.onKeyPreIme(keyCode, event);
+ }
+ return result;
+ }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
index 15943b423a..6e5d5067db 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
@@ -22,17 +22,21 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v17.leanback.R;
import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.animation.DecelerateInterpolator;
+import android.view.inputmethod.EditorInfo;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -40,6 +44,8 @@ import android.view.ViewGroup.LayoutParams;
import android.view.ViewPropertyAnimator;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
+import android.widget.Checkable;
+import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
@@ -81,11 +87,15 @@ import java.util.List;
* </ul><p>
* These view IDs are allowed to be missing, in which case the corresponding views in {@link
* GuidedActionsStylist.ViewHolder} will be null.
+ * <p>
+ * In order to support editable actions, the view associated with guidedactions_item_title should
+ * be a subclass of {@link android.widget.EditText}, and should satisfy the {@link
+ * ImeKeyMonitor} interface.
*
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsEntryAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeAppearingAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeDisappearingAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsSelectorShowAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsSelectorHideAnimation
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsContainerStyle
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsSelectorStyle
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsListStyle
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemContainerStyle
@@ -95,24 +105,30 @@ import java.util.List;
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemTitleStyle
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemDescriptionStyle
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemChevronStyle
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionCheckedAnimation
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionUncheckedAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionPressedAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionUnpressedAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionEnabledChevronAlpha
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionDisabledChevronAlpha
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidth
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidthNoIcon
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionTitleMinLines
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionTitleMaxLines
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionDescriptionMinLines
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionVerticalPadding
+ * @see android.R.styleable#Theme_listChoiceIndicatorSingle
+ * @see android.R.styleable#Theme_listChoiceIndicatorMultiple
* @see android.support.v17.leanback.app.GuidedStepFragment
* @see GuidedAction
*/
public class GuidedActionsStylist implements FragmentAnimationProvider {
/**
+ * Default viewType that associated with default layout Id for the action item.
+ * @see #getItemViewType(GuidedAction)
+ * @see #onProvideItemLayoutId(int)
+ * @see #onCreateViewHolder(ViewGroup, int)
+ */
+ public static final int VIEW_TYPE_DEFAULT = 0;
+
+ /**
* ViewHolder caches information about the action item layouts' subviews. Subclasses of {@link
* GuidedActionsStylist} may also wish to subclass this in order to add fields.
* @see GuidedAction
@@ -127,6 +143,8 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
private ImageView mIconView;
private ImageView mCheckmarkView;
private ImageView mChevronView;
+ private boolean mInEditing;
+ private boolean mInEditingDescription;
/**
* Constructs an ViewHolder and caches the relevant subviews.
@@ -158,6 +176,14 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
}
/**
+ * Convenience method to return an editable version of the title, if possible,
+ * or null if the title view isn't an EditText.
+ */
+ public EditText getEditableTitleView() {
+ return (mTitleView instanceof EditText) ? (EditText)mTitleView : null;
+ }
+
+ /**
* Returns the description view within this view holder's view.
*/
public TextView getDescriptionView() {
@@ -165,6 +191,14 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
}
/**
+ * Convenience method to return an editable version of the description, if possible,
+ * or null if the description view isn't an EditText.
+ */
+ public EditText getEditableDescriptionView() {
+ return (mDescriptionView instanceof EditText) ? (EditText)mDescriptionView : null;
+ }
+
+ /**
* Returns the icon view within this view holder's view.
*/
public ImageView getIconView() {
@@ -185,19 +219,47 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
return mChevronView;
}
+ /**
+ * Returns true if the TextView is in editing title or description, false otherwise.
+ */
+ public boolean isInEditing() {
+ return mInEditing;
+ }
+
+ /**
+ * Returns true if the TextView is in editing description, false otherwise.
+ */
+ public boolean isInEditingDescription() {
+ return mInEditingDescription;
+ }
+
+ public View getEditingView() {
+ if (mInEditing) {
+ return mInEditingDescription ? mDescriptionView : mTitleView;
+ } else {
+ return null;
+ }
+ }
}
private static String TAG = "GuidedActionsStylist";
- protected View mMainView;
- protected VerticalGridView mActionsGridView;
- protected View mSelectorView;
+ private ViewGroup mMainView;
+ private VerticalGridView mActionsGridView;
+ private View mBgView;
+ private View mSelectorView;
+ private View mContentView;
+ private boolean mButtonActions;
+
+ private Animator mSelectorAnimator;
// Cached values from resources
+ private float mEnabledTextAlpha;
+ private float mDisabledTextAlpha;
+ private float mEnabledDescriptionAlpha;
+ private float mDisabledDescriptionAlpha;
private float mEnabledChevronAlpha;
private float mDisabledChevronAlpha;
- private int mContentWidth;
- private int mContentWidthNoIcon;
private int mTitleMinLines;
private int mTitleMaxLines;
private int mDescriptionMinLines;
@@ -216,8 +278,17 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
* @return The view to be added to the caller's view hierarchy.
*/
public View onCreateView(LayoutInflater inflater, ViewGroup container) {
- mMainView = inflater.inflate(onProvideLayoutId(), container, false);
+ mMainView = (ViewGroup) inflater.inflate(onProvideLayoutId(), container, false);
+ mContentView = mMainView.findViewById(R.id.guidedactions_content);
mSelectorView = mMainView.findViewById(R.id.guidedactions_selector);
+ mSelectorView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ updateSelectorView(false);
+ }
+ });
+ mBgView = mMainView.findViewById(R.id.guidedactions_list_background);
if (mMainView instanceof VerticalGridView) {
mActionsGridView = (VerticalGridView) mMainView;
} else {
@@ -229,32 +300,23 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
mActionsGridView.setWindowAlignmentOffsetPercent(50f);
mActionsGridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE);
if (mSelectorView != null) {
- mActionsGridView.setOnScrollListener(new
- SelectorAnimator(mSelectorView, mActionsGridView));
+ mActionsGridView.setOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+ if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+ if (mSelectorView.getAlpha() != 1f) {
+ updateSelectorView(true);
+ }
+ }
+ }
+ });
}
}
- mActionsGridView.requestFocusFromTouch();
-
if (mSelectorView != null) {
// ALlow focus to move to other views
mActionsGridView.getViewTreeObserver().addOnGlobalFocusChangeListener(
- new ViewTreeObserver.OnGlobalFocusChangeListener() {
- private boolean mChildFocused;
-
- @Override
- public void onGlobalFocusChanged(View oldFocus, View newFocus) {
- View focusedChild = mActionsGridView.getFocusedChild();
- if (focusedChild == null) {
- mSelectorView.setVisibility(View.INVISIBLE);
- mChildFocused = false;
- } else if (!mChildFocused) {
- mChildFocused = true;
- mSelectorView.setVisibility(View.VISIBLE);
- updateSelectorView(focusedChild);
- }
- }
- });
+ mGlobalFocusChangeListener);
}
// Cache widths, chevron alpha values, max and min text lines, etc
@@ -262,8 +324,6 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
TypedValue val = new TypedValue();
mEnabledChevronAlpha = getFloat(ctx, val, R.attr.guidedActionEnabledChevronAlpha);
mDisabledChevronAlpha = getFloat(ctx, val, R.attr.guidedActionDisabledChevronAlpha);
- mContentWidth = getDimension(ctx, val, R.attr.guidedActionContentWidth);
- mContentWidthNoIcon = getDimension(ctx, val, R.attr.guidedActionContentWidthNoIcon);
mTitleMinLines = getInteger(ctx, val, R.attr.guidedActionTitleMinLines);
mTitleMaxLines = getInteger(ctx, val, R.attr.guidedActionTitleMaxLines);
mDescriptionMinLines = getInteger(ctx, val, R.attr.guidedActionDescriptionMinLines);
@@ -271,10 +331,79 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
mDisplayHeight = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay().getHeight();
+ mEnabledTextAlpha = Float.valueOf(ctx.getResources().getString(R.string
+ .lb_guidedactions_item_unselected_text_alpha));
+ mDisabledTextAlpha = Float.valueOf(ctx.getResources().getString(R.string
+ .lb_guidedactions_item_disabled_text_alpha));
+ mEnabledDescriptionAlpha = Float.valueOf(ctx.getResources().getString(R.string
+ .lb_guidedactions_item_unselected_description_text_alpha));
+ mDisabledDescriptionAlpha = Float.valueOf(ctx.getResources().getString(R.string
+ .lb_guidedactions_item_disabled_description_text_alpha));
return mMainView;
}
/**
+ * Default implementation turns on background for actions and applies different Ids to views so
+ * that GuidedStepFragment could run transitions against two action lists. The method is called
+ * by GuidedStepFragment, app may override this function when replacing default layout file
+ * provided by {@link #onProvideLayoutId()}
+ */
+ public void setAsButtonActions() {
+ mButtonActions = true;
+ mMainView.setId(R.id.guidedactions_root2);
+ ViewCompat.setTransitionName(mMainView, "guidedactions_root2");
+ if (mActionsGridView != null) {
+ mActionsGridView.setId(R.id.guidedactions_list2);
+ }
+ if (mSelectorView != null) {
+ mSelectorView.setId(R.id.guidedactions_selector2);
+ ViewCompat.setTransitionName(mSelectorView, "guidedactions_selector2");
+ }
+ if (mContentView != null) {
+ mContentView.setId(R.id.guidedactions_content2);
+ ViewCompat.setTransitionName(mContentView, "guidedactions_content2");
+ }
+ if (mBgView != null) {
+ mBgView.setId(R.id.guidedactions_list_background2);
+ ViewCompat.setTransitionName(mBgView, "guidedactions_list_background2");
+ mBgView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ /**
+ * Returns true if {@link #setAsButtonActions()} was called, false otherwise.
+ * @return True if {@link #setAsButtonActions()} was called, false otherwise.
+ */
+ public boolean isButtonActions() {
+ return mButtonActions;
+ }
+
+ final ViewTreeObserver.OnGlobalFocusChangeListener mGlobalFocusChangeListener =
+ new ViewTreeObserver.OnGlobalFocusChangeListener() {
+
+ @Override
+ public void onGlobalFocusChanged(View oldFocus, View newFocus) {
+ updateSelectorView(false);
+ }
+ };
+
+ /**
+ * Called when destroy the View created by GuidedActionsStylist.
+ */
+ public void onDestroyView() {
+ if (mSelectorView != null) {
+ mActionsGridView.getViewTreeObserver().removeOnGlobalFocusChangeListener(
+ mGlobalFocusChangeListener);
+ }
+ endSelectorAnimator();
+ mActionsGridView = null;
+ mSelectorView = null;
+ mContentView = null;
+ mBgView = null;
+ mMainView = null;
+ }
+
+ /**
* Returns the VerticalGridView that displays the list of GuidedActions.
* @return The VerticalGridView for this presenter.
*/
@@ -296,11 +425,25 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
}
/**
+ * Return view type of action, each different type can have differently associated layout Id.
+ * Default implementation returns {@link #VIEW_TYPE_DEFAULT}.
+ * @param action The action object.
+ * @return View type that used in {@link #onProvideItemLayoutId(int)}.
+ */
+ public int getItemViewType(GuidedAction action) {
+ return VIEW_TYPE_DEFAULT;
+ }
+
+ /**
* Provides the resource ID of the layout defining the view for an individual guided actions.
* Subclasses may override to provide their own customized layouts. The base implementation
* returns {@link android.support.v17.leanback.R.layout#lb_guidedactions_item}. If overridden,
* the substituted layout should contain matching IDs for any views that should be managed by
- * the base class; this can be achieved by starting with a copy of the base layout file.
+ * the base class; this can be achieved by starting with a copy of the base layout file. Note
+ * that in order for the item to support editing, the title view should both subclass {@link
+ * android.widget.EditText} and implement {@link ImeKeyMonitor}; see {@link
+ * GuidedActionEditText}. To support different types of Layouts, override {@link
+ * #onProvideItemLayoutId(int)}.
* @return The resource ID of the layout to be inflated to define the view to display an
* individual GuidedAction.
*/
@@ -309,8 +452,31 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
}
/**
+ * Provides the resource ID of the layout defining the view for an individual guided actions.
+ * Subclasses may override to provide their own customized layouts. The base implementation
+ * returns {@link android.support.v17.leanback.R.layout#lb_guidedactions_item}. If overridden,
+ * the substituted layout should contain matching IDs for any views that should be managed by
+ * the base class; this can be achieved by starting with a copy of the base layout file. Note
+ * that in order for the item to support editing, the title view should both subclass {@link
+ * android.widget.EditText} and implement {@link ImeKeyMonitor}; see {@link
+ * GuidedActionEditText}.
+ * @param viewType View type returned by {@link #getItemViewType(GuidedAction)}
+ * @return The resource ID of the layout to be inflated to define the view to display an
+ * individual GuidedAction.
+ */
+ public int onProvideItemLayoutId(int viewType) {
+ if (viewType == VIEW_TYPE_DEFAULT) {
+ return onProvideItemLayoutId();
+ } else {
+ throw new RuntimeException("ViewType " + viewType +
+ " not supported in GuidedActionsStylist");
+ }
+ }
+
+ /**
* Constructs a {@link ViewHolder} capable of representing {@link GuidedAction}s. Subclasses
- * may choose to return a subclass of ViewHolder.
+ * may choose to return a subclass of ViewHolder. To support different view types, override
+ * {@link #onCreateViewHolder(ViewGroup, int)}
* <p>
* <i>Note: Should not actually add the created view to the parent; the caller will do
* this.</i>
@@ -324,6 +490,25 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
}
/**
+ * Constructs a {@link ViewHolder} capable of representing {@link GuidedAction}s. Subclasses
+ * may choose to return a subclass of ViewHolder.
+ * <p>
+ * <i>Note: Should not actually add the created view to the parent; the caller will do
+ * this.</i>
+ * @param parent The view group to be used as the parent of the new view.
+ * @param viewType The viewType returned by {@link #getItemViewType(GuidedAction)}
+ * @return The view to be added to the caller's view hierarchy.
+ */
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ if (viewType == VIEW_TYPE_DEFAULT) {
+ return onCreateViewHolder(parent);
+ }
+ LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+ View v = inflater.inflate(onProvideItemLayoutId(viewType), parent, false);
+ return new ViewHolder(v);
+ }
+
+ /**
* Binds a {@link ViewHolder} to a particular {@link GuidedAction}.
* @param vh The view holder to be associated with the given action.
* @param action The guided action to be displayed by the view holder's view.
@@ -333,31 +518,24 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
if (vh.mTitleView != null) {
vh.mTitleView.setText(action.getTitle());
+ vh.mTitleView.setAlpha(action.isEnabled() ? mEnabledTextAlpha : mDisabledTextAlpha);
+ vh.mTitleView.setFocusable(action.isEditable());
}
if (vh.mDescriptionView != null) {
vh.mDescriptionView.setText(action.getDescription());
vh.mDescriptionView.setVisibility(TextUtils.isEmpty(action.getDescription()) ?
View.GONE : View.VISIBLE);
+ vh.mDescriptionView.setAlpha(action.isEnabled() ? mEnabledDescriptionAlpha :
+ mDisabledDescriptionAlpha);
+ vh.mDescriptionView.setFocusable(action.isDescriptionEditable());
}
// Clients might want the check mark view to be gone entirely, in which case, ignore it.
- if (vh.mCheckmarkView != null && vh.mCheckmarkView.getVisibility() != View.GONE) {
- vh.mCheckmarkView.setVisibility(action.isChecked() ? View.VISIBLE : View.INVISIBLE);
- }
-
- if (vh.mContentView != null) {
- ViewGroup.LayoutParams contentLp = vh.mContentView.getLayoutParams();
- if (setIcon(vh.mIconView, action)) {
- contentLp.width = mContentWidth;
- } else {
- contentLp.width = mContentWidthNoIcon;
- }
- vh.mContentView.setLayoutParams(contentLp);
+ if (vh.mCheckmarkView != null) {
+ onBindCheckMarkView(vh, action);
}
if (vh.mChevronView != null) {
- vh.mChevronView.setVisibility(action.hasNext() ? View.VISIBLE : View.INVISIBLE);
- vh.mChevronView.setAlpha(action.isEnabled() ? mEnabledChevronAlpha :
- mDisabledChevronAlpha);
+ onBindChevronView(vh, action);
}
if (action.hasMultilineDescription()) {
@@ -376,6 +554,89 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
vh.mDescriptionView.setMaxLines(mDescriptionMinLines);
}
}
+ setEditingMode(vh, action, false);
+ if (action.isFocusable()) {
+ vh.view.setFocusable(true);
+ if (vh.view instanceof ViewGroup) {
+ ((ViewGroup) vh.view).setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+ }
+ } else {
+ vh.view.setFocusable(false);
+ if (vh.view instanceof ViewGroup) {
+ ((ViewGroup) vh.view).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+ }
+ }
+ setupImeOptions(vh, action);
+ }
+
+ /**
+ * Called by {@link #onBindViewHolder(ViewHolder, GuidedAction)} to setup IME options. Default
+ * implementation assigns {@link EditorInfo#IME_ACTION_DONE}. Subclass may override.
+ * @param vh The view holder to be associated with the given action.
+ * @param action The guided action to be displayed by the view holder's view.
+ */
+ protected void setupImeOptions(ViewHolder vh, GuidedAction action) {
+ setupNextImeOptions(vh.getEditableTitleView());
+ setupNextImeOptions(vh.getEditableDescriptionView());
+ }
+
+ private void setupNextImeOptions(EditText edit) {
+ if (edit != null) {
+ edit.setImeOptions(EditorInfo.IME_ACTION_NEXT);
+ }
+ }
+
+ public void setEditingMode(ViewHolder vh, GuidedAction action, boolean editing) {
+ if (editing != vh.mInEditing) {
+ vh.mInEditing = editing;
+ onEditingModeChange(vh, action, editing);
+ }
+ }
+
+ protected void onEditingModeChange(ViewHolder vh, GuidedAction action, boolean editing) {
+ TextView titleView = vh.getTitleView();
+ TextView descriptionView = vh.getDescriptionView();
+ if (editing) {
+ CharSequence editTitle = action.getEditTitle();
+ if (titleView != null && editTitle != null) {
+ titleView.setText(editTitle);
+ }
+ CharSequence editDescription = action.getEditDescription();
+ if (descriptionView != null && editDescription != null) {
+ descriptionView.setText(editDescription);
+ }
+ if (action.isDescriptionEditable()) {
+ if (descriptionView != null) {
+ descriptionView.setVisibility(View.VISIBLE);
+ descriptionView.setInputType(action.getDescriptionEditInputType());
+ }
+ vh.mInEditingDescription = true;
+ } else {
+ vh.mInEditingDescription = false;
+ if (titleView != null) {
+ titleView.setInputType(action.getEditInputType());
+ }
+ }
+ } else {
+ if (titleView != null) {
+ titleView.setText(action.getTitle());
+ }
+ if (descriptionView != null) {
+ descriptionView.setText(action.getDescription());
+ }
+ if (vh.mInEditingDescription) {
+ if (descriptionView != null) {
+ descriptionView.setVisibility(TextUtils.isEmpty(action.getDescription()) ?
+ View.GONE : View.VISIBLE);
+ descriptionView.setInputType(action.getDescriptionInputType());
+ }
+ vh.mInEditingDescription = false;
+ } else {
+ if (titleView != null) {
+ titleView.setInputType(action.getInputType());
+ }
+ }
+ }
}
/**
@@ -402,85 +663,97 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
}
/**
- * Animates the view holder's view (or subviews thereof) when the action has had its check
- * state changed.
+ * Resets the view holder's view to unpressed state.
* @param vh The view holder associated with the relevant action.
- * @param checked True if the action has become checked, false if it has become unchecked.
*/
- public void onAnimateItemChecked(ViewHolder vh, boolean checked) {
- final View checkView = vh.mCheckmarkView;
- if (checkView != null) {
- if (checked) {
- checkView.setVisibility(View.VISIBLE);
- createAnimator(checkView, R.attr.guidedActionCheckedAnimation).start();
- } else {
- Animator animator = createAnimator(checkView,
- R.attr.guidedActionUncheckedAnimation);
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- checkView.setVisibility(View.INVISIBLE);
- }
- });
- animator.start();
- }
- }
+ public void onAnimateItemPressedCancelled(ViewHolder vh) {
+ createAnimator(vh.view, R.attr.guidedActionUnpressedAnimation).end();
}
- /*
- * ==========================================
- * FragmentAnimationProvider overrides
- * ==========================================
- */
-
/**
- * {@inheritDoc}
+ * Animates the view holder's view (or subviews thereof) when the action has had its check state
+ * changed. Default implementation calls setChecked() if {@link ViewHolder#getCheckmarkView()}
+ * is instance of {@link Checkable}.
+ *
+ * @param vh The view holder associated with the relevant action.
+ * @param checked True if the action has become checked, false if it has become unchecked.
+ * @see #onBindCheckMarkView(ViewHolder, GuidedAction)
*/
- @Override
- public void onActivityEnter(@NonNull List<Animator> animators) {
- animators.add(createAnimator(mMainView, R.attr.guidedActionsEntryAnimation));
+ public void onAnimateItemChecked(ViewHolder vh, boolean checked) {
+ if (vh.mCheckmarkView instanceof Checkable) {
+ ((Checkable) vh.mCheckmarkView).setChecked(checked);
+ }
}
/**
- * {@inheritDoc}
+ * Sets states of check mark view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}
+ * when action's checkset Id is other than {@link GuidedAction#NO_CHECK_SET}. Default
+ * implementation assigns drawable loaded from theme attribute
+ * {@link android.R.attr#listChoiceIndicatorMultiple} for checkbox or
+ * {@link android.R.attr#listChoiceIndicatorSingle} for radio button. Subclass rarely needs
+ * override the method, instead app can provide its own drawable that supports transition
+ * animations, change theme attributes {@link android.R.attr#listChoiceIndicatorMultiple} and
+ * {@link android.R.attr#listChoiceIndicatorSingle} in {android.support.v17.leanback.R.
+ * styleable#LeanbackGuidedStepTheme}.
+ *
+ * @param vh The view holder associated with the relevant action.
+ * @param action The GuidedAction object to bind to.
+ * @see #onAnimateItemChecked(ViewHolder, boolean)
*/
- @Override
- public void onActivityExit(@NonNull List<Animator> animators) {}
+ public void onBindCheckMarkView(ViewHolder vh, GuidedAction action) {
+ if (action.getCheckSetId() != GuidedAction.NO_CHECK_SET) {
+ vh.mCheckmarkView.setVisibility(View.VISIBLE);
+ int attrId = action.getCheckSetId() == GuidedAction.CHECKBOX_CHECK_SET_ID ?
+ android.R.attr.listChoiceIndicatorMultiple :
+ android.R.attr.listChoiceIndicatorSingle;
+ final Context context = vh.mCheckmarkView.getContext();
+ Drawable drawable = null;
+ TypedValue typedValue = new TypedValue();
+ if (context.getTheme().resolveAttribute(attrId, typedValue, true)) {
+ drawable = ContextCompat.getDrawable(context, typedValue.resourceId);
+ }
+ vh.mCheckmarkView.setImageDrawable(drawable);
+ if (vh.mCheckmarkView instanceof Checkable) {
+ ((Checkable) vh.mCheckmarkView).setChecked(action.isChecked());
+ }
+ } else {
+ vh.mCheckmarkView.setVisibility(View.GONE);
+ }
+ }
/**
- * {@inheritDoc}
+ * Sets states of chevron view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}.
+ * Subclass may override.
+ *
+ * @param vh The view holder associated with the relevant action.
+ * @param action The GuidedAction object to bind to.
*/
- @Override
- public void onFragmentEnter(@NonNull List<Animator> animators) {
- animators.add(createAnimator(mActionsGridView, R.attr.guidedStepEntryAnimation));
- animators.add(createAnimator(mSelectorView, R.attr.guidedStepEntryAnimation));
+ public void onBindChevronView(ViewHolder vh, GuidedAction action) {
+ vh.mChevronView.setVisibility(action.hasNext() ? View.VISIBLE : View.GONE);
+ vh.mChevronView.setAlpha(action.isEnabled() ? mEnabledChevronAlpha :
+ mDisabledChevronAlpha);
}
- /**
- * {@inheritDoc}
+ /*
+ * ==========================================
+ * FragmentAnimationProvider overrides
+ * ==========================================
*/
- @Override
- public void onFragmentExit(@NonNull List<Animator> animators) {
- animators.add(createAnimator(mActionsGridView, R.attr.guidedStepExitAnimation));
- animators.add(createAnimator(mSelectorView, R.attr.guidedStepExitAnimation));
- }
/**
* {@inheritDoc}
*/
@Override
- public void onFragmentReenter(@NonNull List<Animator> animators) {
- animators.add(createAnimator(mActionsGridView, R.attr.guidedStepReentryAnimation));
- animators.add(createAnimator(mSelectorView, R.attr.guidedStepReentryAnimation));
+ public void onImeAppearing(@NonNull List<Animator> animators) {
+ animators.add(createAnimator(mContentView, R.attr.guidedStepImeAppearingAnimation));
}
/**
* {@inheritDoc}
*/
@Override
- public void onFragmentReturn(@NonNull List<Animator> animators) {
- animators.add(createAnimator(mActionsGridView, R.attr.guidedStepReturnAnimation));
- animators.add(createAnimator(mSelectorView, R.attr.guidedStepReturnAnimation));
+ public void onImeDisappearing(@NonNull List<Animator> animators) {
+ animators.add(createAnimator(mContentView, R.attr.guidedStepImeDisappearingAnimation));
}
/*
@@ -489,15 +762,6 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
* ==========================================
*/
- private void updateSelectorView(View focusedChild) {
- // Display the selector view.
- int height = focusedChild.getHeight();
- LayoutParams lp = mSelectorView.getLayoutParams();
- lp.height = height;
- mSelectorView.setLayoutParams(lp);
- mSelectorView.setAlpha(1f);
- }
-
private float getFloat(Context ctx, TypedValue typedValue, int attrId) {
ctx.getTheme().resolveAttribute(attrId, typedValue, true);
// Android resources don't have a native float type, so we have to use strings.
@@ -551,96 +815,43 @@ public class GuidedActionsStylist implements FragmentAnimationProvider {
return (int)(mDisplayHeight - 2*mVerticalPadding - 2*mTitleMaxLines*title.getLineHeight());
}
- /**
- * SelectorAnimator
- * Controls animation for selected item backgrounds
- * TODO: Move into focus animation override?
- */
- private static class SelectorAnimator extends RecyclerView.OnScrollListener {
-
- private final View mSelectorView;
- private final ViewGroup mParentView;
- private volatile boolean mFadedOut = true;
-
- SelectorAnimator(View selectorView, ViewGroup parentView) {
- mSelectorView = selectorView;
- mParentView = parentView;
+ private void endSelectorAnimator() {
+ if (mSelectorAnimator != null) {
+ mSelectorAnimator.end();
+ mSelectorAnimator = null;
}
+ }
- // We want to fade in the selector if we've stopped scrolling on it. If
- // we're scrolling, we want to ensure to dim the selector if we haven't
- // already. We dim the last highlighted view so that while a user is
- // scrolling, nothing is highlighted.
- @Override
- public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
- Animator animator = null;
- boolean fadingOut = false;
- if (newState == RecyclerView.SCROLL_STATE_IDLE) {
- // The selector starts with a height of 0. In order to scale up from
- // 0, we first need the set the height to 1 and scale from there.
- View focusedChild = mParentView.getFocusedChild();
- if (focusedChild != null) {
- int selectorHeight = mSelectorView.getHeight();
- float scaleY = (float) focusedChild.getHeight() / selectorHeight;
- AnimatorSet animators = (AnimatorSet)createAnimator(mSelectorView,
- R.attr.guidedActionsSelectorShowAnimation);
- if (mFadedOut) {
- // selector is completely faded out, so we can just scale before fading in.
- mSelectorView.setScaleY(scaleY);
- animator = animators.getChildAnimations().get(0);
- } else {
- // selector is not faded out, so we must animate the scale as we fade in.
- ((ObjectAnimator)animators.getChildAnimations().get(1))
- .setFloatValues(scaleY);
- animator = animators;
- }
- }
- } else {
- animator = createAnimator(mSelectorView, R.attr.guidedActionsSelectorHideAnimation);
- fadingOut = true;
- }
- if (animator != null) {
- animator.addListener(new Listener(fadingOut));
- animator.start();
- }
+ private void updateSelectorView(boolean animate) {
+ if (mActionsGridView == null || mSelectorView == null || mSelectorView.getHeight() <= 0) {
+ return;
}
-
- /**
- * Sets {@link BaseScrollAdapterFragment#mFadedOut}
- * {@link BaseScrollAdapterFragment#mFadedOut} is true, iff
- * {@link BaseScrollAdapterFragment#mSelectorView} has an alpha of 0
- * (faded out). If false the view either has an alpha of 1 (visible) or
- * is in the process of animating.
- */
- private class Listener implements Animator.AnimatorListener {
- private boolean mFadingOut;
- private boolean mCanceled;
-
- public Listener(boolean fadingOut) {
- mFadingOut = fadingOut;
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- if (!mFadingOut) {
- mFadedOut = false;
- }
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!mCanceled && mFadingOut) {
- mFadedOut = true;
- }
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mCanceled = true;
+ final View focusedChild = mActionsGridView.getFocusedChild();
+ endSelectorAnimator();
+ if (focusedChild == null || !mActionsGridView.hasFocus()
+ || mActionsGridView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
+ if (animate) {
+ mSelectorAnimator = createAnimator(mSelectorView,
+ R.attr.guidedActionsSelectorHideAnimation);
+ mSelectorAnimator.start();
+ } else {
+ mSelectorView.setAlpha(0f);
}
-
- @Override
- public void onAnimationRepeat(Animator animation) {
+ } else {
+ final float scaleY = (float) focusedChild.getHeight() / mSelectorView.getHeight();
+ Rect r = new Rect(0, 0, focusedChild.getWidth(), focusedChild.getHeight());
+ mMainView.offsetDescendantRectToMyCoords(focusedChild, r);
+ mMainView.offsetRectIntoDescendantCoords(mSelectorView, r);
+ mSelectorView.setTranslationY(r.exactCenterY() - mSelectorView.getHeight() * 0.5f);
+ if (animate) {
+ mSelectorAnimator = createAnimator(mSelectorView,
+ R.attr.guidedActionsSelectorShowAnimation);
+ ((ObjectAnimator) ((AnimatorSet) mSelectorAnimator).getChildAnimations().get(1))
+ .setFloatValues(scaleY);
+ mSelectorAnimator.start();
+ } else {
+ mSelectorView.setAlpha(1f);
+ mSelectorView.setScaleY(scaleY);
}
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
index 2c1c7e075f..08eb617725 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
@@ -18,58 +18,286 @@ import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.v17.leanback.R;
-import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
+import android.widget.RelativeLayout;
import android.widget.TextView;
/**
- * A subclass of {@link BaseCardView} with an {@link ImageView} as its main region.
+ * A subclass of {@link BaseCardView} with an {@link ImageView} as its main
+ * region. The {@link ImageCardView} is highly customizable and can be used for
+ * various use-cases by adjusting the ImageViewCard's type to any combination of
+ * Title, Content, Badge or ImageOnly.
+ * <p>
+ * <h3>Styling</h3> There are three different ways to style the ImageCardView.
+ * <br>
+ * No matter what way you use, all your styles applied to an ImageCardView have
+ * to extend the style {@link R.style#Widget_Leanback_ImageCardViewStyle}.
+ * <p>
+ * <u>Example:</u><br>
+ *
+ * <pre>
+ * {@code <style name="CustomImageCardViewStyle" parent="Widget.Leanback.ImageCardViewStyle">
+ <item name="cardBackground">#F0F</item>
+ <item name="lbImageCardViewType">Title|Content</item>
+ <item name="lbImageCardViewInfoAreaStyle">@style/ImageCardViewColoredInfoArea</item>
+ <item name="lbImageCardViewTitleStyle">@style/ImageCardViewColoredTitle</item>
+ </style>}
+ * </pre>
+ * <p>
+ * The first possibility is to set a custom Style in the Leanback Theme's
+ * attribute <code>imageCardViewStyle</code>. The style set here, is the default
+ * style for all ImageCardViews. The other two possibilities allow you to style
+ * a particular ImageCardView. This is usefull if you want to create multiple
+ * types of cards. E.g. you might want to display a card with only a title and
+ * another one with title and content. Thus you need to define two different
+ * <code>ImageCardViewStyles</code> and apply them to the ImageCardViews. You
+ * can do this by either using a the {@link #ImageCardView(Context, int)}
+ * constructor and passing a style as second argument or by setting the style in
+ * a layout.
+ * <p>
+ * <u>Example (using constructor):</u><br>
+ *
+ * <pre>
+ * {@code
+ * new ImageCardView(context, R.style.CustomImageCardViewStyle);
+ * }
+ * </pre>
+ *
+ * <u>Example (using style attribute in a layout):</u><br>
+ *
+ * <pre>
+ * {@code <android.support.v17.leanback.widget.ImageCardView
+ android:id="@+id/imageCardView"
+ style="@style/CustomImageCardViewStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ </android.support.v17.leanback.widget.ImageCardView>}
+ * </pre>
+ * <p>
+ * You can style all ImageCardView's components such as the title, content,
+ * badge, infoArea and the image itself by extending the corresponding style and
+ * overriding the specific attribute in your custom
+ * <code>ImageCardViewStyle</code>.
+ *
+ * <h3>Components</h3> The ImageCardView contains three components which can be
+ * combined in any combination:
+ * <ul>
+ * <li>Title: The card's title</li>
+ * <li>Content: A short description</li>
+ * <li>Badge: An icon which can be displayed on the right or left side of the
+ * card.</li>
+ * </ul>
+ * In order to choose the components you want to use in your ImageCardView, you
+ * have to specify them in the <code>lbImageCardViewType</code> attribute of
+ * your custom <code>ImageCardViewStyle</code>. You can combine the following
+ * values: <code>Title, Content, IconOnRight, IconOnLeft, ImageOnly</code>.
+ * <p>
+ * <u>Examples:</u><br>
+ *
+ * <pre>
+ * {@code <style name="CustomImageCardViewStyle" parent="Widget.Leanback.ImageCardViewStyle">
+ ...
+ <item name="lbImageCardViewType">Title|Content|IconOnLeft</item>
+ ...
+ </style>}
+ * </pre>
+ *
+ * <pre>
+ * {@code <style name="CustomImageCardViewStyle" parent="Widget.Leanback.ImageCardViewStyle">
+ ...
+ <item name="lbImageCardViewType">ImageOnly</item>
+ ...
+ </style>}
+ * </pre>
+ *
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackTheme_imageCardViewStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewType
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewTitleStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewContentStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewBadgeStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewImageStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewInfoAreaStyle
*/
public class ImageCardView extends BaseCardView {
+ public static final int CARD_TYPE_FLAG_IMAGE_ONLY = 0;
+ public static final int CARD_TYPE_FLAG_TITLE = 1;
+ public static final int CARD_TYPE_FLAG_CONTENT = 2;
+ public static final int CARD_TYPE_FLAG_ICON_RIGHT = 4;
+ public static final int CARD_TYPE_FLAG_ICON_LEFT = 8;
+
private ImageView mImageView;
- private View mInfoArea;
+ private ViewGroup mInfoArea;
private TextView mTitleView;
private TextView mContentView;
private ImageView mBadgeImage;
private boolean mAttachedToWindow;
- public ImageCardView(Context context) {
- this(context, null);
+ /**
+ * Create an ImageCardView using a given style for customization.
+ *
+ * @param context
+ * The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ * @param styleResId
+ * The resourceId of the style you want to apply to the
+ * ImageCardView. The style has to extend
+ * {@link R.style#Widget_Leanback_ImageCardViewStyle}.
+ */
+ public ImageCardView(Context context, int styleResId) {
+ super(new ContextThemeWrapper(context, styleResId), null, 0);
+ buildImageCardView(styleResId);
}
- public ImageCardView(Context context, AttributeSet attrs) {
- this(context, attrs, R.attr.imageCardViewStyle);
+ /**
+ * @see #View(Context, AttributeSet, int)
+ */
+ public ImageCardView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(getStyledContext(context, attrs, defStyleAttr), attrs, defStyleAttr);
+ buildImageCardView(getImageCardViewStyle(context, attrs, defStyleAttr));
}
- public ImageCardView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
+ private void buildImageCardView(int styleResId) {
+ // Make sure the ImageCardView is focusable.
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ inflater.inflate(R.layout.lb_image_card_view, this);
+ TypedArray cardAttrs = getContext().obtainStyledAttributes(styleResId, R.styleable.lbImageCardView);
+ int cardType = cardAttrs.getInt(R.styleable.lbImageCardView_lbImageCardViewType, CARD_TYPE_FLAG_IMAGE_ONLY);
+ boolean hasImageOnly = cardType == CARD_TYPE_FLAG_IMAGE_ONLY;
+ boolean hasTitle = (cardType & CARD_TYPE_FLAG_TITLE) == CARD_TYPE_FLAG_TITLE;
+ boolean hasContent = (cardType & CARD_TYPE_FLAG_CONTENT) == CARD_TYPE_FLAG_CONTENT;
+ boolean hasIconRight = (cardType & CARD_TYPE_FLAG_ICON_RIGHT) == CARD_TYPE_FLAG_ICON_RIGHT;
+ boolean hasIconLeft = !hasIconRight && (cardType & CARD_TYPE_FLAG_ICON_LEFT) == CARD_TYPE_FLAG_ICON_LEFT;
+
+ mImageView = (ImageView) findViewById(R.id.main_image);
+ if (mImageView.getDrawable() == null) {
+ mImageView.setVisibility(View.INVISIBLE);
+ }
+
+ mInfoArea = (ViewGroup) findViewById(R.id.info_field);
+ if (hasImageOnly) {
+ removeView(mInfoArea);
+ cardAttrs.recycle();
+ return;
+ }
+ // Create children
+ if (hasTitle) {
+ mTitleView = (TextView) inflater.inflate(R.layout.lb_image_card_view_themed_title, mInfoArea, false);
+ mInfoArea.addView(mTitleView);
+ }
+
+ if (hasContent) {
+ mContentView = (TextView) inflater.inflate(R.layout.lb_image_card_view_themed_content, mInfoArea, false);
+ mInfoArea.addView(mContentView);
+ }
- LayoutInflater inflater = LayoutInflater.from(context);
- View v = inflater.inflate(R.layout.lb_image_card_view, this);
+ if (hasIconRight || hasIconLeft) {
+ int layoutId = R.layout.lb_image_card_view_themed_badge_right;
+ if (hasIconLeft) {
+ layoutId = R.layout.lb_image_card_view_themed_badge_left;
+ }
+ mBadgeImage = (ImageView) inflater.inflate(layoutId, mInfoArea, false);
+ mInfoArea.addView(mBadgeImage);
+ }
- mImageView = (ImageView) v.findViewById(R.id.main_image);
- mImageView.setVisibility(View.INVISIBLE);
- mInfoArea = v.findViewById(R.id.info_field);
- mTitleView = (TextView) v.findViewById(R.id.title_text);
- mContentView = (TextView) v.findViewById(R.id.content_text);
- mBadgeImage = (ImageView) v.findViewById(R.id.extra_badge);
+ // Set up LayoutParams for children
+ if (hasTitle && !hasContent && mBadgeImage != null) {
+ RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) mTitleView
+ .getLayoutParams();
+ // Adjust title TextView if there is an icon but no content
+ if (hasIconLeft) {
+ relativeLayoutParams.addRule(RelativeLayout.END_OF, mBadgeImage.getId());
+ } else {
+ relativeLayoutParams.addRule(RelativeLayout.START_OF, mBadgeImage.getId());
+ }
+ mTitleView.setLayoutParams(relativeLayoutParams);
+ }
- if (mInfoArea != null) {
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.lbImageCardView,
- defStyle, 0);
- try {
- setInfoAreaBackground(
- a.getDrawable(R.styleable.lbImageCardView_infoAreaBackground));
- } finally {
- a.recycle();
+ // Set up LayoutParams for children
+ if (hasContent) {
+ RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) mContentView
+ .getLayoutParams();
+ if (!hasTitle) {
+ relativeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ }
+ // Adjust content TextView if icon is on the left
+ if (hasIconLeft) {
+ relativeLayoutParams.removeRule(RelativeLayout.START_OF);
+ relativeLayoutParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
+ relativeLayoutParams.addRule(RelativeLayout.END_OF, mBadgeImage.getId());
+ }
+ mContentView.setLayoutParams(relativeLayoutParams);
+ }
+
+ if (mBadgeImage != null) {
+ RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) mBadgeImage
+ .getLayoutParams();
+ if (hasContent) {
+ relativeLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mContentView.getId());
+ } else if (hasTitle) {
+ relativeLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mTitleView.getId());
}
+ mBadgeImage.setLayoutParams(relativeLayoutParams);
+ }
+
+ // Backward compatibility: Newly created ImageCardViews should change
+ // the InfoArea's background color in XML using the corresponding style.
+ // However, since older implementations might make use of the
+ // 'infoAreaBackground' attribute, we have to make sure to support it.
+ // If the user has set a specific value here, it will differ from null.
+ // In this case, we do want to override the value set in the style.
+ Drawable background = cardAttrs.getDrawable(R.styleable.lbImageCardView_infoAreaBackground);
+ if (null != background) {
+ setInfoAreaBackground(background);
}
+ // Backward compatibility: There has to be an icon in the default
+ // version. If there is one, we have to set it's visibility to 'GONE'.
+ // Disabling 'adjustIconVisibility' allows the user to set the icon's
+ // visibility state in XML rather than code.
+ if (mBadgeImage != null && mBadgeImage.getDrawable() == null) {
+ mBadgeImage.setVisibility(View.GONE);
+ }
+ cardAttrs.recycle();
+ }
+
+ private static Context getStyledContext(Context context, AttributeSet attrs, int defStyleAttr) {
+ int style = getImageCardViewStyle(context, attrs, defStyleAttr);
+ return new ContextThemeWrapper(context, style);
+ }
+
+ private static int getImageCardViewStyle(Context context, AttributeSet attrs, int defStyleAttr) {
+ // Read style attribute defined in XML layout.
+ int style = null == attrs ? 0 : attrs.getStyleAttribute();
+ if (0 == style) {
+ // Not found? Read global ImageCardView style from Theme attribute.
+ TypedArray styledAttrs = context.obtainStyledAttributes(R.styleable.LeanbackTheme);
+ style = styledAttrs.getResourceId(R.styleable.LeanbackTheme_imageCardViewStyle, 0);
+ styledAttrs.recycle();
+ }
+ return style;
+ }
+
+ /**
+ * @see #View(Context)
+ */
+ public ImageCardView(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * @see #View(Context, AttributeSet)
+ */
+ public ImageCardView(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.imageCardViewStyle);
}
/**
@@ -170,7 +398,7 @@ public class ImageCardView extends BaseCardView {
/**
* Sets the info area background color.
- */
+ */
public void setInfoAreaBackgroundColor(@ColorInt int color) {
if (mInfoArea != null) {
mInfoArea.setBackgroundColor(color);
@@ -184,7 +412,6 @@ public class ImageCardView extends BaseCardView {
if (mTitleView == null) {
return;
}
-
mTitleView.setText(text);
}
@@ -206,7 +433,6 @@ public class ImageCardView extends BaseCardView {
if (mContentView == null) {
return;
}
-
mContentView.setText(text);
}
@@ -229,7 +455,7 @@ public class ImageCardView extends BaseCardView {
return;
}
mBadgeImage.setImageDrawable(drawable);
- if (drawable != null && mContentView!= null && mContentView.getVisibility() != GONE) {
+ if (drawable != null) {
mBadgeImage.setVisibility(View.VISIBLE);
} else {
mBadgeImage.setVisibility(View.GONE);
@@ -250,8 +476,8 @@ public class ImageCardView extends BaseCardView {
private void fadeIn() {
mImageView.setAlpha(0f);
if (mAttachedToWindow) {
- mImageView.animate().alpha(1f).setDuration(mImageView.getResources().getInteger(
- android.R.integer.config_shortAnimTime));
+ mImageView.animate().alpha(1f)
+ .setDuration(mImageView.getResources().getInteger(android.R.integer.config_shortAnimTime));
}
}
@@ -276,4 +502,5 @@ public class ImageCardView extends BaseCardView {
mImageView.setAlpha(1f);
super.onDetachedFromWindow();
}
+
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java b/v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java
new file mode 100644
index 0000000000..4691ad2bc0
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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 android.support.v17.leanback.widget;
+
+import android.widget.EditText;
+import android.view.KeyEvent;
+
+/**
+ * Interface for an EditText subclass that can delegate calls to onKeyPreIme up to a registered
+ * listener.
+ * <p>
+ * Used in editable actions within {@link android.support.v17.leanback.app.GuidedStepFragment} to
+ * allow for custom back key handling. Specifically, this is used to implement the behavior that
+ * dismissing the IME also clears edit text focus. Clients who need to supply custom layouts for
+ * {@link GuidedActionsStylist} with their own EditText classes should satisfy this interface in
+ * order to inherit this behavior.
+ */
+public interface ImeKeyMonitor {
+
+ /**
+ * Listener interface for key events intercepted pre-IME by edit text objects.
+ */
+ public interface ImeKeyListener {
+ /**
+ * Callback invoked from EditText's onKeyPreIme method override. Returning true tells the
+ * caller that the key event is handled and should not be propagated.
+ */
+ public abstract boolean onKeyPreIme(EditText editText, int keyCode, KeyEvent event);
+ }
+
+ /**
+ * Set the listener for this edit text object. The listener's onKeyPreIme method will be
+ * invoked from the host edit text's onKeyPreIme method.
+ */
+ public void setImeKeyListener(ImeKeyListener listener);
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ItemBridgeAdapter.java b/v17/leanback/src/android/support/v17/leanback/widget/ItemBridgeAdapter.java
index 8e3aea3fe7..57e8bfe356 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ItemBridgeAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ItemBridgeAdapter.java
@@ -177,11 +177,15 @@ public class ItemBridgeAdapter extends RecyclerView.Adapter implements FacetProv
* Sets the {@link ObjectAdapter}.
*/
public void setAdapter(ObjectAdapter adapter) {
+ if (adapter == mAdapter) {
+ return;
+ }
if (mAdapter != null) {
mAdapter.unregisterObserver(mDataObserver);
}
mAdapter = adapter;
if (mAdapter == null) {
+ notifyDataSetChanged();
return;
}
@@ -189,6 +193,7 @@ public class ItemBridgeAdapter extends RecyclerView.Adapter implements FacetProv
if (hasStableIds() != mAdapter.hasStableIds()) {
setHasStableIds(mAdapter.hasStableIds());
}
+ notifyDataSetChanged();
}
/**
@@ -233,7 +238,7 @@ public class ItemBridgeAdapter extends RecyclerView.Adapter implements FacetProv
@Override
public int getItemCount() {
- return mAdapter.size();
+ return mAdapter != null ? mAdapter.size() : 0;
}
@Override
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ItemBridgeAdapterShadowOverlayWrapper.java b/v17/leanback/src/android/support/v17/leanback/widget/ItemBridgeAdapterShadowOverlayWrapper.java
new file mode 100644
index 0000000000..19e6e9a6fa
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ItemBridgeAdapterShadowOverlayWrapper.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+
+/**
+ * A wrapper class working with {@link ItemBridgeAdapter} to wrap item view in a
+ * {@link ShadowOverlayContainer}. The ShadowOverlayContainer is created from conditions
+ * of {@link ShadowOverlayHelper}.
+ */
+public class ItemBridgeAdapterShadowOverlayWrapper extends ItemBridgeAdapter.Wrapper {
+
+ private final ShadowOverlayHelper mHelper;
+
+ public ItemBridgeAdapterShadowOverlayWrapper(ShadowOverlayHelper helper) {
+ mHelper = helper;
+ }
+
+ @Override
+ public View createWrapper(View root) {
+ Context context = root.getContext();
+ ShadowOverlayContainer wrapper = mHelper.createShadowOverlayContainer(context);
+ return wrapper;
+ }
+ @Override
+ public void wrap(View wrapper, View wrapped) {
+ ((ShadowOverlayContainer) wrapper).wrap(wrapped);
+ }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
index 9e588ebf0a..5540f788ed 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
@@ -15,8 +15,10 @@ package android.support.v17.leanback.widget;
import android.content.Context;
import android.content.res.TypedArray;
+import android.os.Build;
import android.support.v17.leanback.R;
import android.support.v17.leanback.system.Settings;
+import android.support.v17.leanback.transition.TransitionHelper;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
@@ -96,6 +98,16 @@ public class ListRowPresenter extends RowPresenter {
}
@Override
+ protected void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
+ if (viewHolder.itemView instanceof ViewGroup) {
+ TransitionHelper.setTransitionGroup((ViewGroup) viewHolder.itemView, true);
+ }
+ if (mShadowOverlayHelper != null) {
+ mShadowOverlayHelper.onViewCreated(viewHolder.itemView);
+ }
+ }
+
+ @Override
public void onBind(final ItemBridgeAdapter.ViewHolder viewHolder) {
// Only when having an OnItemClickListner, we will attach the OnClickListener.
if (mRowViewHolder.getOnItemViewClickedListener() != null) {
@@ -122,9 +134,9 @@ public class ListRowPresenter extends RowPresenter {
@Override
public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
- if (needsDefaultListSelectEffect()) {
+ if (mShadowOverlayHelper != null && mShadowOverlayHelper.needsOverlay()) {
int dimmedColor = mRowViewHolder.mColorDimmer.getPaint().getColor();
- ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor);
+ mShadowOverlayHelper.setOverlayColor(viewHolder.itemView, dimmedColor);
}
mRowViewHolder.syncActivatedStatus(viewHolder.itemView);
}
@@ -144,7 +156,10 @@ public class ListRowPresenter extends RowPresenter {
private boolean mShadowEnabled = true;
private int mBrowseRowsFadingEdgeLength = -1;
private boolean mRoundedCornersEnabled = true;
+ private boolean mKeepChildForeground = true;
private HashMap<Presenter, Integer> mRecycledPoolSize = new HashMap<Presenter, Integer>();
+ private ShadowOverlayHelper mShadowOverlayHelper;
+ private ItemBridgeAdapter.Wrapper mShadowOverlayWrapper;
private static int sSelectedRowTopPadding;
private static int sExpandedSelectedRowTopPadding;
@@ -253,44 +268,34 @@ public class ListRowPresenter extends RowPresenter {
return mUseFocusDimmer;
}
- private ItemBridgeAdapter.Wrapper mCardWrapper = new ItemBridgeAdapter.Wrapper() {
- @Override
- public View createWrapper(View root) {
- ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
- wrapper.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- if (isUsingZOrder(root.getContext())) {
- wrapper.useDynamicShadow();
- } else {
- wrapper.useStaticShadow();
- }
- wrapper.initialize(needsDefaultShadow(),
- needsDefaultListSelectEffect(),
- areChildRoundedCornersEnabled());
- return wrapper;
- }
- @Override
- public void wrap(View wrapper, View wrapped) {
- ((ShadowOverlayContainer) wrapper).wrap(wrapped);
- }
- };
-
@Override
protected void initializeRowViewHolder(RowPresenter.ViewHolder holder) {
super.initializeRowViewHolder(holder);
final ViewHolder rowViewHolder = (ViewHolder) holder;
- rowViewHolder.mItemBridgeAdapter = new ListRowPresenterItemBridgeAdapter(rowViewHolder);
- if (needsDefaultListSelectEffect() || needsDefaultShadow()
- || areChildRoundedCornersEnabled()) {
- rowViewHolder.mItemBridgeAdapter.setWrapper(mCardWrapper);
- }
- if (needsDefaultShadow()) {
- ShadowOverlayContainer.prepareParentForShadow(rowViewHolder.mGridView);
+ Context context = holder.view.getContext();
+ if (mShadowOverlayHelper == null) {
+ mShadowOverlayHelper = new ShadowOverlayHelper.Builder()
+ .needsOverlay(needsDefaultListSelectEffect())
+ .needsShadow(needsDefaultShadow())
+ .needsRoundedCorner(areChildRoundedCornersEnabled())
+ .preferZOrder(isUsingZOrder(context))
+ .keepForegroundDrawable(mKeepChildForeground)
+ .options(createShadowOverlayOptions())
+ .build(context);
+ if (mShadowOverlayHelper.needsWrapper()) {
+ mShadowOverlayWrapper = new ItemBridgeAdapterShadowOverlayWrapper(
+ mShadowOverlayHelper);
+ }
}
+ rowViewHolder.mItemBridgeAdapter = new ListRowPresenterItemBridgeAdapter(rowViewHolder);
+ // set wrapper if needed
+ rowViewHolder.mItemBridgeAdapter.setWrapper(mShadowOverlayWrapper);
+ mShadowOverlayHelper.prepareParentForShadow(rowViewHolder.mGridView);
+
FocusHighlightHelper.setupBrowseItemFocusHighlight(rowViewHolder.mItemBridgeAdapter,
mFocusZoomFactor, mUseFocusDimmer);
- rowViewHolder.mGridView.setFocusDrawingOrderEnabled(
- !isUsingZOrder(rowViewHolder.getGridView().getContext()));
+ rowViewHolder.mGridView.setFocusDrawingOrderEnabled(mShadowOverlayHelper.getShadowType()
+ == ShadowOverlayHelper.SHADOW_STATIC);
rowViewHolder.mGridView.setOnChildSelectedListener(
new OnChildSelectedListener() {
@Override
@@ -545,7 +550,7 @@ public class ListRowPresenter extends RowPresenter {
* Subclass may return false to disable.
*/
public boolean isUsingDefaultShadow() {
- return ShadowOverlayContainer.supportsShadow();
+ return ShadowOverlayHelper.supportsShadow();
}
/**
@@ -554,8 +559,7 @@ public class ListRowPresenter extends RowPresenter {
* and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false.
*/
public boolean isUsingZOrder(Context context) {
- return ShadowOverlayContainer.supportsDynamicShadow() &&
- !Settings.getInstance(context).preferStaticShadows();
+ return !Settings.getInstance(context).preferStaticShadows();
}
/**
@@ -595,9 +599,41 @@ public class ListRowPresenter extends RowPresenter {
return isUsingDefaultShadow() && getShadowEnabled();
}
- @Override
- public boolean canDrawOutOfBounds() {
- return needsDefaultShadow();
+ /**
+ * When ListRowPresenter applies overlay color on the child, it may change child's foreground
+ * Drawable. If application uses child's foreground for other purposes such as ripple effect,
+ * it needs tell ListRowPresenter to keep the child's foreground. The default value is true.
+ *
+ * @param keep true if keep foreground of child of this row, false ListRowPresenter might change
+ * the foreground of the child.
+ */
+ public final void setKeepChildForeground(boolean keep) {
+ mKeepChildForeground = keep;
+ }
+
+ /**
+ * Returns true if keeps foreground of child of this row, false otherwise. When
+ * ListRowPresenter applies overlay color on the child, it may change child's foreground
+ * Drawable. If application uses child's foreground for other purposes such as ripple effect,
+ * it needs tell ListRowPresenter to keep the child's foreground. The default value is true.
+ *
+ * @return true if keeps foreground of child of this row, false otherwise.
+ */
+ public final boolean isKeepChildForeground() {
+ return mKeepChildForeground;
+ }
+
+ /**
+ * Create ShadowOverlayHelper Options. Subclass may override.
+ * e.g.
+ * <code>
+ * return new ShadowOverlayHelper.Options().roundedCornerRadius(10);
+ * </code>
+ *
+ * @return The options to be used for shadow, overlay and rouded corner.
+ */
+ protected ShadowOverlayHelper.Options createShadowOverlayOptions() {
+ return ShadowOverlayHelper.Options.DEFAULT;
}
/**
@@ -615,12 +651,11 @@ public class ListRowPresenter extends RowPresenter {
@Override
protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) {
super.onSelectLevelChanged(holder);
- if (needsDefaultListSelectEffect()) {
+ if (mShadowOverlayHelper != null && mShadowOverlayHelper.needsOverlay()) {
ViewHolder vh = (ViewHolder) holder;
int dimmedColor = vh.mColorDimmer.getPaint().getColor();
for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
- ShadowOverlayContainer wrapper = (ShadowOverlayContainer) vh.mGridView.getChildAt(i);
- wrapper.setOverlayColor(dimmedColor);
+ mShadowOverlayHelper.setOverlayColor(vh.mGridView.getChildAt(i), dimmedColor);
}
if (vh.mGridView.getFadingLeftEdge()) {
vh.mGridView.invalidate();
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsPresenter.java
index f1db00bbe1..17225f8863 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsPresenter.java
@@ -58,7 +58,7 @@ class PlaybackControlsPresenter extends ControlBarPresenter {
final TextView mCurrentTime;
final TextView mTotalTime;
final ProgressBar mProgressBar;
- int mCurrentTimeInSeconds;
+ int mCurrentTimeInSeconds = -1;
StringBuilder mTotalTimeStringBuilder = new StringBuilder();
StringBuilder mCurrentTimeStringBuilder = new StringBuilder();
int mCurrentTimeMarginStart;
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java
index e1c59797ea..35a5b6703a 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java
@@ -13,8 +13,7 @@
*/
package android.support.v17.leanback.widget;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
+import android.support.v17.leanback.R;
import android.os.Build;
import android.view.View;
@@ -24,7 +23,7 @@ import android.view.View;
final class RoundedRectHelper {
private final static RoundedRectHelper sInstance = new RoundedRectHelper();
- private Impl mImpl;
+ private final Impl mImpl;
/**
* Returns an instance of the helper.
@@ -33,15 +32,27 @@ final class RoundedRectHelper {
return sInstance;
}
+ public static boolean supportsRoundedCorner() {
+ return Build.VERSION.SDK_INT >= 21;
+ }
+
+ /**
+ * Sets or removes a rounded rectangle outline on the given view.
+ */
+ public void setClipToRoundedOutline(View view, boolean clip, int radius) {
+ mImpl.setClipToRoundedOutline(view, clip, radius);
+ }
+
/**
* Sets or removes a rounded rectangle outline on the given view.
*/
public void setClipToRoundedOutline(View view, boolean clip) {
- mImpl.setClipToRoundedOutline(view, clip);
+ mImpl.setClipToRoundedOutline(view, clip, view.getResources().getDimensionPixelSize(
+ R.dimen.lb_rounded_rect_corner_radius));
}
static interface Impl {
- public void setClipToRoundedOutline(View view, boolean clip);
+ public void setClipToRoundedOutline(View view, boolean clip, int radius);
}
/**
@@ -49,7 +60,7 @@ final class RoundedRectHelper {
*/
private static final class StubImpl implements Impl {
@Override
- public void setClipToRoundedOutline(View view, boolean clip) {
+ public void setClipToRoundedOutline(View view, boolean clip, int radius) {
// Not supported
}
}
@@ -59,13 +70,13 @@ final class RoundedRectHelper {
*/
private static final class Api21Impl implements Impl {
@Override
- public void setClipToRoundedOutline(View view, boolean clip) {
- RoundedRectHelperApi21.setClipToRoundedOutline(view, clip);
+ public void setClipToRoundedOutline(View view, boolean clip, int radius) {
+ RoundedRectHelperApi21.setClipToRoundedOutline(view, clip, radius);
}
}
private RoundedRectHelper() {
- if (Build.VERSION.SDK_INT >= 21) {
+ if (supportsRoundedCorner()) {
mImpl = new Api21Impl();
} else {
mImpl = new StubImpl();
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/RowPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/RowPresenter.java
index 4f078f14d5..cb1f2ac7cc 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/RowPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/RowPresenter.java
@@ -565,13 +565,6 @@ public abstract class RowPresenter extends Presenter {
return mHeaderPresenter != null || needsDefaultSelectEffect();
}
- /**
- * Returns true if the Row view can draw outside its bounds.
- */
- public boolean canDrawOutOfBounds() {
- return false;
- }
-
@Override
public final void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
onBindRowViewHolder(getRowViewHolder(viewHolder), item);
@@ -642,12 +635,16 @@ public abstract class RowPresenter extends Presenter {
* Changes the visibility of views. The entrance transition will be run against the views that
* change visibilities. A subclass may override and begin with calling
* super.setEntranceTransitionState(). This method is called by the fragment,
- * it should not call it directly by the application.
+ * it should not be called directly by the application.
+ *
+ * @param holder The ViewHolder of the row.
+ * @param afterEntrance true if children of row participating in entrance transition
+ * should be set to visible, false otherwise.
*/
- public void setEntranceTransitionState(ViewHolder holder, boolean afterTransition) {
+ public void setEntranceTransitionState(ViewHolder holder, boolean afterEntrance) {
if (holder.mHeaderViewHolder != null &&
holder.mHeaderViewHolder.view.getVisibility() != View.GONE) {
- holder.mHeaderViewHolder.view.setVisibility(afterTransition ?
+ holder.mHeaderViewHolder.view.setVisibility(afterEntrance ?
View.VISIBLE : View.INVISIBLE);
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/SearchBar.java b/v17/leanback/src/android/support/v17/leanback/widget/SearchBar.java
index acdebcb0ab..1c3835fa18 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/SearchBar.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/SearchBar.java
@@ -406,15 +406,23 @@ public class SearchBar extends RelativeLayout {
* @param completions list of completions shown in the IME, can be null or empty to clear them
*/
public void displayCompletions(List<String> completions) {
- List<CompletionInfo> infos = new ArrayList<CompletionInfo>();
+ List<CompletionInfo> infos = new ArrayList<>();
if (null != completions) {
for (String completion : completions) {
infos.add(new CompletionInfo(infos.size(), infos.size(), completion));
}
}
+ CompletionInfo[] array = new CompletionInfo[infos.size()];
+ displayCompletions(infos.toArray(array));
+ }
- mInputMethodManager.displayCompletions(mSearchTextEditor,
- infos.toArray(new CompletionInfo[] {}));
+ /**
+ * Updates the completion list shown by the IME
+ *
+ * @param completions list of completions shown in the IME, can be null or empty to clear them
+ */
+ public void displayCompletions(CompletionInfo[] completions) {
+ mInputMethodManager.displayCompletions(mSearchTextEditor, completions);
}
/**
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java
index be70575a92..aec9673eef 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java
@@ -14,7 +14,6 @@
package android.support.v17.leanback.widget;
import android.os.Build;
-import android.view.ViewGroup;
import android.view.View;
@@ -32,7 +31,7 @@ final class ShadowHelper {
*/
static interface ShadowHelperVersionImpl {
public Object addDynamicShadow(
- ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners);
+ View shadowContainer, float unfocusedZ, float focusedZ, int roundedCornerRadius);
public void setZ(View view, float z);
public void setShadowFocusLevel(Object impl, float level);
}
@@ -43,7 +42,7 @@ final class ShadowHelper {
private static final class ShadowHelperStubImpl implements ShadowHelperVersionImpl {
@Override
public Object addDynamicShadow(
- ViewGroup shadowContainer, float focusedZ, float unfocusedZ, boolean roundedCorners) {
+ View shadowContainer, float focusedZ, float unfocusedZ, int roundedCornerRadius) {
// do nothing
return null;
}
@@ -65,9 +64,9 @@ final class ShadowHelper {
private static final class ShadowHelperApi21Impl implements ShadowHelperVersionImpl {
@Override
public Object addDynamicShadow(
- ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
+ View shadowContainer, float unfocusedZ, float focusedZ, int roundedCornerRadius) {
return ShadowHelperApi21.addDynamicShadow(
- shadowContainer, unfocusedZ, focusedZ, roundedCorners);
+ shadowContainer, unfocusedZ, focusedZ, roundedCornerRadius);
}
@Override
@@ -102,8 +101,8 @@ final class ShadowHelper {
}
public Object addDynamicShadow(
- ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
- return mImpl.addDynamicShadow(shadowContainer, unfocusedZ, focusedZ, roundedCorners);
+ View shadowContainer, float unfocusedZ, float focusedZ, int roundedCornerRadius) {
+ return mImpl.addDynamicShadow(shadowContainer, unfocusedZ, focusedZ, roundedCornerRadius);
}
public void setShadowFocusLevel(Object impl, float level) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
index e367494dc7..fdb7c7122d 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
@@ -20,11 +20,16 @@ import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.Rect;
/**
* Provides an SDK version-independent wrapper to support shadows, color overlays, and rounded
- * corners.
+ * corners. It's not always preferred to create a ShadowOverlayContainer, use
+ * {@link ShadowOverlayHelper} instead.
* <p>
* {@link #prepareParentForShadow(ViewGroup)} must be called on parent of container
* before using shadow. Depending on sdk version, optical bounds might be applied
@@ -46,41 +51,52 @@ import android.graphics.Rect;
* Call {@link #setOverlayColor(int)} to control overlay color.
* </p>
*/
-public class ShadowOverlayContainer extends ViewGroup {
+public class ShadowOverlayContainer extends FrameLayout {
/**
* No shadow.
*/
- public static final int SHADOW_NONE = 1;
+ public static final int SHADOW_NONE = ShadowOverlayHelper.SHADOW_NONE;
/**
* Shadows are fixed.
*/
- public static final int SHADOW_STATIC = 2;
+ public static final int SHADOW_STATIC = ShadowOverlayHelper.SHADOW_STATIC;
/**
* Shadows depend on the size, shape, and position of the view.
*/
- public static final int SHADOW_DYNAMIC = 3;
+ public static final int SHADOW_DYNAMIC = ShadowOverlayHelper.SHADOW_DYNAMIC;
private boolean mInitialized;
- private View mColorDimOverlay;
private Object mShadowImpl;
private View mWrappedView;
private boolean mRoundedCorners;
private int mShadowType = SHADOW_NONE;
private float mUnfocusedZ;
private float mFocusedZ;
+ private int mRoundedCornerRadius;
private static final Rect sTempRect = new Rect();
+ private Paint mOverlayPaint;
+ private int mOverlayColor;
+ /**
+ * Create ShadowOverlayContainer and auto select shadow type.
+ */
public ShadowOverlayContainer(Context context) {
this(context, null, 0);
}
+ /**
+ * Create ShadowOverlayContainer and auto select shadow type.
+ */
public ShadowOverlayContainer(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
+ /**
+ * Create ShadowOverlayContainer and auto select shadow type.
+ */
public ShadowOverlayContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
useStaticShadow();
@@ -88,6 +104,18 @@ public class ShadowOverlayContainer extends ViewGroup {
}
/**
+ * Create ShadowOverlayContainer with specific shadowType.
+ */
+ ShadowOverlayContainer(Context context,
+ int shadowType, boolean hasColorDimOverlay,
+ float unfocusedZ, float focusedZ, int roundedCornerRadius) {
+ super(context);
+ mUnfocusedZ = unfocusedZ;
+ mFocusedZ = focusedZ;
+ initialize(shadowType, hasColorDimOverlay, roundedCornerRadius);
+ }
+
+ /**
* Return true if the platform sdk supports shadow.
*/
public static boolean supportsShadow() {
@@ -155,7 +183,7 @@ public class ShadowOverlayContainer extends ViewGroup {
/**
* Initialize shadows, color overlay.
- * @deprecated use {@link #initialize(boolean, boolean, boolean)} instead.
+ * @deprecated use {@link ShadowOverlayHelper#createShadowOverlayContainer(Context)} instead.
*/
@Deprecated
public void initialize(boolean hasShadow, boolean hasColorDimOverlay) {
@@ -164,29 +192,62 @@ public class ShadowOverlayContainer extends ViewGroup {
/**
* Initialize shadows, color overlay, and rounded corners. All are optional.
+ * Shadow type are auto-selected based on {@link #useStaticShadow()} and
+ * {@link #useDynamicShadow()} call.
+ * @deprecated use {@link ShadowOverlayHelper#createShadowOverlayContainer(Context)} instead.
*/
+ @Deprecated
public void initialize(boolean hasShadow, boolean hasColorDimOverlay, boolean roundedCorners) {
+ int shadowType;
+ if (!hasShadow) {
+ shadowType = SHADOW_NONE;
+ } else {
+ shadowType = mShadowType;
+ }
+ int roundedCornerRadius = roundedCorners ? getContext().getResources().getDimensionPixelSize(
+ R.dimen.lb_rounded_rect_corner_radius) : 0;
+ initialize(shadowType, hasColorDimOverlay, roundedCornerRadius);
+ }
+
+ /**
+ * Initialize shadows, color overlay, and rounded corners. All are optional.
+ */
+ void initialize(int shadowType, boolean hasColorDimOverlay, int roundedCornerRadius) {
if (mInitialized) {
throw new IllegalStateException();
}
mInitialized = true;
- if (hasShadow) {
- switch (mShadowType) {
- case SHADOW_DYNAMIC:
- mShadowImpl = ShadowHelper.getInstance().addDynamicShadow(
- this, mUnfocusedZ, mFocusedZ, roundedCorners);
- break;
- case SHADOW_STATIC:
- mShadowImpl = StaticShadowHelper.getInstance().addStaticShadow(
- this, roundedCorners);
- break;
- }
+ mRoundedCornerRadius = roundedCornerRadius;
+ mRoundedCorners = roundedCornerRadius > 0;
+ mShadowType = shadowType;
+ switch (mShadowType) {
+ case SHADOW_DYNAMIC:
+ mShadowImpl = ShadowHelper.getInstance().addDynamicShadow(
+ this, mUnfocusedZ, mFocusedZ, mRoundedCornerRadius);
+ break;
+ case SHADOW_STATIC:
+ mShadowImpl = StaticShadowHelper.getInstance().addStaticShadow(this);
+ break;
}
- mRoundedCorners = roundedCorners;
if (hasColorDimOverlay) {
- mColorDimOverlay = LayoutInflater.from(getContext())
- .inflate(R.layout.lb_card_color_overlay, this, false);
- addView(mColorDimOverlay);
+ setWillNotDraw(false);
+ mOverlayColor = Color.TRANSPARENT;
+ mOverlayPaint = new Paint();
+ mOverlayPaint.setColor(mOverlayColor);
+ mOverlayPaint.setStyle(Paint.Style.FILL);
+ } else {
+ setWillNotDraw(true);
+ mOverlayPaint = null;
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ if (mOverlayPaint != null && mOverlayColor != Color.TRANSPARENT) {
+ canvas.drawRect(mWrappedView.getLeft(), mWrappedView.getTop(),
+ mWrappedView.getRight(), mWrappedView.getBottom(),
+ mOverlayPaint);
}
}
@@ -195,19 +256,7 @@ public class ShadowOverlayContainer extends ViewGroup {
*/
public void setShadowFocusLevel(float level) {
if (mShadowImpl != null) {
- if (level < 0f) {
- level = 0f;
- } else if (level > 1f) {
- level = 1f;
- }
- switch (mShadowType) {
- case SHADOW_DYNAMIC:
- ShadowHelper.getInstance().setShadowFocusLevel(mShadowImpl, level);
- break;
- case SHADOW_STATIC:
- StaticShadowHelper.getInstance().setShadowFocusLevel(mShadowImpl, level);
- break;
- }
+ ShadowOverlayHelper.setShadowFocusLevel(mShadowImpl, mShadowType, level);
}
}
@@ -215,8 +264,12 @@ public class ShadowOverlayContainer extends ViewGroup {
* Set color (with alpha) of the overlay.
*/
public void setOverlayColor(@ColorInt int overlayColor) {
- if (mColorDimOverlay != null) {
- mColorDimOverlay.setBackgroundColor(overlayColor);
+ if (mOverlayPaint != null) {
+ if (overlayColor != mOverlayColor) {
+ mOverlayColor = overlayColor;
+ mOverlayPaint.setColor(overlayColor);
+ invalidate();
+ }
}
}
@@ -227,15 +280,27 @@ public class ShadowOverlayContainer extends ViewGroup {
if (!mInitialized || mWrappedView != null) {
throw new IllegalStateException();
}
- if (mColorDimOverlay != null) {
- addView(view, indexOfChild(mColorDimOverlay));
+ ViewGroup.LayoutParams lp = view.getLayoutParams();
+ if (lp != null) {
+ // if wrapped view has layout params, inherit everything but width/height.
+ // Wrapped view is assigned a FrameLayout.LayoutParams with width and height only.
+ // Margins, etc are assigned to the wrapper and take effect in parent container.
+ ViewGroup.LayoutParams wrapped_lp = new FrameLayout.LayoutParams(lp.width, lp.height);
+ // Uses MATCH_PARENT for MATCH_PARENT, WRAP_CONTENT for WRAP_CONTENT and fixed size,
+ // App can still change wrapped view fixed width/height afterwards.
+ lp.width = lp.width == LayoutParams.MATCH_PARENT ?
+ LayoutParams.MATCH_PARENT : LayoutParams.WRAP_CONTENT;
+ lp.height = lp.height == LayoutParams.MATCH_PARENT ?
+ LayoutParams.MATCH_PARENT : LayoutParams.WRAP_CONTENT;
+ this.setLayoutParams(lp);
+ addView(view, wrapped_lp);
} else {
addView(view);
}
- mWrappedView = view;
- if (mRoundedCorners) {
- RoundedRectHelper.getInstance().setClipToRoundedOutline(mWrappedView, true);
+ if (mRoundedCorners && mShadowType == SHADOW_STATIC) {
+ RoundedRectHelper.getInstance().setClipToRoundedOutline(view, true);
}
+ mWrappedView = view;
}
/**
@@ -246,67 +311,9 @@ public class ShadowOverlayContainer extends ViewGroup {
}
@Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mWrappedView == null) {
- throw new IllegalStateException();
- }
- // padding and child margin are not supported.
- // first measure the wrapped view, then measure the shadow view and/or overlay view.
- int childWidthMeasureSpec, childHeightMeasureSpec;
- LayoutParams lp = mWrappedView.getLayoutParams();
- if (lp.width == LayoutParams.MATCH_PARENT) {
- childWidthMeasureSpec = MeasureSpec.makeMeasureSpec
- (MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY);
- } else {
- childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
- }
- if (lp.height == LayoutParams.MATCH_PARENT) {
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec
- (MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
- } else {
- childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height);
- }
- mWrappedView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
-
- int measuredWidth = mWrappedView.getMeasuredWidth();
- int measuredHeight = mWrappedView.getMeasuredHeight();
-
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child == mWrappedView) {
- continue;
- }
- lp = child.getLayoutParams();
- if (lp.width == LayoutParams.MATCH_PARENT) {
- childWidthMeasureSpec = MeasureSpec.makeMeasureSpec
- (measuredWidth, MeasureSpec.EXACTLY);
- } else {
- childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
- }
-
- if (lp.height == LayoutParams.MATCH_PARENT) {
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec
- (measuredHeight, MeasureSpec.EXACTLY);
- } else {
- childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height);
- }
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
- setMeasuredDimension(measuredWidth, measuredHeight);
- }
-
- @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- final int width = child.getMeasuredWidth();
- final int height = child.getMeasuredHeight();
- child.layout(0, 0, width, height);
- }
- }
- if (mWrappedView != null) {
+ super.onLayout(changed, l, t, r, b);
+ if (changed && mWrappedView != null) {
sTempRect.left = (int) mWrappedView.getPivotX();
sTempRect.top = (int) mWrappedView.getPivotY();
offsetDescendantRectToMyCoords(mWrappedView, sTempRect);
@@ -315,4 +322,8 @@ public class ShadowOverlayContainer extends ViewGroup {
}
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java
new file mode 100644
index 0000000000..5f942c6930
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.support.v17.leanback.R;
+import android.support.v17.leanback.system.Settings;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.View;
+
+
+/**
+ * ShadowOverlayHelper is a helper class for shadow, overlay color and rounded corner.
+ * There are many choices to implement Shadow, overlay color.
+ * Initialize it with ShadowOverlayHelper.Builder and it decides the best strategy based
+ * on options user choose and current platform version.
+ *
+ * <li> For shadow: it may use 9-patch with opticalBounds or Z-value based shadow for
+ * API >= 21. When 9-patch is used, it requires a ShadowOverlayContainer
+ * to include 9-patch views.
+ * <li> For overlay: it may use ShadowOverlayContainer which overrides draw() or it may
+ * use setForeground(new ColorDrawable()) for API>=23. The foreground support
+ * might be disabled if rounded corner is applied due to performance reason.
+ * <li> For rounded-corner: it uses a ViewOutlineProvider for API>=21.
+ *
+ * There are two different strategies: use Wrapper with a ShadowOverlayContainer;
+ * or apply rounded corner, overlay and rounded-corner to the view itself. Below is an example
+ * of how helper is used.
+ *
+ * <code>
+ * ShadowOverlayHelper mHelper = new ShadowOverlayHelper.Builder().
+ * .needsOverlay(true).needsRoundedCorner(true).needsShadow(true)
+ * .build();
+ * mHelper.prepareParentForShadow(parentView); // apply optical-bounds for 9-patch shadow.
+ * mHelper.setOverlayColor(view, Color.argb(0x80, 0x80, 0x80, 0x80));
+ * mHelper.setShadowFocusLevel(view, 1.0f);
+ * ...
+ * View initializeView(View view) {
+ * if (mHelper.needsWrapper()) {
+ * ShadowOverlayContainer wrapper = mHelper.createShadowOverlayContainer(context);
+ * wrapper.wrap(view);
+ * return wrapper;
+ * } else {
+ * mHelper.onViewCreated(view);
+ * return view;
+ * }
+ * }
+ * ...
+ *
+ * </code>
+ */
+public final class ShadowOverlayHelper {
+
+ /**
+ * Builder for creating ShadowOverlayHelper.
+ */
+ public static final class Builder {
+
+ private boolean needsOverlay;
+ private boolean needsRoundedCorner;
+ private boolean needsShadow;
+ private boolean preferZOrder = true;
+ private boolean keepForegroundDrawable;
+ private Options options = Options.DEFAULT;
+
+ /**
+ * Set if needs overlay color.
+ * @param needsOverlay True if needs overlay.
+ * @return The Builder object itself.
+ */
+ public Builder needsOverlay(boolean needsOverlay) {
+ this.needsOverlay = needsOverlay;
+ return this;
+ }
+
+ /**
+ * Set if needs shadow.
+ * @param needsShadow True if needs shadow.
+ * @return The Builder object itself.
+ */
+ public Builder needsShadow(boolean needsShadow) {
+ this.needsShadow = needsShadow;
+ return this;
+ }
+
+ /**
+ * Set if needs rounded corner.
+ * @param needsRoundedCorner True if needs rounded corner.
+ * @return The Builder object itself.
+ */
+ public Builder needsRoundedCorner(boolean needsRoundedCorner) {
+ this.needsRoundedCorner = needsRoundedCorner;
+ return this;
+ }
+
+ /**
+ * Set if prefer z-order shadow. On old devices, z-order shadow might be slow,
+ * set to false to fall back to static 9-patch shadow. Recommend to read
+ * from system wide Setting value: see {@link Settings}.
+ *
+ * @param preferZOrder True if prefer Z shadow. Default is true.
+ * @return The Builder object itself.
+ */
+ public Builder preferZOrder(boolean preferZOrder) {
+ this.preferZOrder = preferZOrder;
+ return this;
+ }
+
+ /**
+ * Set if not using foreground drawable for overlay color. For example if
+ * the view has already assigned a foreground drawable for other purposes.
+ * When it's true, helper will use a ShadowOverlayContainer for overlay color.
+ *
+ * @param keepForegroundDrawable True to keep the original foreground drawable.
+ * @return The Builder object itself.
+ */
+ public Builder keepForegroundDrawable(boolean keepForegroundDrawable) {
+ this.keepForegroundDrawable = keepForegroundDrawable;
+ return this;
+ }
+
+ /**
+ * Set option values e.g. Shadow Z value, rounded corner radius.
+ *
+ * @param options The Options object to create ShadowOverlayHelper.
+ */
+ public Builder options(Options options) {
+ this.options = options;
+ return this;
+ }
+
+ /**
+ * Create ShadowOverlayHelper object
+ * @param context The context uses to read Resources settings.
+ * @return The ShadowOverlayHelper object.
+ */
+ public ShadowOverlayHelper build(Context context) {
+ final ShadowOverlayHelper helper = new ShadowOverlayHelper();
+ helper.mNeedsOverlay = needsOverlay;
+ helper.mNeedsRoundedCorner = needsRoundedCorner && supportsRoundedCorner();
+ helper.mNeedsShadow = needsShadow && supportsShadow();
+
+ if (helper.mNeedsRoundedCorner) {
+ helper.setupRoundedCornerRadius(options, context);
+ }
+
+ // figure out shadow type and if we need use wrapper:
+ if (helper.mNeedsShadow) {
+ // if static shadow is prefered or dynamic shadow is not supported,
+ // use static shadow, otherwise use dynamic shadow.
+ if (!preferZOrder || !supportsDynamicShadow()) {
+ helper.mShadowType = SHADOW_STATIC;
+ // static shadow requires ShadowOverlayContainer to support crossfading
+ // of two shadow views.
+ helper.mNeedsWrapper = true;
+ } else {
+ helper.mShadowType = SHADOW_DYNAMIC;
+ helper.setupDynamicShadowZ(options, context);
+ helper.mNeedsWrapper = ((!supportsForeground() || keepForegroundDrawable)
+ && helper.mNeedsOverlay);
+ }
+ } else {
+ helper.mShadowType = SHADOW_NONE;
+ helper.mNeedsWrapper = ((!supportsForeground() || keepForegroundDrawable)
+ && helper.mNeedsOverlay);
+ }
+
+ return helper;
+ }
+
+ }
+
+ /**
+ * Option values for ShadowOverlayContainer.
+ */
+ public static final class Options {
+
+ /**
+ * Default Options for values.
+ */
+ public static final Options DEFAULT = new Options();
+
+ private int roundedCornerRadius = 0; // 0 for default value
+ private float dynamicShadowUnfocusedZ = -1; // < 0 for default value
+ private float dynamicShadowFocusedZ = -1; // < 0 for default value
+ /**
+ * Set value of rounded corner radius.
+ *
+ * @param roundedCornerRadius Number of pixels of rounded corner radius.
+ * Set to 0 to use default settings.
+ * @return The Options object itself.
+ */
+ public Options roundedCornerRadius(int roundedCornerRadius){
+ this.roundedCornerRadius = roundedCornerRadius;
+ return this;
+ }
+
+ /**
+ * Set value of focused and unfocused Z value for shadow.
+ *
+ * @param unfocusedZ Number of pixels for unfocused Z value.
+ * @param focusedZ Number of pixels for foucsed Z value.
+ * @return The Options object itself.
+ */
+ public Options dynamicShadowZ(float unfocusedZ, float focusedZ){
+ this.dynamicShadowUnfocusedZ = unfocusedZ;
+ this.dynamicShadowFocusedZ = focusedZ;
+ return this;
+ }
+
+ /**
+ * Get radius of rounded corner in pixels.
+ *
+ * @return Radius of rounded corner in pixels.
+ */
+ public final int getRoundedCornerRadius() {
+ return roundedCornerRadius;
+ }
+
+ /**
+ * Get z value of shadow when a view is not focused.
+ *
+ * @return Z value of shadow when a view is not focused.
+ */
+ public final float getDynamicShadowUnfocusedZ() {
+ return dynamicShadowUnfocusedZ;
+ }
+
+ /**
+ * Get z value of shadow when a view is focused.
+ *
+ * @return Z value of shadow when a view is focused.
+ */
+ public final float getDynamicShadowFocusedZ() {
+ return dynamicShadowFocusedZ;
+ }
+ }
+
+ /**
+ * No shadow.
+ */
+ public static final int SHADOW_NONE = 1;
+
+ /**
+ * Shadows are fixed.
+ */
+ public static final int SHADOW_STATIC = 2;
+
+ /**
+ * Shadows depend on the size, shape, and position of the view.
+ */
+ public static final int SHADOW_DYNAMIC = 3;
+
+ int mShadowType = SHADOW_NONE;
+ boolean mNeedsOverlay;
+ boolean mNeedsRoundedCorner;
+ boolean mNeedsShadow;
+ boolean mNeedsWrapper;
+
+ int mRoundedCornerRadius;
+ float mUnfocusedZ;
+ float mFocusedZ;
+
+ /**
+ * Return true if the platform sdk supports shadow.
+ */
+ public static boolean supportsShadow() {
+ return StaticShadowHelper.getInstance().supportsShadow();
+ }
+
+ /**
+ * Returns true if the platform sdk supports dynamic shadows.
+ */
+ public static boolean supportsDynamicShadow() {
+ return ShadowHelper.getInstance().supportsDynamicShadow();
+ }
+
+ /**
+ * Returns true if the platform sdk supports rounded corner through outline.
+ */
+ public static boolean supportsRoundedCorner() {
+ return RoundedRectHelper.supportsRoundedCorner();
+ }
+
+ /**
+ * Returns true if view.setForeground() is supported.
+ */
+ public static boolean supportsForeground() {
+ return ForegroundHelper.supportsForeground();
+ }
+
+ /*
+ * hide from external, should be only created by ShadowOverlayHelper.Options.
+ */
+ ShadowOverlayHelper() {
+ }
+
+ /**
+ * {@link #prepareParentForShadow(ViewGroup)} must be called on parent of container
+ * before using shadow. Depending on Shadow type, optical bounds might be applied.
+ */
+ public void prepareParentForShadow(ViewGroup parent) {
+ if (mShadowType == SHADOW_STATIC) {
+ StaticShadowHelper.getInstance().prepareParent(parent);
+ }
+ }
+
+ public int getShadowType() {
+ return mShadowType;
+ }
+
+ public boolean needsOverlay() {
+ return mNeedsOverlay;
+ }
+
+ public boolean needsRoundedCorner() {
+ return mNeedsRoundedCorner;
+ }
+
+ /**
+ * Returns true if a "wrapper" ShadowOverlayContainer is needed.
+ * When needsWrapper() is true, call {@link #createShadowOverlayContainer(Context)}
+ * to create the wrapper.
+ */
+ public boolean needsWrapper() {
+ return mNeedsWrapper;
+ }
+
+ /**
+ * Create ShadowOverlayContainer for this helper.
+ * @param context Context to create view.
+ * @return ShadowOverlayContainer.
+ */
+ public ShadowOverlayContainer createShadowOverlayContainer(Context context) {
+ if (!needsWrapper()) {
+ throw new IllegalArgumentException();
+ }
+ return new ShadowOverlayContainer(context, mShadowType, mNeedsOverlay,
+ mUnfocusedZ, mFocusedZ, mRoundedCornerRadius);
+ }
+
+ /**
+ * Set overlay color for view other than ShadowOverlayContainer.
+ * See also {@link ShadowOverlayContainer#setOverlayColor(int)}.
+ */
+ public static void setNoneWrapperOverlayColor(View view, int color) {
+ Drawable d = ForegroundHelper.getInstance().getForeground(view);
+ if (d instanceof ColorDrawable) {
+ ((ColorDrawable) d).setColor(color);
+ } else {
+ ForegroundHelper.getInstance().setForeground(view, new ColorDrawable(color));
+ }
+ }
+
+ /**
+ * Set overlay color for view, it can be a ShadowOverlayContainer if needsWrapper() is true,
+ * or other view type.
+ */
+ public void setOverlayColor(View view, int color) {
+ if (needsWrapper()) {
+ ((ShadowOverlayContainer) view).setOverlayColor(color);
+ } else {
+ setNoneWrapperOverlayColor(view, color);
+ }
+ }
+
+ /**
+ * Must be called when view is created for cases {@link #needsWrapper()} is false.
+ * @param view
+ */
+ public void onViewCreated(View view) {
+ if (!needsWrapper()) {
+ if (!mNeedsShadow) {
+ if (mNeedsRoundedCorner) {
+ RoundedRectHelper.getInstance().setClipToRoundedOutline(view,
+ true, mRoundedCornerRadius);
+ }
+ } else {
+ if (mShadowType == SHADOW_DYNAMIC) {
+ Object tag = ShadowHelper.getInstance().addDynamicShadow(
+ view, mUnfocusedZ, mFocusedZ, mRoundedCornerRadius);
+ view.setTag(R.id.lb_shadow_impl, tag);
+ }
+ }
+ }
+ }
+
+ /**
+ * Set shadow focus level (0 to 1). 0 for unfocused, 1 for fully focused.
+ * This is for view other than ShadowOverlayContainer.
+ * See also {@link ShadowOverlayContainer#setShadowFocusLevel(float)}.
+ */
+ public static void setNoneWrapperShadowFocusLevel(View view, float level) {
+ setShadowFocusLevel(getNoneWrapperDyamicShadowImpl(view), SHADOW_DYNAMIC, level);
+ }
+
+ /**
+ * Set shadow focus level (0 to 1). 0 for unfocused, 1 for fully focused.
+ */
+ public void setShadowFocusLevel(View view, float level) {
+ if (needsWrapper()) {
+ ((ShadowOverlayContainer) view).setShadowFocusLevel(level);
+ } else {
+ setShadowFocusLevel(getNoneWrapperDyamicShadowImpl(view), SHADOW_DYNAMIC, level);
+ }
+ }
+
+ void setupDynamicShadowZ(Options options, Context context) {
+ if (options.getDynamicShadowUnfocusedZ() < 0f) {
+ Resources res = context.getResources();
+ mFocusedZ = res.getDimension(R.dimen.lb_material_shadow_focused_z);
+ mUnfocusedZ = res.getDimension(R.dimen.lb_material_shadow_normal_z);
+ } else {
+ mFocusedZ = options.getDynamicShadowFocusedZ();
+ mUnfocusedZ = options.getDynamicShadowUnfocusedZ();
+ }
+ }
+
+ void setupRoundedCornerRadius(Options options, Context context) {
+ if (options.getRoundedCornerRadius() == 0) {
+ Resources res = context.getResources();
+ mRoundedCornerRadius = res.getDimensionPixelSize(
+ R.dimen.lb_rounded_rect_corner_radius);
+ } else {
+ mRoundedCornerRadius = options.getRoundedCornerRadius();
+ }
+ }
+
+ static Object getNoneWrapperDyamicShadowImpl(View view) {
+ return view.getTag(R.id.lb_shadow_impl);
+ }
+
+ static void setShadowFocusLevel(Object impl, int shadowType, float level) {
+ if (impl != null) {
+ if (level < 0f) {
+ level = 0f;
+ } else if (level > 1f) {
+ level = 1f;
+ }
+ switch (shadowType) {
+ case SHADOW_DYNAMIC:
+ ShadowHelper.getInstance().setShadowFocusLevel(impl, level);
+ break;
+ case SHADOW_STATIC:
+ StaticShadowHelper.getInstance().setShadowFocusLevel(impl, level);
+ break;
+ }
+ }
+ }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java
index 4d8411b3aa..022ff1de30 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java
@@ -34,7 +34,7 @@ final class StaticShadowHelper {
*/
static interface ShadowHelperVersionImpl {
public void prepareParent(ViewGroup parent);
- public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners);
+ public Object addStaticShadow(ViewGroup shadowContainer);
public void setShadowFocusLevel(Object impl, float level);
}
@@ -48,7 +48,7 @@ final class StaticShadowHelper {
}
@Override
- public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners) {
+ public Object addStaticShadow(ViewGroup shadowContainer) {
// do nothing
return null;
}
@@ -69,8 +69,7 @@ final class StaticShadowHelper {
}
@Override
- public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners) {
- // Static shadows are always rounded
+ public Object addStaticShadow(ViewGroup shadowContainer) {
return ShadowHelperJbmr2.addShadow(shadowContainer);
}
@@ -105,8 +104,8 @@ final class StaticShadowHelper {
mImpl.prepareParent(parent);
}
- public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners) {
- return mImpl.addStaticShadow(shadowContainer, roundedCorners);
+ public Object addStaticShadow(ViewGroup shadowContainer) {
+ return mImpl.addStaticShadow(shadowContainer);
}
public void setShadowFocusLevel(Object impl, float level) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/TitleHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/TitleHelper.java
index c61087b0d3..9282bb1f87 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/TitleHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/TitleHelper.java
@@ -36,8 +36,6 @@ public class TitleHelper {
private Object mSceneWithTitle;
private Object mSceneWithoutTitle;
- static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
-
// When moving focus off the TitleView, this focus search listener assumes that the view that
// should take focus comes before the TitleView in a focus search starting at the scene root.
private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =
@@ -68,16 +66,16 @@ public class TitleHelper {
private void createTransitions() {
mTitleUpTransition = LeanbackTransitionHelper.loadTitleOutTransition(
- mSceneRoot.getContext(), sTransitionHelper);
+ mSceneRoot.getContext());
mTitleDownTransition = LeanbackTransitionHelper.loadTitleInTransition(
- mSceneRoot.getContext(), sTransitionHelper);
- mSceneWithTitle = sTransitionHelper.createScene(mSceneRoot, new Runnable() {
+ mSceneRoot.getContext());
+ mSceneWithTitle = TransitionHelper.createScene(mSceneRoot, new Runnable() {
@Override
public void run() {
mTitleView.setVisibility(View.VISIBLE);
}
});
- mSceneWithoutTitle = sTransitionHelper.createScene(mSceneRoot, new Runnable() {
+ mSceneWithoutTitle = TransitionHelper.createScene(mSceneRoot, new Runnable() {
@Override
public void run() {
mTitleView.setVisibility(View.INVISIBLE);
@@ -90,9 +88,9 @@ public class TitleHelper {
*/
public void showTitle(boolean show) {
if (show) {
- sTransitionHelper.runTransition(mSceneWithTitle, mTitleDownTransition);
+ TransitionHelper.runTransition(mSceneWithTitle, mTitleDownTransition);
} else {
- sTransitionHelper.runTransition(mSceneWithoutTitle, mTitleUpTransition);
+ TransitionHelper.runTransition(mSceneWithoutTitle, mTitleUpTransition);
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
index 16b66cde35..7af5ea0cf7 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
@@ -16,6 +16,7 @@ package android.support.v17.leanback.widget;
import android.content.Context;
import android.support.v17.leanback.R;
import android.support.v17.leanback.system.Settings;
+import android.support.v17.leanback.transition.TransitionHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -31,6 +32,17 @@ public class VerticalGridPresenter extends Presenter {
class VerticalGridItemBridgeAdapter extends ItemBridgeAdapter {
@Override
+ protected void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
+ if (viewHolder.itemView instanceof ViewGroup) {
+ TransitionHelper.setTransitionGroup((ViewGroup) viewHolder.itemView,
+ true);
+ }
+ if (mShadowOverlayHelper != null) {
+ mShadowOverlayHelper.onViewCreated(viewHolder.itemView);
+ }
+ }
+
+ @Override
public void onBind(final ItemBridgeAdapter.ViewHolder itemViewHolder) {
// Only when having an OnItemClickListner, we attach the OnClickListener.
if (getOnItemViewClickedListener() != null) {
@@ -83,9 +95,12 @@ public class VerticalGridPresenter extends Presenter {
private int mFocusZoomFactor;
private boolean mUseFocusDimmer;
private boolean mShadowEnabled = true;
+ private boolean mKeepChildForeground = true;
private OnItemViewSelectedListener mOnItemViewSelectedListener;
private OnItemViewClickedListener mOnItemViewClickedListener;
private boolean mRoundedCornersEnabled = true;
+ private ShadowOverlayHelper mShadowOverlayHelper;
+ private ItemBridgeAdapter.Wrapper mShadowOverlayWrapper;
/**
* Constructs a VerticalGridPresenter with defaults.
@@ -170,7 +185,7 @@ public class VerticalGridPresenter extends Presenter {
* Subclass may return false to disable.
*/
public boolean isUsingDefaultShadow() {
- return ShadowOverlayContainer.supportsShadow();
+ return ShadowOverlayHelper.supportsShadow();
}
/**
@@ -194,8 +209,7 @@ public class VerticalGridPresenter extends Presenter {
* and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false.
*/
public boolean isUsingZOrder(Context context) {
- return ShadowOverlayContainer.supportsDynamicShadow() &&
- !Settings.getInstance(context).preferStaticShadows();
+ return !Settings.getInstance(context).preferStaticShadows();
}
final boolean needsDefaultShadow() {
@@ -216,7 +230,6 @@ public class VerticalGridPresenter extends Presenter {
return mUseFocusDimmer;
}
-
@Override
public final ViewHolder onCreateViewHolder(ViewGroup parent) {
ViewHolder vh = createGridViewHolder(parent);
@@ -238,21 +251,6 @@ public class VerticalGridPresenter extends Presenter {
return new ViewHolder((VerticalGridView) root.findViewById(R.id.browse_grid));
}
- private ItemBridgeAdapter.Wrapper mWrapper = new ItemBridgeAdapter.Wrapper() {
- @Override
- public View createWrapper(View root) {
- ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
- wrapper.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- wrapper.initialize(needsDefaultShadow(), true, areChildRoundedCornersEnabled());
- return wrapper;
- }
- @Override
- public void wrap(View wrapper, View wrapped) {
- ((ShadowOverlayContainer) wrapper).wrap(wrapped);
- }
- };
-
/**
* Called after a {@link VerticalGridPresenter.ViewHolder} is created.
* Subclasses may override this method and start by calling
@@ -268,12 +266,25 @@ public class VerticalGridPresenter extends Presenter {
vh.getGridView().setNumColumns(mNumColumns);
vh.mInitialized = true;
- vh.mItemBridgeAdapter.setWrapper(mWrapper);
- if (needsDefaultShadow() || areChildRoundedCornersEnabled()) {
- ShadowOverlayContainer.prepareParentForShadow(vh.getGridView());
- ((ViewGroup) vh.view).setClipChildren(false);
+ Context context = vh.mGridView.getContext();
+ if (mShadowOverlayHelper == null) {
+ mShadowOverlayHelper = new ShadowOverlayHelper.Builder()
+ .needsOverlay(mUseFocusDimmer)
+ .needsShadow(needsDefaultShadow())
+ .needsRoundedCorner(areChildRoundedCornersEnabled())
+ .preferZOrder(isUsingZOrder(context))
+ .keepForegroundDrawable(mKeepChildForeground)
+ .options(createShadowOverlayOptions())
+ .build(context);
+ if (mShadowOverlayHelper.needsWrapper()) {
+ mShadowOverlayWrapper = new ItemBridgeAdapterShadowOverlayWrapper(
+ mShadowOverlayHelper);
+ }
}
- vh.getGridView().setFocusDrawingOrderEnabled(!isUsingZOrder(vh.getGridView().getContext()));
+ vh.mItemBridgeAdapter.setWrapper(mShadowOverlayWrapper);
+ mShadowOverlayHelper.prepareParentForShadow(vh.mGridView);
+ vh.getGridView().setFocusDrawingOrderEnabled(mShadowOverlayHelper.getShadowType()
+ == ShadowOverlayHelper.SHADOW_STATIC);
FocusHighlightHelper.setupBrowseItemFocusHighlight(vh.mItemBridgeAdapter,
mFocusZoomFactor, mUseFocusDimmer);
@@ -286,6 +297,39 @@ public class VerticalGridPresenter extends Presenter {
});
}
+ /**
+ * Set if keeps foreground of child of this grid, the foreground will not
+ * be used for overlay color. Default value is true.
+ *
+ * @param keep True if keep foreground of child of this grid.
+ */
+ public final void setKeepChildForeground(boolean keep) {
+ mKeepChildForeground = keep;
+ }
+
+ /**
+ * Returns true if keeps foreground of child of this grid, the foreground will not
+ * be used for overlay color. Default value is true.
+ *
+ * @return True if keeps foreground of child of this grid.
+ */
+ public final boolean getKeepChildForeground() {
+ return mKeepChildForeground;
+ }
+
+ /**
+ * Create ShadowOverlayHelper Options. Subclass may override.
+ * e.g.
+ * <code>
+ * return new ShadowOverlayHelper.Options().roundedCornerRadius(10);
+ * </code>
+ *
+ * @return The options to be used for shadow, overlay and rouded corner.
+ */
+ protected ShadowOverlayHelper.Options createShadowOverlayOptions() {
+ return ShadowOverlayHelper.Options.DEFAULT;
+ }
+
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
if (DEBUG) Log.v(TAG, "onBindViewHolder " + item);
@@ -345,4 +389,18 @@ public class VerticalGridPresenter extends Presenter {
}
}
}
+
+ /**
+ * Changes the visibility of views. The entrance transition will be run against the views that
+ * change visibilities. This method is called by the fragment, it should not be called
+ * directly by the application.
+ *
+ * @param holder The ViewHolder for the vertical grid.
+ * @param afterEntrance true if children of vertical grid participating in entrance transition
+ * should be set to visible, false otherwise.
+ */
+ public void setEntranceTransitionState(VerticalGridPresenter.ViewHolder holder,
+ boolean afterEntrance) {
+ holder.mGridView.setChildrenVisibility(afterEntrance? View.VISIBLE : View.INVISIBLE);
+ }
}
diff --git a/v17/preference-leanback/Android.mk b/v17/preference-leanback/Android.mk
index c3bc8037f5..14be7eb93b 100644
--- a/v17/preference-leanback/Android.mk
+++ b/v17/preference-leanback/Android.mk
@@ -34,6 +34,8 @@ LOCAL_AAPT_FLAGS := \
LOCAL_JAR_EXCLUDE_FILES := none
include $(BUILD_STATIC_JAVA_LIBRARY)
+support_module_src_files := $(LOCAL_SRC_FILES)
+
# -----------------------------------------------------------------------
# A helper sub-library that makes direct use of API 21.
@@ -41,9 +43,12 @@ include $(CLEAR_VARS)
LOCAL_MODULE := android-support-v17-preference-leanback-api21
LOCAL_SDK_VERSION := 21
LOCAL_SRC_FILES := $(call all-java-files-under, api21)
-LOCAL_JAVA_LIBRARIES := android-support-v17-preference-leanback-res
+LOCAL_JAVA_LIBRARIES := android-support-v17-preference-leanback-res \
+ android-support-v17-leanback
include $(BUILD_STATIC_JAVA_LIBRARY)
+support_module_src_files += $(LOCAL_SRC_FILES)
+
# Here is the final static library that apps can link against.
# The R class is automatically excluded from the generated library.
# Applications that use this library must specify LOCAL_RESOURCE_DIR
@@ -65,11 +70,12 @@ LOCAL_JAVA_LIBRARIES := \
android-support-v17-preference-leanback-res
include $(BUILD_STATIC_JAVA_LIBRARY)
+support_module_src_files += $(LOCAL_SRC_FILES)
+
# API Check
# ---------------------------------------------
support_module := $(LOCAL_MODULE)
support_module_api_dir := $(LOCAL_PATH)/api
-support_module_src_files := $(LOCAL_SRC_FILES)
support_module_java_libraries := $(LOCAL_JAVA_LIBRARIES)
support_module_java_packages := android.support.v17.preference
include $(SUPPORT_API_CHECK)
diff --git a/v17/preference-leanback/api/23.txt b/v17/preference-leanback/api/23.0.0.txt
index 06316abcff..06316abcff 100644
--- a/v17/preference-leanback/api/23.txt
+++ b/v17/preference-leanback/api/23.0.0.txt
diff --git a/v17/preference-leanback/api/23.1.0.txt b/v17/preference-leanback/api/23.1.0.txt
new file mode 100644
index 0000000000..06316abcff
--- /dev/null
+++ b/v17/preference-leanback/api/23.1.0.txt
@@ -0,0 +1,61 @@
+package android.support.v17.preference {
+
+ public abstract class BaseLeanbackPreferenceFragment extends android.support.v14.preference.PreferenceFragment {
+ ctor public BaseLeanbackPreferenceFragment();
+ }
+
+ public class LeanbackListPreferenceDialogFragment extends android.support.v17.preference.LeanbackPreferenceDialogFragment {
+ ctor public LeanbackListPreferenceDialogFragment();
+ method public static android.support.v17.preference.LeanbackListPreferenceDialogFragment newInstanceMulti(java.lang.String);
+ method public static android.support.v17.preference.LeanbackListPreferenceDialogFragment newInstanceSingle(java.lang.String);
+ method public android.support.v7.widget.RecyclerView.Adapter onCreateAdapter();
+ }
+
+ public class LeanbackListPreferenceDialogFragment.AdapterMulti extends android.support.v7.widget.RecyclerView.Adapter implements android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder.OnItemClickListener {
+ ctor public LeanbackListPreferenceDialogFragment.AdapterMulti(java.lang.CharSequence[], java.lang.CharSequence[], java.util.Set<java.lang.String>);
+ method public int getItemCount();
+ method public void onBindViewHolder(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder, int);
+ method public android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder onCreateViewHolder(android.view.ViewGroup, int);
+ method public void onItemClick(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder);
+ }
+
+ public class LeanbackListPreferenceDialogFragment.AdapterSingle extends android.support.v7.widget.RecyclerView.Adapter implements android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder.OnItemClickListener {
+ ctor public LeanbackListPreferenceDialogFragment.AdapterSingle(java.lang.CharSequence[], java.lang.CharSequence[], java.lang.CharSequence);
+ method public int getItemCount();
+ method public void onBindViewHolder(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder, int);
+ method public android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder onCreateViewHolder(android.view.ViewGroup, int);
+ method public void onItemClick(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder);
+ }
+
+ public static class LeanbackListPreferenceDialogFragment.ViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder implements android.view.View.OnClickListener {
+ ctor public LeanbackListPreferenceDialogFragment.ViewHolder(android.view.View, android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder.OnItemClickListener);
+ method public android.view.ViewGroup getContainer();
+ method public android.widget.TextView getTitleView();
+ method public android.widget.Checkable getWidgetView();
+ method public void onClick(android.view.View);
+ }
+
+ public static abstract interface LeanbackListPreferenceDialogFragment.ViewHolder.OnItemClickListener {
+ method public abstract void onItemClick(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder);
+ }
+
+ public class LeanbackPreferenceDialogFragment extends android.app.Fragment {
+ ctor public LeanbackPreferenceDialogFragment();
+ method public android.support.v7.preference.DialogPreference getPreference();
+ field public static final java.lang.String ARG_KEY = "key";
+ }
+
+ public abstract class LeanbackPreferenceFragment extends android.support.v17.preference.BaseLeanbackPreferenceFragment {
+ ctor public LeanbackPreferenceFragment();
+ }
+
+ public abstract class LeanbackSettingsFragment extends android.app.Fragment {
+ ctor public LeanbackSettingsFragment();
+ method public boolean onPreferenceDisplayDialog(android.support.v14.preference.PreferenceFragment, android.support.v7.preference.Preference);
+ method public abstract void onPreferenceStartInitialScreen();
+ method public void startImmersiveFragment(android.app.Fragment);
+ method public void startPreferenceFragment(android.app.Fragment);
+ }
+
+}
+
diff --git a/v17/preference-leanback/api21/android/support/v17/preference/LeanbackPreferenceFragmentTransitionHelperApi21.java b/v17/preference-leanback/api21/android/support/v17/preference/LeanbackPreferenceFragmentTransitionHelperApi21.java
index 2002a54b9a..37e7a7976e 100644
--- a/v17/preference-leanback/api21/android/support/v17/preference/LeanbackPreferenceFragmentTransitionHelperApi21.java
+++ b/v17/preference-leanback/api21/android/support/v17/preference/LeanbackPreferenceFragmentTransitionHelperApi21.java
@@ -16,21 +16,10 @@
package android.support.v17.preference;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.TimeInterpolator;
+import android.support.v17.leanback.transition.FadeAndShortSlide;
import android.app.Fragment;
-import android.graphics.Path;
-import android.transition.Fade;
import android.transition.Transition;
-import android.transition.TransitionValues;
-import android.transition.Visibility;
import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.DecelerateInterpolator;
/**
* @hide
@@ -38,8 +27,8 @@ import android.view.animation.DecelerateInterpolator;
public class LeanbackPreferenceFragmentTransitionHelperApi21 {
public static void addTransitions(Fragment f) {
- final Transition transitionStartEdge = new FadeAndShortSlideTransition(Gravity.START);
- final Transition transitionEndEdge = new FadeAndShortSlideTransition(Gravity.END);
+ final Transition transitionStartEdge = new FadeAndShortSlide(Gravity.START);
+ final Transition transitionEndEdge = new FadeAndShortSlide(Gravity.END);
f.setEnterTransition(transitionEndEdge);
f.setExitTransition(transitionStartEdge);
@@ -47,273 +36,5 @@ public class LeanbackPreferenceFragmentTransitionHelperApi21 {
f.setReturnTransition(transitionEndEdge);
}
- private static class FadeAndShortSlideTransition extends Visibility {
-
- private static final TimeInterpolator sDecelerate = new DecelerateInterpolator();
-// private static final TimeInterpolator sAccelerate = new AccelerateInterpolator();
- private static final String PROPNAME_SCREEN_POSITION =
- "android:fadeAndShortSlideTransition:screenPosition";
-
- private CalculateSlide mSlideCalculator = sCalculateEnd;
- private Visibility mFade = new Fade();
-
- private interface CalculateSlide {
-
- /** Returns the translation value for view when it goes out of the scene */
- float getGoneX(ViewGroup sceneRoot, View view);
- }
-
- private static final CalculateSlide sCalculateStart = new CalculateSlide() {
- @Override
- public float getGoneX(ViewGroup sceneRoot, View view) {
- final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
- final float x;
- if (isRtl) {
- x = view.getTranslationX() + sceneRoot.getWidth() / 4;
- } else {
- x = view.getTranslationX() - sceneRoot.getWidth() / 4;
- }
- return x;
- }
- };
-
- private static final CalculateSlide sCalculateEnd = new CalculateSlide() {
- @Override
- public float getGoneX(ViewGroup sceneRoot, View view) {
- final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
- final float x;
- if (isRtl) {
- x = view.getTranslationX() - sceneRoot.getWidth() / 4;
- } else {
- x = view.getTranslationX() + sceneRoot.getWidth() / 4;
- }
- return x;
- }
- };
-
- public FadeAndShortSlideTransition(int slideEdge) {
- setSlideEdge(slideEdge);
- }
-
- @Override
- public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
- super.setEpicenterCallback(epicenterCallback);
- mFade.setEpicenterCallback(epicenterCallback);
- }
-
- private void captureValues(TransitionValues transitionValues) {
- View view = transitionValues.view;
- int[] position = new int[2];
- view.getLocationOnScreen(position);
- transitionValues.values.put(PROPNAME_SCREEN_POSITION, position[0]);
- }
-
- @Override
- public void captureStartValues(TransitionValues transitionValues) {
- super.captureStartValues(transitionValues);
- mFade.captureStartValues(transitionValues);
- captureValues(transitionValues);
- }
-
- @Override
- public void captureEndValues(TransitionValues transitionValues) {
- super.captureEndValues(transitionValues);
- mFade.captureEndValues(transitionValues);
- captureValues(transitionValues);
- }
-
- public void setSlideEdge(int slideEdge) {
- switch (slideEdge) {
- case Gravity.START:
- mSlideCalculator = sCalculateStart;
- break;
- case Gravity.END:
- mSlideCalculator = sCalculateEnd;
- break;
- default:
- throw new IllegalArgumentException("Invalid slide direction");
- }
-// SidePropagation propagation = new SidePropagation();
-// propagation.setSide(slideEdge);
-// setPropagation(propagation);
- }
-
- @Override
- public Animator onAppear(ViewGroup sceneRoot, View view,
- TransitionValues startValues, TransitionValues endValues) {
- if (endValues == null) {
- return null;
- }
- Integer position = (Integer) endValues.values.get(PROPNAME_SCREEN_POSITION);
- float endX = view.getTranslationX();
- float startX = mSlideCalculator.getGoneX(sceneRoot, view);
- final Animator slideAnimator = TranslationAnimationCreator
- .createAnimation(view, endValues, position,
- startX, endX, sDecelerate, this);
- final AnimatorSet set = new AnimatorSet();
- set.play(slideAnimator)
- .with(mFade.onAppear(sceneRoot, view, startValues, endValues));
-
- return set;
- }
-
- @Override
- public Animator onDisappear(ViewGroup sceneRoot, View view,
- TransitionValues startValues, TransitionValues endValues) {
- if (startValues == null) {
- return null;
- }
- Integer position = (Integer) startValues.values.get(PROPNAME_SCREEN_POSITION);
- float startX = view.getTranslationX();
- float endX = mSlideCalculator.getGoneX(sceneRoot, view);
- final Animator slideAnimator = TranslationAnimationCreator
- .createAnimation(view, startValues, position,
- startX, endX, sDecelerate /*sAccelerate*/, this);
- final AnimatorSet set = new AnimatorSet();
- set.play(slideAnimator)
- .with(mFade.onDisappear(sceneRoot, view, startValues, endValues));
-
- return set;
- }
-
- @Override
- public Transition addListener(TransitionListener listener) {
- mFade.addListener(listener);
- return super.addListener(listener);
- }
-
- @Override
- public Transition removeListener(TransitionListener listener) {
- mFade.removeListener(listener);
- return super.removeListener(listener);
- }
-
- @Override
- public Transition clone() {
- FadeAndShortSlideTransition clone = null;
- clone = (FadeAndShortSlideTransition) super.clone();
- clone.mFade = (Visibility) mFade.clone();
- return clone;
- }
- }
-
- /**
- * This class is used by Slide and Explode to create an animator that goes from the start
- * position to the end position. It takes into account the canceled position so that it
- * will not blink out or shift suddenly when the transition is interrupted.
- */
- private static class TranslationAnimationCreator {
-
- /**
- * Creates an animator that can be used for x and/or y translations. When interrupted,
- * it sets a tag to keep track of the position so that it may be continued from position.
- *
- * @param view The view being moved. This may be in the overlay for onDisappear.
- * @param values The values containing the view in the view hierarchy.
- * @param viewPosX The x screen coordinate of view
- * @param startX The start translation x of view
- * @param endX The end translation x of view
- * @param interpolator The interpolator to use with this animator.
- * @return An animator that moves from (startX, startY) to (endX, endY) unless there was
- * a previous interruption, in which case it moves from the current position to
- * (endX, endY).
- */
- static Animator createAnimation(View view, TransitionValues values, int viewPosX,
- float startX, float endX, TimeInterpolator interpolator,
- Transition transition) {
- float terminalX = view.getTranslationX();
- Integer startPosition = (Integer) values.view.getTag(R.id.transitionPosition);
- if (startPosition != null) {
- startX = startPosition - viewPosX + terminalX;
- }
- // Initial position is at translation startX, startY, so position is offset by that
- // amount
- int startPosX = viewPosX + Math.round(startX - terminalX);
-
- view.setTranslationX(startX);
- if (startX == endX) {
- return null;
- }
- Path path = new Path();
- path.moveTo(startX, 0);
- path.lineTo(endX, 0);
- ObjectAnimator anim =
- ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y, path);
-
- TransitionPositionListener listener = new TransitionPositionListener(view, values.view,
- startPosX, terminalX);
- transition.addListener(listener);
- anim.addListener(listener);
- anim.addPauseListener(listener);
- anim.setInterpolator(interpolator);
- return anim;
- }
-
- private static class TransitionPositionListener extends AnimatorListenerAdapter implements
- Transition.TransitionListener {
-
- private final View mViewInHierarchy;
- private final View mMovingView;
- private final int mStartX;
- private Integer mTransitionPosition;
- private float mPausedX;
- private final float mTerminalX;
-
- private TransitionPositionListener(View movingView, View viewInHierarchy,
- int startX, float terminalX) {
- mMovingView = movingView;
- mViewInHierarchy = viewInHierarchy;
- mStartX = startX - Math.round(mMovingView.getTranslationX());
- mTerminalX = terminalX;
- mTransitionPosition = (Integer) mViewInHierarchy.getTag(R.id.transitionPosition);
- if (mTransitionPosition != null) {
- mViewInHierarchy.setTag(R.id.transitionPosition, null);
- }
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mTransitionPosition = Math.round(mStartX + mMovingView.getTranslationX());
- mViewInHierarchy.setTag(R.id.transitionPosition, mTransitionPosition);
- }
-
- @Override
- public void onAnimationEnd(Animator animator) {
- }
-
- @Override
- public void onAnimationPause(Animator animator) {
- mPausedX = mMovingView.getTranslationX();
- mMovingView.setTranslationX(mTerminalX);
- }
-
- @Override
- public void onAnimationResume(Animator animator) {
- mMovingView.setTranslationX(mPausedX);
- }
-
- @Override
- public void onTransitionStart(Transition transition) {
- }
-
- @Override
- public void onTransitionEnd(Transition transition) {
- mMovingView.setTranslationX(mTerminalX);
- }
-
- @Override
- public void onTransitionCancel(Transition transition) {
- }
-
- @Override
- public void onTransitionPause(Transition transition) {
- }
-
- @Override
- public void onTransitionResume(Transition transition) {
- }
- }
-
- }
}
diff --git a/v17/preference-leanback/build.gradle b/v17/preference-leanback/build.gradle
index 4063122edd..0ddcdd2dc8 100644
--- a/v17/preference-leanback/build.gradle
+++ b/v17/preference-leanback/build.gradle
@@ -56,3 +56,37 @@ android {
abortOnError false
}
}
+
+uploadArchives {
+ repositories {
+ mavenDeployer {
+ repository(url: uri(rootProject.ext.supportRepoOut)) {
+ }
+
+ pom.project {
+ name 'Android Support Leanback Preference v17'
+ description "Android Support Leanback Preference v17"
+ url 'http://developer.android.com/tools/extras/support-library.html'
+ inceptionYear '2015'
+
+ licenses {
+ license {
+ name 'The Apache Software License, Version 2.0'
+ url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+ distribution 'repo'
+ }
+ }
+
+ scm {
+ url "http://source.android.com"
+ connection "scm:git:https://android.googlesource.com/platform/frameworks/support"
+ }
+ developers {
+ developer {
+ name 'The Android Open Source Project'
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/v17/preference-leanback/res/values/ids.xml b/v17/preference-leanback/res/color/lb_preference_item_primary_text_color.xml
index 20c1edaa00..efdf1c0976 100644
--- a/v17/preference-leanback/res/values/ids.xml
+++ b/v17/preference-leanback/res/color/lb_preference_item_primary_text_color.xml
@@ -15,6 +15,7 @@
~ limitations under the License
-->
-<resources>
- <item name="transitionPosition" type="id" />
-</resources>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@color/lb_preference_item_primary_text_color_disabled" />
+ <item android:color="@color/lb_preference_item_primary_text_color_default"/>
+</selector>
diff --git a/v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml b/v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml
new file mode 100644
index 0000000000..68bb81aef5
--- /dev/null
+++ b/v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@color/lb_preference_item_secondary_text_color_disabled" />
+ <item android:color="@color/lb_preference_item_secondary_text_color_default"/>
+</selector>
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml b/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
index 9fae0f888c..f073f3e463 100644
--- a/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
@@ -20,6 +20,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/lb_preference_decor_list_background"
+ android:elevation="@dimen/lb_preference_decor_elevation"
android:orientation="vertical"
android:transitionGroup="false"
>
@@ -29,17 +30,18 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/defaultBrandColor"
+ android:elevation="@dimen/lb_preference_decor_title_container_elevation"
android:transitionGroup="false"
>
<TextView
android:id="@+id/decor_title"
android:layout_width="match_parent"
android:layout_height="@dimen/lb_preference_decor_title_text_height"
+ android:layout_marginTop="@dimen/lb_preference_decor_title_margin_top"
+ android:layout_marginStart="@dimen/lb_preference_decor_title_margin_start"
+ android:layout_marginEnd="@dimen/lb_preference_decor_title_margin_end"
android:fontFamily="sans-serif-condensed"
android:gravity="center_vertical"
- android:paddingTop="@dimen/lb_preference_decor_title_padding_top"
- android:paddingStart="@dimen/lb_preference_decor_title_padding_start"
- android:paddingEnd="@dimen/lb_preference_decor_title_padding_end"
android:singleLine="true"
android:textSize="@dimen/lb_preference_decor_title_text_size"
android:textColor="?android:attr/textColorPrimary"
@@ -50,6 +52,7 @@
android:id="@android:id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:fontFamily="sans-serif-condensed"
android:paddingTop="14dp"
android:paddingBottom="14dp"
android:paddingStart="24dp"
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml b/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
index 3b1345cbd5..728ecff6d7 100644
--- a/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
@@ -18,20 +18,35 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:descendantFocusability="blocksDescendants"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
<CheckBox
android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@android:id/title"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center_vertical" />
+ android:layout_width="@dimen/lb_preference_item_icon_size"
+ android:layout_height="@dimen/lb_preference_item_icon_size"
+ android:layout_marginEnd="@dimen/lb_preference_item_icon_margin_end"
+ android:layout_gravity="center_vertical" />
+
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+ android:fontFamily="sans-serif-condensed"
+ android:textColor="@color/lb_preference_item_primary_text_color"
+ android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+ </LinearLayout>
+
</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml b/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
index eaf42a4fa8..354ca41abd 100644
--- a/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
@@ -18,20 +18,35 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:descendantFocusability="blocksDescendants"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
<RadioButton
android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@android:id/title"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center_vertical" />
+ android:layout_width="@dimen/lb_preference_item_icon_size"
+ android:layout_height="@dimen/lb_preference_item_icon_size"
+ android:layout_marginEnd="@dimen/lb_preference_item_icon_margin_end"
+ android:layout_gravity="center_vertical" />
+
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+ android:fontFamily="sans-serif-condensed"
+ android:textColor="@color/lb_preference_item_primary_text_color"
+ android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+ </LinearLayout>
+
</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference.xml b/v17/preference-leanback/res/layout/leanback_preference.xml
new file mode 100644
index 0000000000..05ca21c14e
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground"
+ android:clickable="true"
+ android:focusable="true"
+ android:descendantFocusability="blocksDescendants"
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
+ <FrameLayout
+ android:id="@+id/icon_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical" >
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@dimen/lb_preference_item_icon_size"
+ android:layout_height="@dimen/lb_preference_item_icon_size"
+ android:layout_marginEnd="@dimen/lb_preference_item_icon_margin_end"
+ />
+ </FrameLayout>
+
+ <LinearLayout android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+ android:fontFamily="sans-serif-condensed"
+ android:textColor="@color/lb_preference_item_primary_text_color"
+ android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:fontFamily="sans-serif-condensed"
+ android:textColor="@color/lb_preference_item_secondary_text_color"
+ android:textSize="@dimen/lb_preference_item_secondary_text_size"
+ android:maxLines="4" />
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+ </LinearLayout>
+
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout android:id="@android:id/widget_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference_category.xml b/v17/preference-leanback/res/layout/leanback_preference_category.xml
new file mode 100644
index 0000000000..9b978f3616
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference_category.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/lb_preference_category_height"
+ android:clipToPadding="false"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end">
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:fontFamily="sans-serif-condensed"
+ android:textColor="?android:attr/colorAccent"
+ android:textSize="@dimen/lb_preference_category_text_size"/>
+</FrameLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference_fragment.xml b/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
index d119c2dfa0..199e0f71de 100644
--- a/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
+++ b/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
@@ -20,6 +20,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/lb_preference_decor_list_background"
+ android:elevation="@dimen/lb_preference_decor_elevation"
android:orientation="vertical"
android:transitionGroup="false"
>
@@ -29,17 +30,18 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/defaultBrandColor"
+ android:elevation="@dimen/lb_preference_decor_title_container_elevation"
android:transitionGroup="false"
>
<TextView
android:id="@+id/decor_title"
android:layout_width="match_parent"
android:layout_height="@dimen/lb_preference_decor_title_text_height"
+ android:layout_marginTop="@dimen/lb_preference_decor_title_margin_top"
+ android:layout_marginStart="@dimen/lb_preference_decor_title_margin_start"
+ android:layout_marginEnd="@dimen/lb_preference_decor_title_margin_end"
android:fontFamily="sans-serif-condensed"
android:gravity="center_vertical"
- android:paddingTop="@dimen/lb_preference_decor_title_padding_top"
- android:paddingStart="@dimen/lb_preference_decor_title_padding_start"
- android:paddingEnd="@dimen/lb_preference_decor_title_padding_end"
android:singleLine="true"
android:textSize="@dimen/lb_preference_decor_title_text_size"
android:textColor="?android:attr/textColorPrimary"
diff --git a/v17/preference-leanback/res/layout/leanback_preference_information.xml b/v17/preference-leanback/res/layout/leanback_preference_information.xml
new file mode 100644
index 0000000000..18da8d9bfa
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference_information.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground"
+ android:clickable="false"
+ android:focusable="false"
+ android:descendantFocusability="blocksDescendants"
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
+ <LinearLayout android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+ android:fontFamily="sans-serif-condensed"
+ android:textColor="@color/lb_preference_item_primary_text_color"
+ android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:fontFamily="sans-serif-condensed"
+ android:textColor="@color/lb_preference_item_secondary_text_color"
+ android:textSize="@dimen/lb_preference_item_secondary_text_size"
+ android:maxLines="4" />
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+ </LinearLayout>
+
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout android:id="@android:id/widget_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preferences_list.xml b/v17/preference-leanback/res/layout/leanback_preferences_list.xml
index 15ecebc293..21e4e4a5b2 100644
--- a/v17/preference-leanback/res/layout/leanback_preferences_list.xml
+++ b/v17/preference-leanback/res/layout/leanback_preferences_list.xml
@@ -19,4 +19,5 @@
android:id="@+id/list"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent"
+ style="?attr/preferenceFragmentListStyle" />
diff --git a/v17/preference-leanback/res/values/colors.xml b/v17/preference-leanback/res/values/colors.xml
index de6c888463..30a373af5d 100644
--- a/v17/preference-leanback/res/values/colors.xml
+++ b/v17/preference-leanback/res/values/colors.xml
@@ -16,4 +16,11 @@
-->
<resources>
<color name="lb_preference_decor_list_background">#263238</color>
+
+ <color name="lb_preference_item_primary_text_color_default">#EEEEEE</color>
+ <color name="lb_preference_item_primary_text_color_disabled">#4DEEEEEE</color>
+
+ <color name="lb_preference_item_secondary_text_color_default">#B3EEEEEE</color>
+ <color name="lb_preference_item_secondary_text_color_disabled">#4DEEEEEE</color>
+
</resources>
diff --git a/v17/preference-leanback/res/values/dimens.xml b/v17/preference-leanback/res/values/dimens.xml
index 49763fe4fa..f3d36af530 100644
--- a/v17/preference-leanback/res/values/dimens.xml
+++ b/v17/preference-leanback/res/values/dimens.xml
@@ -15,11 +15,27 @@
~ limitations under the License
-->
<resources>
- <dimen name="lb_preference_decor_title_text_height">64dp</dimen>
- <dimen name="lb_preference_decor_title_padding_top">27dp</dimen>
- <dimen name="lb_preference_decor_title_padding_start">24dp</dimen>
- <dimen name="lb_preference_decor_title_padding_end">56dp</dimen>
- <dimen name="lb_preference_decor_title_text_size">20sp</dimen>
+ <dimen name="lb_preference_decor_title_text_height">64dp</dimen>
+ <dimen name="lb_preference_decor_title_margin_top">27dp</dimen>
+ <dimen name="lb_preference_decor_title_margin_start">24dp</dimen>
+ <dimen name="lb_preference_decor_title_margin_end">56dp</dimen>
+ <dimen name="lb_preference_decor_title_text_size">20sp</dimen>
+ <dimen name="lb_preference_decor_title_container_elevation">2dp</dimen>
+ <dimen name="lb_preference_decor_elevation">6dp</dimen>
- <dimen name="lb_settings_pane_width">360dp</dimen>
+ <dimen name="lb_preference_item_padding_start">24dp</dimen>
+ <dimen name="lb_preference_item_padding_end">56dp</dimen>
+ <dimen name="lb_preference_item_icon_size">32dp</dimen>
+ <dimen name="lb_preference_item_icon_margin_end">16dp</dimen>
+
+ <dimen name="lb_preference_item_primary_text_size">14sp</dimen>
+ <dimen name="lb_preference_item_primary_text_margin_bottom">2dp</dimen>
+ <dimen name="lb_preference_item_secondary_text_size">12sp</dimen>
+ <dimen name="lb_preference_item_text_space_top">14dp</dimen>
+ <dimen name="lb_preference_item_text_space_bottom">13dp</dimen>
+
+ <dimen name="lb_preference_category_text_size">12sp</dimen>
+ <dimen name="lb_preference_category_height">40dp</dimen>
+
+ <dimen name="lb_settings_pane_width">360dp</dimen>
</resources>
diff --git a/v17/preference-leanback/res/values/styles.xml b/v17/preference-leanback/res/values/styles.xml
new file mode 100644
index 0000000000..42d2b5b63a
--- /dev/null
+++ b/v17/preference-leanback/res/values/styles.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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
+ -->
+
+<resources>
+
+ <style name="LeanbackPreference">
+ <item name="android:layout">@layout/leanback_preference</item>
+ </style>
+
+ <style name="LeanbackPreference.Information">
+ <item name="android:layout">@layout/leanback_preference_information</item>
+ <item name="android:enabled">false</item>
+ <item name="android:shouldDisableView">false</item>
+ </style>
+
+ <style name="LeanbackPreference.Category">
+ <item name="android:layout">@layout/leanback_preference_category</item>
+ <!-- The title should not dim if the category is disabled, instead only the preference children should dim. -->
+ <item name="android:shouldDisableView">false</item>
+ <item name="android:selectable">false</item>
+ </style>
+
+ <style name="LeanbackPreference.CheckBoxPreference">
+ <item name="android:widgetLayout">@layout/preference_widget_checkbox</item>
+ </style>
+
+ <style name="LeanbackPreference.SwitchPreferenceCompat">
+ <item name="android:widgetLayout">@layout/preference_widget_switch_compat</item>
+ <item name="android:switchTextOn">@string/v7_preference_on</item>
+ <item name="android:switchTextOff">@string/v7_preference_off</item>
+ </style>
+
+ <style name="LeanbackPreference.SwitchPreference">
+ <item name="android:widgetLayout">@layout/preference_widget_switch</item>
+ <item name="android:switchTextOn">@string/v7_preference_on</item>
+ <item name="android:switchTextOff">@string/v7_preference_off</item>
+ </style>
+
+ <style name="LeanbackPreference.PreferenceScreen">
+ </style>
+
+ <style name="LeanbackPreference.DialogPreference">
+ <item name="android:positiveButtonText">@android:string/ok</item>
+ <item name="android:negativeButtonText">@android:string/cancel</item>
+ </style>
+
+ <style name="LeanbackPreference.DialogPreference.EditTextPreference">
+ <item name="android:dialogLayout">@layout/preference_dialog_edittext</item>
+ </style>
+
+ <style name="PreferenceFragment.Leanback">
+ <item name="android:divider">@null</item>
+ </style>
+
+ <style name="PreferenceFragmentList.Leanback">
+ <item name="android:paddingStart">0dp</item>
+ <item name="android:paddingEnd">0dp</item>
+ </style>
+
+</resources>
diff --git a/v17/preference-leanback/res/values/themes.xml b/v17/preference-leanback/res/values/themes.xml
new file mode 100644
index 0000000000..591fdfa1a7
--- /dev/null
+++ b/v17/preference-leanback/res/values/themes.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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
+ -->
+
+<resources>
+ <style name="PreferenceThemeOverlay.v14.Leanback">
+ <item name="preferenceScreenStyle">@style/LeanbackPreference.PreferenceScreen</item>
+ <item name="preferenceFragmentCompatStyle">@style/PreferenceFragment.Leanback</item>
+ <item name="preferenceFragmentStyle">@style/PreferenceFragment.Leanback</item>
+ <item name="preferenceCategoryStyle">@style/LeanbackPreference.Category</item>
+ <item name="preferenceStyle">@style/LeanbackPreference</item>
+ <item name="preferenceInformationStyle">@style/LeanbackPreference.Information</item>
+ <item name="checkBoxPreferenceStyle">@style/LeanbackPreference.CheckBoxPreference</item>
+ <item name="switchPreferenceCompatStyle">@style/LeanbackPreference.SwitchPreferenceCompat</item>
+ <item name="switchPreferenceStyle">@style/LeanbackPreference.SwitchPreference</item>
+ <item name="dialogPreferenceStyle">@style/LeanbackPreference.DialogPreference</item>
+ <item name="editTextPreferenceStyle">@style/LeanbackPreference.DialogPreference.EditTextPreference</item>
+ <item name="preferenceFragmentListStyle">@style/PreferenceFragmentList.Leanback</item>
+ </style>
+</resources>
diff --git a/v17/preference-leanback/src/android/support/v17/preference/LeanbackListPreferenceDialogFragment.java b/v17/preference-leanback/src/android/support/v17/preference/LeanbackListPreferenceDialogFragment.java
index 92fdd62d79..a82f54334c 100644
--- a/v17/preference-leanback/src/android/support/v17/preference/LeanbackListPreferenceDialogFragment.java
+++ b/v17/preference-leanback/src/android/support/v17/preference/LeanbackListPreferenceDialogFragment.java
@@ -156,8 +156,15 @@ public class LeanbackListPreferenceDialogFragment extends LeanbackPreferenceDial
public void onItemClick(ViewHolder viewHolder) {
final int index = viewHolder.getAdapterPosition();
final CharSequence entry = mEntryValues[index];
- mSelectedValue = entry;
- ((ListPreference) getPreference()).setValue(entry.toString());
+ final ListPreference preference = (ListPreference) getPreference();
+ if (index >= 0) {
+ String value = mEntryValues[index].toString();
+ if (preference.callChangeListener(value)) {
+ preference.setValue(value);
+ mSelectedValue = entry;
+ }
+ }
+
getFragmentManager().popBackStack();
notifyDataSetChanged();
}
@@ -206,7 +213,20 @@ public class LeanbackListPreferenceDialogFragment extends LeanbackPreferenceDial
} else {
mSelections.add(entry);
}
- ((MultiSelectListPreference) getPreference()).setValues(mSelections);
+ final MultiSelectListPreference multiSelectListPreference
+ = (MultiSelectListPreference) getPreference();
+ // Pass copies of the set to callChangeListener and setValues to avoid mutations
+ if (multiSelectListPreference.callChangeListener(new HashSet<>(mSelections))) {
+ multiSelectListPreference.setValues(new HashSet<>(mSelections));
+ } else {
+ // Change refused, back it out
+ if (mSelections.contains(entry)) {
+ mSelections.remove(entry);
+ } else {
+ mSelections.add(entry);
+ }
+ }
+
notifyDataSetChanged();
}
}
diff --git a/v17/tests/AndroidManifest.xml b/v17/tests/AndroidManifest.xml
index f78d4356e4..f4dd2936e6 100644
--- a/v17/tests/AndroidManifest.xml
+++ b/v17/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.support.v17.leanback.tests">
- <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="17"/>
+ <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="23"/>
<!--
This declares that this application uses the instrumentation test runner targeting
@@ -33,6 +33,14 @@
<activity android:name="android.support.v17.leanback.widget.GridActivity"
android:exported="true" />
- </application>
+ <activity android:name="android.support.v17.leanback.app.BrowseFragmentTestActivity"
+ android:theme="@style/Theme.Leanback.Browse"
+ android:exported="true" />
+
+ <activity android:name="android.support.v17.leanback.app.BrowseSupportFragmentTestActivity"
+ android:theme="@style/Theme.Leanback.Browse"
+ android:exported="true" />
+
+ </application>
</manifest>
diff --git a/v17/tests/generatev4.py b/v17/tests/generatev4.py
new file mode 100755
index 0000000000..8dc4dc23aa
--- /dev/null
+++ b/v17/tests/generatev4.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+# Copyright (C) 2015 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.
+
+import os
+import sys
+
+print "Generate v4 fragment related code for leanback"
+
+files = ['BrowseTest']
+
+cls = ['BrowseTest', 'Background', 'Base', 'BaseRow', 'Browse', 'Details', 'Error', 'Headers',
+ 'PlaybackOverlay', 'Rows', 'Search', 'VerticalGrid', 'Branded']
+
+for w in files:
+ print "copy {}Fragment to {}SupportFragment".format(w, w)
+
+ file = open('src/android/support/v17/leanback/app/{}Fragment.java'.format(w), 'r')
+ outfile = open('src/android/support/v17/leanback/app/{}SupportFragment.java'.format(w), 'w')
+
+ outfile.write("/* This file is auto-generated from {}Fragment.java. DO NOT MODIFY. */\n\n".format(w))
+
+ for line in file:
+ for w in cls:
+ line = line.replace('{}Fragment'.format(w), '{}SupportFragment'.format(w))
+ line = line.replace('android.app.Fragment', 'android.support.v4.app.Fragment')
+ line = line.replace('android.app.Activity', 'android.support.v4.app.FragmentActivity')
+ outfile.write(line)
+ file.close()
+ outfile.close()
+
+testcls = ['Browse']
+
+for w in testcls:
+ print "copy {}FrgamentTest to {}SupportFragmentTest".format(w, w)
+
+ file = open('src/android/support/v17/leanback/app/{}FragmentTest.java'.format(w), 'r')
+ outfile = open('src/android/support/v17/leanback/app/{}SupportFragmentTest.java'.format(w), 'w')
+
+ outfile.write("/* This file is auto-generated from {}FrgamentTest.java. DO NOT MODIFY. */\n\n".format(w))
+
+ for line in file:
+ for w in testcls:
+ line = line.replace('{}FragmentTest'.format(w), '{}SupportFragmentTest'.format(w))
+ line = line.replace('{}FragmentTestActivity'.format(w), '{}SupportFragmentTestActivity'.format(w))
+ line = line.replace('{}TestFragment'.format(w), '{}TestSupportFragment'.format(w))
+ outfile.write(line)
+ file.close()
+ outfile.close()
+
+
+print "copy BrowseFragmentTestActivity to BrowseSupportFragmentTestActivity"
+file = open('src/android/support/v17/leanback/app/BrowseFragmentTestActivity.java', 'r')
+outfile = open('src/android/support/v17/leanback/app/BrowseSupportFragmentTestActivity.java', 'w')
+outfile.write("/* This file is auto-generated from BrowseFragmentTestActivity.java. DO NOT MODIFY. */\n\n")
+for line in file:
+ line = line.replace('BrowseTestFragment', 'BrowseTestSupportFragment')
+ line = line.replace('BrowseFragmentTestActivity', 'BrowseSupportFragmentTestActivity')
+ line = line.replace('android.app.Fragment', 'android.support.v4.app.Fragment')
+ line = line.replace('android.app.Activity', 'android.support.v4.app.FragmentActivity')
+ line = line.replace('extends Activity', 'extends FragmentActivity')
+ line = line.replace('getFragmentManager', 'getSupportFragmentManager')
+ outfile.write(line)
+file.close()
+outfile.close()
+
diff --git a/v17/tests/res/layout/browse.xml b/v17/tests/res/layout/browse.xml
new file mode 100644
index 0000000000..01226dadc7
--- /dev/null
+++ b/v17/tests/res/layout/browse.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main_frame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- container for hosting GuidedStepFragment background -->
+ <FrameLayout android:id="@+id/lb_guidedstep_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</FrameLayout>
diff --git a/v17/tests/src/android/support/v17/leanback/app/BrowseFragmentTest.java b/v17/tests/src/android/support/v17/leanback/app/BrowseFragmentTest.java
new file mode 100644
index 0000000000..e9b1063b30
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/app/BrowseFragmentTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.app;
+
+import android.support.v17.leanback.tests.R;
+import android.test.ActivityInstrumentationTestCase2;
+import android.text.Selection;
+import android.text.Spannable;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v7.widget.RecyclerViewAccessibilityDelegate;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * @hide from javadoc
+ */
+public class BrowseFragmentTest extends
+ ActivityInstrumentationTestCase2<BrowseFragmentTestActivity> {
+
+ static final long TRANSITION_LENGTH = 1000;
+
+ Instrumentation mInstrumentation;
+ BrowseFragmentTestActivity mActivity;
+
+ public BrowseFragmentTest() {
+ super(BrowseFragmentTestActivity.class);
+ }
+
+ private void initActivity(Intent intent) {
+ setActivityIntent(intent);
+ mActivity = getActivity();
+ try {
+ Thread.sleep(intent.getLongExtra(BrowseFragmentTestActivity.EXTRA_LOAD_DATA_DELAY,
+ BrowseTestFragment.DEFAULT_LOAD_DATA_DELAY) + TRANSITION_LENGTH);
+ } catch (InterruptedException ex) {
+ }
+ }
+
+ public void testTwoBackKeysWithBackStack() throws Throwable {
+ mInstrumentation = getInstrumentation();
+ Intent intent = new Intent(mInstrumentation.getContext(), BrowseFragmentTestActivity.class);
+ intent.putExtra(BrowseFragmentTestActivity.EXTRA_LOAD_DATA_DELAY, (long) 1000);
+ intent.putExtra(BrowseFragmentTestActivity.EXTRA_ADD_TO_BACKSTACK , true);
+ initActivity(intent);
+
+ sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+ Thread.sleep(TRANSITION_LENGTH);
+
+ sendKeys(KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_BACK);
+ }
+
+ public void testTwoBackKeysWithoutBackStack() throws Throwable {
+ mInstrumentation = getInstrumentation();
+ Intent intent = new Intent(mInstrumentation.getContext(), BrowseFragmentTestActivity.class);
+ intent.putExtra(BrowseFragmentTestActivity.EXTRA_LOAD_DATA_DELAY, (long) 1000);
+ intent.putExtra(BrowseFragmentTestActivity.EXTRA_ADD_TO_BACKSTACK , false);
+ initActivity(intent);
+
+ sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+ Thread.sleep(TRANSITION_LENGTH);
+
+ sendKeys(KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_BACK);
+ }
+
+}
diff --git a/v17/tests/src/android/support/v17/leanback/app/BrowseFragmentTestActivity.java b/v17/tests/src/android/support/v17/leanback/app/BrowseFragmentTestActivity.java
new file mode 100644
index 0000000000..ee433bdb0d
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/app/BrowseFragmentTestActivity.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.app;
+
+import android.app.Activity;
+import android.app.FragmentTransaction;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v17.leanback.tests.R;
+
+/**
+ * @hide from javadoc
+ */
+public class BrowseFragmentTestActivity extends Activity {
+
+ public static final String EXTRA_ADD_TO_BACKSTACK = "addToBackStack";
+ public static final String EXTRA_NUM_ROWS = "numRows";
+ public static final String EXTRA_REPEAT_PER_ROW = "repeatPerRow";
+ public static final String EXTRA_LOAD_DATA_DELAY = "loadDataDelay";
+ public static final String EXTRA_TEST_ENTRANCE_TRANSITION = "testEntranceTransition";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = getIntent();
+
+ BrowseTestFragment.NUM_ROWS = intent.getIntExtra(EXTRA_NUM_ROWS,
+ BrowseTestFragment.DEFAULT_NUM_ROWS);
+ BrowseTestFragment.REPEAT_PER_ROW = intent.getIntExtra(EXTRA_REPEAT_PER_ROW,
+ BrowseTestFragment.DEFAULT_REPEAT_PER_ROW);
+ BrowseTestFragment.LOAD_DATA_DELAY = intent.getLongExtra(EXTRA_LOAD_DATA_DELAY,
+ BrowseTestFragment.DEFAULT_LOAD_DATA_DELAY);
+ BrowseTestFragment.TEST_ENTRANCE_TRANSITION = intent.getBooleanExtra(
+ EXTRA_TEST_ENTRANCE_TRANSITION,
+ BrowseTestFragment.DEFAULT_TEST_ENTRANCE_TRANSITION);
+ setContentView(R.layout.browse);
+ FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.replace(R.id.main_frame, new BrowseTestFragment());
+ if (intent.getBooleanExtra(EXTRA_ADD_TO_BACKSTACK, false)) {
+ ft.addToBackStack(null);
+ }
+ ft.commit();
+ }
+}
diff --git a/v17/tests/src/android/support/v17/leanback/app/BrowseSupportFragmentTest.java b/v17/tests/src/android/support/v17/leanback/app/BrowseSupportFragmentTest.java
new file mode 100644
index 0000000000..0c901be000
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/app/BrowseSupportFragmentTest.java
@@ -0,0 +1,95 @@
+/* This file is auto-generated from BrowseFrgamentTest.java. DO NOT MODIFY. */
+
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.app;
+
+import android.support.v17.leanback.tests.R;
+import android.test.ActivityInstrumentationTestCase2;
+import android.text.Selection;
+import android.text.Spannable;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v7.widget.RecyclerViewAccessibilityDelegate;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * @hide from javadoc
+ */
+public class BrowseSupportFragmentTest extends
+ ActivityInstrumentationTestCase2<BrowseSupportFragmentTestActivity> {
+
+ static final long TRANSITION_LENGTH = 1000;
+
+ Instrumentation mInstrumentation;
+ BrowseSupportFragmentTestActivity mActivity;
+
+ public BrowseSupportFragmentTest() {
+ super(BrowseSupportFragmentTestActivity.class);
+ }
+
+ private void initActivity(Intent intent) {
+ setActivityIntent(intent);
+ mActivity = getActivity();
+ try {
+ Thread.sleep(intent.getLongExtra(BrowseSupportFragmentTestActivity.EXTRA_LOAD_DATA_DELAY,
+ BrowseTestSupportFragment.DEFAULT_LOAD_DATA_DELAY) + TRANSITION_LENGTH);
+ } catch (InterruptedException ex) {
+ }
+ }
+
+ public void testTwoBackKeysWithBackStack() throws Throwable {
+ mInstrumentation = getInstrumentation();
+ Intent intent = new Intent(mInstrumentation.getContext(), BrowseSupportFragmentTestActivity.class);
+ intent.putExtra(BrowseSupportFragmentTestActivity.EXTRA_LOAD_DATA_DELAY, (long) 1000);
+ intent.putExtra(BrowseSupportFragmentTestActivity.EXTRA_ADD_TO_BACKSTACK , true);
+ initActivity(intent);
+
+ sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+ Thread.sleep(TRANSITION_LENGTH);
+
+ sendKeys(KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_BACK);
+ }
+
+ public void testTwoBackKeysWithoutBackStack() throws Throwable {
+ mInstrumentation = getInstrumentation();
+ Intent intent = new Intent(mInstrumentation.getContext(), BrowseSupportFragmentTestActivity.class);
+ intent.putExtra(BrowseSupportFragmentTestActivity.EXTRA_LOAD_DATA_DELAY, (long) 1000);
+ intent.putExtra(BrowseSupportFragmentTestActivity.EXTRA_ADD_TO_BACKSTACK , false);
+ initActivity(intent);
+
+ sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+ Thread.sleep(TRANSITION_LENGTH);
+
+ sendKeys(KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_BACK);
+ }
+
+}
diff --git a/v17/tests/src/android/support/v17/leanback/app/BrowseSupportFragmentTestActivity.java b/v17/tests/src/android/support/v17/leanback/app/BrowseSupportFragmentTestActivity.java
new file mode 100644
index 0000000000..036d25486a
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/app/BrowseSupportFragmentTestActivity.java
@@ -0,0 +1,60 @@
+/* This file is auto-generated from BrowseFragmentTestActivity.java. DO NOT MODIFY. */
+
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.app;
+
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v17.leanback.tests.R;
+
+/**
+ * @hide from javadoc
+ */
+public class BrowseSupportFragmentTestActivity extends FragmentActivity {
+
+ public static final String EXTRA_ADD_TO_BACKSTACK = "addToBackStack";
+ public static final String EXTRA_NUM_ROWS = "numRows";
+ public static final String EXTRA_REPEAT_PER_ROW = "repeatPerRow";
+ public static final String EXTRA_LOAD_DATA_DELAY = "loadDataDelay";
+ public static final String EXTRA_TEST_ENTRANCE_TRANSITION = "testEntranceTransition";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = getIntent();
+
+ BrowseTestSupportFragment.NUM_ROWS = intent.getIntExtra(EXTRA_NUM_ROWS,
+ BrowseTestSupportFragment.DEFAULT_NUM_ROWS);
+ BrowseTestSupportFragment.REPEAT_PER_ROW = intent.getIntExtra(EXTRA_REPEAT_PER_ROW,
+ BrowseTestSupportFragment.DEFAULT_REPEAT_PER_ROW);
+ BrowseTestSupportFragment.LOAD_DATA_DELAY = intent.getLongExtra(EXTRA_LOAD_DATA_DELAY,
+ BrowseTestSupportFragment.DEFAULT_LOAD_DATA_DELAY);
+ BrowseTestSupportFragment.TEST_ENTRANCE_TRANSITION = intent.getBooleanExtra(
+ EXTRA_TEST_ENTRANCE_TRANSITION,
+ BrowseTestSupportFragment.DEFAULT_TEST_ENTRANCE_TRANSITION);
+ setContentView(R.layout.browse);
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ ft.replace(R.id.main_frame, new BrowseTestSupportFragment());
+ if (intent.getBooleanExtra(EXTRA_ADD_TO_BACKSTACK, false)) {
+ ft.addToBackStack(null);
+ }
+ ft.commit();
+ }
+}
diff --git a/v17/tests/src/android/support/v17/leanback/app/BrowseTestFragment.java b/v17/tests/src/android/support/v17/leanback/app/BrowseTestFragment.java
new file mode 100644
index 0000000000..744a926e87
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/app/BrowseTestFragment.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.app;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.OnItemViewClickedListener;
+import android.support.v17.leanback.widget.OnItemViewSelectedListener;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.RowPresenter;
+import android.util.Log;
+import android.view.View;
+
+/**
+ * @hide from javadoc
+ */
+public class BrowseTestFragment extends BrowseFragment {
+ private static final String TAG = "BrowseTestFragment";
+
+ final static int DEFAULT_NUM_ROWS = 100;
+ final static int DEFAULT_REPEAT_PER_ROW = 20;
+ final static long DEFAULT_LOAD_DATA_DELAY = 2000;
+ final static boolean DEFAULT_TEST_ENTRANCE_TRANSITION = true;
+
+ static int NUM_ROWS = DEFAULT_NUM_ROWS;
+ static int REPEAT_PER_ROW = DEFAULT_REPEAT_PER_ROW;
+ static long LOAD_DATA_DELAY = DEFAULT_LOAD_DATA_DELAY;
+ static boolean TEST_ENTRANCE_TRANSITION = DEFAULT_TEST_ENTRANCE_TRANSITION;
+
+ private ArrayObjectAdapter mRowsAdapter;
+
+ // For good performance, it's important to use a single instance of
+ // a card presenter for all rows using that presenter.
+ final static StringPresenter sCardPresenter = new StringPresenter();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
+ setTitle("BrowseTestFragment");
+ setHeadersState(HEADERS_ENABLED);
+
+ setOnSearchClickedListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Log.i(TAG, "onSearchClicked");
+ }
+ });
+
+ setupRows();
+ setOnItemViewClickedListener(new ItemViewClickedListener());
+ setOnItemViewSelectedListener(new OnItemViewSelectedListener() {
+ @Override
+ public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ Log.i(TAG, "onItemSelected: " + item + " row " + row);
+ }
+ });
+ if (TEST_ENTRANCE_TRANSITION) {
+ // don't run entrance transition if fragment is restored.
+ if (savedInstanceState == null) {
+ prepareEntranceTransition();
+ }
+ }
+ // simulates in a real world use case data being loaded two seconds later
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ loadData();
+ startEntranceTransition();
+ }
+ }, LOAD_DATA_DELAY);
+ }
+
+ private void setupRows() {
+ ListRowPresenter lrp = new ListRowPresenter();
+
+ mRowsAdapter = new ArrayObjectAdapter(lrp);
+
+ setAdapter(mRowsAdapter);
+ }
+
+ private void loadData() {
+ for (int i = 0; i < NUM_ROWS; ++i) {
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(sCardPresenter);
+ for (int j = 0; j < REPEAT_PER_ROW; ++j) {
+ listRowAdapter.add("Hello world");
+ listRowAdapter.add("This is a test");
+ listRowAdapter.add("Android TV");
+ listRowAdapter.add("Leanback");
+ listRowAdapter.add("Hello world");
+ listRowAdapter.add("Android TV");
+ listRowAdapter.add("Leanback");
+ listRowAdapter.add("GuidedStepFragment");
+ }
+ HeaderItem header = new HeaderItem(i, "Row " + i);
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+ }
+
+ }
+
+ private final class ItemViewClickedListener implements OnItemViewClickedListener {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ Log.i(TAG, "onItemClicked: " + item + " row " + row);
+ }
+ }
+}
diff --git a/v17/tests/src/android/support/v17/leanback/app/BrowseTestSupportFragment.java b/v17/tests/src/android/support/v17/leanback/app/BrowseTestSupportFragment.java
new file mode 100644
index 0000000000..1a01b7b177
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/app/BrowseTestSupportFragment.java
@@ -0,0 +1,128 @@
+/* This file is auto-generated from BrowseTestFragment.java. DO NOT MODIFY. */
+
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.app;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.OnItemViewClickedListener;
+import android.support.v17.leanback.widget.OnItemViewSelectedListener;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.RowPresenter;
+import android.util.Log;
+import android.view.View;
+
+/**
+ * @hide from javadoc
+ */
+public class BrowseTestSupportFragment extends BrowseSupportFragment {
+ private static final String TAG = "BrowseTestSupportFragment";
+
+ final static int DEFAULT_NUM_ROWS = 100;
+ final static int DEFAULT_REPEAT_PER_ROW = 20;
+ final static long DEFAULT_LOAD_DATA_DELAY = 2000;
+ final static boolean DEFAULT_TEST_ENTRANCE_TRANSITION = true;
+
+ static int NUM_ROWS = DEFAULT_NUM_ROWS;
+ static int REPEAT_PER_ROW = DEFAULT_REPEAT_PER_ROW;
+ static long LOAD_DATA_DELAY = DEFAULT_LOAD_DATA_DELAY;
+ static boolean TEST_ENTRANCE_TRANSITION = DEFAULT_TEST_ENTRANCE_TRANSITION;
+
+ private ArrayObjectAdapter mRowsAdapter;
+
+ // For good performance, it's important to use a single instance of
+ // a card presenter for all rows using that presenter.
+ final static StringPresenter sCardPresenter = new StringPresenter();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
+ setTitle("BrowseTestSupportFragment");
+ setHeadersState(HEADERS_ENABLED);
+
+ setOnSearchClickedListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Log.i(TAG, "onSearchClicked");
+ }
+ });
+
+ setupRows();
+ setOnItemViewClickedListener(new ItemViewClickedListener());
+ setOnItemViewSelectedListener(new OnItemViewSelectedListener() {
+ @Override
+ public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ Log.i(TAG, "onItemSelected: " + item + " row " + row);
+ }
+ });
+ if (TEST_ENTRANCE_TRANSITION) {
+ // don't run entrance transition if fragment is restored.
+ if (savedInstanceState == null) {
+ prepareEntranceTransition();
+ }
+ }
+ // simulates in a real world use case data being loaded two seconds later
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ loadData();
+ startEntranceTransition();
+ }
+ }, LOAD_DATA_DELAY);
+ }
+
+ private void setupRows() {
+ ListRowPresenter lrp = new ListRowPresenter();
+
+ mRowsAdapter = new ArrayObjectAdapter(lrp);
+
+ setAdapter(mRowsAdapter);
+ }
+
+ private void loadData() {
+ for (int i = 0; i < NUM_ROWS; ++i) {
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(sCardPresenter);
+ for (int j = 0; j < REPEAT_PER_ROW; ++j) {
+ listRowAdapter.add("Hello world");
+ listRowAdapter.add("This is a test");
+ listRowAdapter.add("Android TV");
+ listRowAdapter.add("Leanback");
+ listRowAdapter.add("Hello world");
+ listRowAdapter.add("Android TV");
+ listRowAdapter.add("Leanback");
+ listRowAdapter.add("GuidedStepFragment");
+ }
+ HeaderItem header = new HeaderItem(i, "Row " + i);
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+ }
+
+ }
+
+ private final class ItemViewClickedListener implements OnItemViewClickedListener {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ Log.i(TAG, "onItemClicked: " + item + " row " + row);
+ }
+ }
+}
diff --git a/v17/tests/src/android/support/v17/leanback/app/StringPresenter.java b/v17/tests/src/android/support/v17/leanback/app/StringPresenter.java
new file mode 100644
index 0000000000..e6e0793f0b
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/app/StringPresenter.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.app;
+
+import android.graphics.Color;
+import android.support.v17.leanback.widget.Presenter;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * @hide from javadoc
+ */
+public class StringPresenter extends Presenter {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "StringPresenter";
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent) {
+ if (DEBUG) Log.d(TAG, "onCreateViewHolder");
+ TextView tv = new TextView(parent.getContext());
+ tv.setFocusable(true);
+ tv.setFocusableInTouchMode(true);
+ tv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 200));
+ tv.setBackgroundColor(Color.CYAN);
+ tv.setTextColor(Color.BLACK);
+ return new ViewHolder(tv);
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder viewHolder, Object item) {
+ if (DEBUG) Log.d(TAG, "onBindViewHolder for " + item.toString());
+ ((TextView) viewHolder.view).setText(item.toString());
+ }
+
+ @Override
+ public void onUnbindViewHolder(ViewHolder viewHolder) {
+ if (DEBUG) Log.d(TAG, "onUnbindViewHolder");
+ }
+}
diff --git a/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java b/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
index 145ae4850d..902a665a40 100644
--- a/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
+++ b/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
@@ -360,7 +360,8 @@ public class GridActivity extends Activity {
holder.mItemAlignment = null;
}
if (mChildLayout == -1) {
- ((TextView) holder.itemView).setText("Item "+mItemLengths[position]);
+ ((TextView) holder.itemView).setText("Item "+mItemLengths[position]
+ + " type=" + getItemViewType(position));
boolean focusable = true;
if (mItemFocusables != null) {
focusable = mItemFocusables[position];
@@ -370,7 +371,8 @@ public class GridActivity extends Activity {
holder.itemView.setBackgroundColor(Color.LTGRAY);
} else {
if (holder.itemView instanceof TextView) {
- ((TextView) holder.itemView).setText("Item "+mItemLengths[position]);
+ ((TextView) holder.itemView).setText("Item "+mItemLengths[position]
+ + " type=" + getItemViewType(position));
}
}
updateSize(holder.itemView, position);
@@ -380,6 +382,7 @@ public class GridActivity extends Activity {
public int getItemCount() {
return mNumItems;
}
+
}
void updateSize(View view, int position) {
diff --git a/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java b/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
index e9e53e4a33..335f449bd4 100644
--- a/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
+++ b/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
@@ -21,6 +21,7 @@ import android.text.Selection;
import android.text.Spannable;
import android.util.Log;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -105,6 +106,23 @@ public class GridWidgetTest extends ActivityInstrumentationTestCase2<GridActivit
Thread.sleep(500);
}
+ protected void waitForScrollIdleAndItemAnimation(Runnable verify) throws Throwable {
+ waitForScrollIdle();
+ waitForItemAnimation();
+ verify.run();
+ }
+
+ protected void waitForItemAnimation() throws Throwable {
+ Thread.sleep(100);
+ while (mGridView.getItemAnimator() != null && mGridView.getItemAnimator().isRunning()) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ break;
+ }
+ }
+ }
+
/**
* Wait for grid view stop scroll and optionally verify state of grid view.
*/
@@ -1161,12 +1179,12 @@ public class GridWidgetTest extends ActivityInstrumentationTestCase2<GridActivit
initActivity(intent);
mGridView.setSelectedPositionSmooth(0);
- waitForScrollIdle(mVerifyLayout);
+ waitForScrollIdleAndItemAnimation(mVerifyLayout);
for (int i = 0; i < pressDown; i++) {
sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
}
- waitForScrollIdle(mVerifyLayout);
+ waitForScrollIdleAndItemAnimation(mVerifyLayout);
assertFalse(mGridView.isFocused());
}
@@ -1570,6 +1588,40 @@ public class GridWidgetTest extends ActivityInstrumentationTestCase2<GridActivit
((VerticalGridViewEx) mGridView).mSmoothScrollByCalled < 10);
}
+ public void testSmoothscrollerCancelled() throws Throwable {
+ mInstrumentation = getInstrumentation();
+ Intent intent = new Intent(mInstrumentation.getContext(), GridActivity.class);
+ intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
+ R.layout.vertical_linear);
+ intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
+ int[] items = new int[100];
+ for (int i = 0; i < items.length; i++) {
+ items[i] = 680;
+ }
+ intent.putExtra(GridActivity.EXTRA_ITEMS, items);
+ intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
+ mOrientation = BaseGridView.VERTICAL;
+ mNumRows = 1;
+
+ initActivity(intent);
+
+ mGridView.setSelectedPositionSmooth(0);
+ waitForScrollIdle(mVerifyLayout);
+ assertTrue(mGridView.getChildAt(0).hasFocus());
+
+ int targetPosition = items.length - 1;
+ mGridView.setSelectedPositionSmooth(targetPosition);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mGridView.stopScroll();
+ }
+ });
+ Thread.sleep(100);
+ assertEquals(mGridView.getSelectedPosition(), targetPosition);
+ assertSame(mGridView.getLayoutManager().findViewByPosition(targetPosition),
+ mGridView.findFocus());
+ }
+
public void testSetNumRowsAndAddItem() throws Throwable {
mInstrumentation = getInstrumentation();
Intent intent = new Intent(mInstrumentation.getContext(), GridActivity.class);
@@ -1656,7 +1708,7 @@ public class GridWidgetTest extends ActivityInstrumentationTestCase2<GridActivit
mGridView.setSelectedPositionSmooth(0);
}
});
- waitForScrollIdle(mVerifyLayout);
+ waitForScrollIdleAndItemAnimation(mVerifyLayout);
verifyMargin();
runTestOnUiThread(new Runnable() {
@@ -1664,7 +1716,7 @@ public class GridWidgetTest extends ActivityInstrumentationTestCase2<GridActivit
mGridView.setSelectedPositionSmooth(1);
}
});
- waitForScrollIdle(mVerifyLayout);
+ waitForScrollIdleAndItemAnimation(mVerifyLayout);
verifyMargin();
}
@@ -1735,7 +1787,7 @@ public class GridWidgetTest extends ActivityInstrumentationTestCase2<GridActivit
mGridView.setSelectedPositionSmooth(1);
}
});
- waitForScrollIdle(mVerifyLayout);
+ waitForScrollIdleAndItemAnimation(mVerifyLayout);
assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionStart(), 1);
assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionEnd(), 2);
assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionStart(), 1);
@@ -1753,7 +1805,7 @@ public class GridWidgetTest extends ActivityInstrumentationTestCase2<GridActivit
mGridView.setSelectedPositionSmooth(0);
}
});
- waitForScrollIdle(mVerifyLayout);
+ waitForScrollIdleAndItemAnimation(mVerifyLayout);
assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionStart(), 1);
assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionEnd(), 2);
assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionStart(), 1);
@@ -1835,6 +1887,20 @@ public class GridWidgetTest extends ActivityInstrumentationTestCase2<GridActivit
}
}
+ static class ChangeableViewTypesProvider implements ViewTypeProvider {
+ static SparseIntArray sViewTypes = new SparseIntArray();
+ @Override
+ public int getViewType(int position) {
+ return sViewTypes.get(position);
+ }
+ public static void clear() {
+ sViewTypes.clear();
+ }
+ public static void setViewType(int position, int type) {
+ sViewTypes.put(position, type);
+ }
+ }
+
static class PositionItemAlignmentFacetProviderForRelativeLayout1
implements ItemAlignmentFacetProvider {
ItemAlignmentFacet mMultipleFacet;
@@ -2050,6 +2116,38 @@ public class GridWidgetTest extends ActivityInstrumentationTestCase2<GridActivit
assertEquals(0, mGridView.getSelectedPosition());
}
+ public void testNotifyItemTypeChangedSelectionEvent() throws Throwable {
+ mInstrumentation = getInstrumentation();
+ Intent intent = new Intent(mInstrumentation.getContext(), GridActivity.class);
+ intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
+ R.layout.vertical_linear);
+ intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10);
+ intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
+ ChangeableViewTypesProvider.class.getName());
+ ChangeableViewTypesProvider.clear();
+ initActivity(intent);
+ mOrientation = BaseGridView.HORIZONTAL;
+ mNumRows = 1;
+
+ final ArrayList<Integer> selectedLog = new ArrayList<Integer>();
+ mGridView.setOnChildSelectedListener(new OnChildSelectedListener() {
+ public void onChildSelected(ViewGroup parent, View view, int position, long id) {
+ selectedLog.add(position);
+ }
+ });
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ ChangeableViewTypesProvider.setViewType(0, 1);
+ mGridView.getAdapter().notifyItemChanged(0, 1);
+ }
+ });
+ waitForTransientStateGone(null);
+ assertEquals(0, mGridView.getSelectedPosition());
+ assertEquals(selectedLog.size(), 1);
+ assertEquals((int) selectedLog.get(0), 0);
+ }
+
public void testSelectionSmoothAndAddItemInOneCycle() throws Throwable {
mInstrumentation = getInstrumentation();
Intent intent = new Intent(mInstrumentation.getContext(), GridActivity.class);
diff --git a/v17/tests/src/android/support/v17/leanback/widget/ShadowOverlayContainerTest.java b/v17/tests/src/android/support/v17/leanback/widget/ShadowOverlayContainerTest.java
new file mode 100644
index 0000000000..e7ec4bf0ce
--- /dev/null
+++ b/v17/tests/src/android/support/v17/leanback/widget/ShadowOverlayContainerTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.widget;
+
+import android.test.AndroidTestCase;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+
+public class ShadowOverlayContainerTest extends AndroidTestCase {
+
+ public void testWrapContent() {
+ FrameLayout frameLayout = new FrameLayout(getContext());
+ TextView textView = new TextView(getContext());
+ textView.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT));
+ textView.setText("abc");
+ ShadowOverlayContainer container = new ShadowOverlayContainer(getContext());
+ container.initialize(true, true, true);
+ container.wrap(textView);
+ frameLayout.addView(container);
+ frameLayout.measure(MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY));
+ frameLayout.layout(0, 0, 500, 500);
+ assertTrue(textView.getWidth() > 0);
+ assertTrue(textView.getWidth() < 500);
+ assertTrue(textView.getHeight() > 0);
+ assertTrue(textView.getHeight() < 500);
+ assertEquals(container.getWidth(), textView.getWidth());
+ assertEquals(container.getHeight(), textView.getHeight());
+
+ // change layout size of textView after wrap()
+ textView.setLayoutParams(new FrameLayout.LayoutParams(123, 123));
+ frameLayout.measure(MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY));
+ frameLayout.layout(0, 0, 500, 500);
+ assertTrue(textView.getWidth() == 123);
+ assertTrue(textView.getHeight() == 123);
+ assertEquals(container.getWidth(), textView.getWidth());
+ assertEquals(container.getHeight(), textView.getHeight());
+ }
+
+ public void testFixedSize() {
+ FrameLayout frameLayout = new FrameLayout(getContext());
+ TextView textView = new TextView(getContext());
+ textView.setLayoutParams(new FrameLayout.LayoutParams(200, LayoutParams.WRAP_CONTENT));
+ textView.setText("abc");
+ ShadowOverlayContainer container = new ShadowOverlayContainer(getContext());
+ container.initialize(true, true, true);
+ container.wrap(textView);
+ frameLayout.addView(container);
+ frameLayout.measure(MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY));
+ frameLayout.layout(0, 0, 500, 500);
+ assertTrue(textView.getWidth() == 200);
+ assertTrue(textView.getHeight() > 0);
+ assertTrue(textView.getHeight() < 500);
+ assertEquals(container.getWidth(), textView.getWidth());
+ assertEquals(container.getHeight(), textView.getHeight());
+
+ // change layout size of textView after wrap()
+ textView.setLayoutParams(new FrameLayout.LayoutParams(123, 123));
+ frameLayout.measure(MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY));
+ frameLayout.layout(0, 0, 500, 500);
+ assertTrue(textView.getWidth() == 123);
+ assertTrue(textView.getHeight() == 123);
+ assertEquals(container.getWidth(), textView.getWidth());
+ assertEquals(container.getHeight(), textView.getHeight());
+ }
+
+ public void testMatchParent() {
+ FrameLayout frameLayout = new FrameLayout(getContext());
+ TextView textView = new TextView(getContext());
+ textView.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT));
+ textView.setText("abc");
+ ShadowOverlayContainer container = new ShadowOverlayContainer(getContext());
+ container.initialize(true, true, true);
+ container.wrap(textView);
+ frameLayout.addView(container);
+ frameLayout.measure(MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY));
+ frameLayout.layout(0, 0, 500, 500);
+ assertTrue(textView.getWidth() == 500);
+ assertTrue(textView.getHeight() > 0);
+ assertTrue(textView.getHeight() < 500);
+ assertEquals(container.getWidth(), textView.getWidth());
+ assertEquals(container.getHeight(), textView.getHeight());
+ }
+}