FocusHighlightHelper.java revision 739e3805bf2785e6773aede5e2e1643f537305f9
147520b68e50572a9775a662410c5aff8300c8784Craig Stout/* 247520b68e50572a9775a662410c5aff8300c8784Craig Stout * Copyright (C) 2014 The Android Open Source Project 347520b68e50572a9775a662410c5aff8300c8784Craig Stout * 447520b68e50572a9775a662410c5aff8300c8784Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 547520b68e50572a9775a662410c5aff8300c8784Craig Stout * in compliance with the License. You may obtain a copy of the License at 647520b68e50572a9775a662410c5aff8300c8784Craig Stout * 747520b68e50572a9775a662410c5aff8300c8784Craig Stout * http://www.apache.org/licenses/LICENSE-2.0 847520b68e50572a9775a662410c5aff8300c8784Craig Stout * 947520b68e50572a9775a662410c5aff8300c8784Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License 1047520b68e50572a9775a662410c5aff8300c8784Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 1147520b68e50572a9775a662410c5aff8300c8784Craig Stout * or implied. See the License for the specific language governing permissions and limitations under 1247520b68e50572a9775a662410c5aff8300c8784Craig Stout * the License. 1347520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 1447520b68e50572a9775a662410c5aff8300c8784Craig Stoutpackage android.support.v17.leanback.widget; 1547520b68e50572a9775a662410c5aff8300c8784Craig Stout 16a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.graphics.drawable.TransitionDrawable; 1747520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport android.support.v17.leanback.R; 1847520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport android.view.View; 1955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.content.res.Resources; 2047520b68e50572a9775a662410c5aff8300c8784Craig Stout 21739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport static android.support.v17.leanback.widget.FocusHighlight.ZOOM_FACTOR_NONE; 22739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport static android.support.v17.leanback.widget.FocusHighlight.ZOOM_FACTOR_SMALL; 23739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport static android.support.v17.leanback.widget.FocusHighlight.ZOOM_FACTOR_MEDIUM; 24739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport static android.support.v17.leanback.widget.FocusHighlight.ZOOM_FACTOR_LARGE; 25739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 26739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 2747520b68e50572a9775a662410c5aff8300c8784Craig Stout/** 2847520b68e50572a9775a662410c5aff8300c8784Craig Stout * Setup the behavior how to highlight when a item gains focus. 2947520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 3047520b68e50572a9775a662410c5aff8300c8784Craig Stoutpublic class FocusHighlightHelper { 3147520b68e50572a9775a662410c5aff8300c8784Craig Stout 32b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout static class BrowseItemFocusHighlight implements FocusHighlight { 3347520b68e50572a9775a662410c5aff8300c8784Craig Stout private static final int DURATION_MS = 150; 3447520b68e50572a9775a662410c5aff8300c8784Craig Stout 35b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout private static float[] sScaleFactor = new float[4]; 36b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout 37b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout private int mScaleIndex; 38b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout 39b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout BrowseItemFocusHighlight(int zoomIndex) { 40b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout mScaleIndex = (zoomIndex >= 0 && zoomIndex < sScaleFactor.length) ? 41b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout zoomIndex : ZOOM_FACTOR_MEDIUM; 4247520b68e50572a9775a662410c5aff8300c8784Craig Stout } 4347520b68e50572a9775a662410c5aff8300c8784Craig Stout 44b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout private void lazyInit(Resources resources) { 45b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout if (sScaleFactor[ZOOM_FACTOR_NONE] == 0f) { 46b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout sScaleFactor[ZOOM_FACTOR_NONE] = 1f; 47b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout sScaleFactor[ZOOM_FACTOR_SMALL] = 48b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout resources.getFraction(R.fraction.lb_focus_zoom_factor_small, 1, 1); 49b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout sScaleFactor[ZOOM_FACTOR_MEDIUM] = 50b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout resources.getFraction(R.fraction.lb_focus_zoom_factor_medium, 1, 1); 51b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout sScaleFactor[ZOOM_FACTOR_LARGE] = 52b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout resources.getFraction(R.fraction.lb_focus_zoom_factor_large, 1, 1); 5347520b68e50572a9775a662410c5aff8300c8784Craig Stout } 5447520b68e50572a9775a662410c5aff8300c8784Craig Stout } 5547520b68e50572a9775a662410c5aff8300c8784Craig Stout 56b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout private float getScale(View view) { 57b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout lazyInit(view.getResources()); 58b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout return sScaleFactor[mScaleIndex]; 59b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout } 60b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout 6147520b68e50572a9775a662410c5aff8300c8784Craig Stout private void viewFocused(View view, boolean hasFocus) { 6247520b68e50572a9775a662410c5aff8300c8784Craig Stout if (hasFocus) { 6347520b68e50572a9775a662410c5aff8300c8784Craig Stout final float scale = getScale(view); 6447520b68e50572a9775a662410c5aff8300c8784Craig Stout view.animate().scaleX(scale).scaleY(scale).setDuration(DURATION_MS); 6547520b68e50572a9775a662410c5aff8300c8784Craig Stout } else { 6647520b68e50572a9775a662410c5aff8300c8784Craig Stout view.animate().scaleX(1f).scaleY(1f).setDuration(DURATION_MS); 6747520b68e50572a9775a662410c5aff8300c8784Craig Stout } 68892181367d658f347d00ea5e091aa31f086b2a20Dake Gu if (view instanceof ListRowCardWrapper) { 69892181367d658f347d00ea5e091aa31f086b2a20Dake Gu ListRowCardWrapper wrapper = (ListRowCardWrapper) view; 70892181367d658f347d00ea5e091aa31f086b2a20Dake Gu if (wrapper.mShadowNormal != null) { 71892181367d658f347d00ea5e091aa31f086b2a20Dake Gu if (hasFocus) { 72892181367d658f347d00ea5e091aa31f086b2a20Dake Gu wrapper.mShadowFocused.animate().alpha(1f) 73892181367d658f347d00ea5e091aa31f086b2a20Dake Gu .setDuration(DURATION_MS).start(); 74892181367d658f347d00ea5e091aa31f086b2a20Dake Gu wrapper.mShadowNormal.animate().alpha(0f) 75892181367d658f347d00ea5e091aa31f086b2a20Dake Gu .setDuration(DURATION_MS).start(); 76892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } else { 77892181367d658f347d00ea5e091aa31f086b2a20Dake Gu wrapper.mShadowFocused.animate().alpha(0f) 78892181367d658f347d00ea5e091aa31f086b2a20Dake Gu .setDuration(DURATION_MS).start(); 79892181367d658f347d00ea5e091aa31f086b2a20Dake Gu wrapper.mShadowNormal.animate().alpha(1f) 80892181367d658f347d00ea5e091aa31f086b2a20Dake Gu .setDuration(DURATION_MS).start(); 81892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 82892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 83892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 8447520b68e50572a9775a662410c5aff8300c8784Craig Stout } 8547520b68e50572a9775a662410c5aff8300c8784Craig Stout 8647520b68e50572a9775a662410c5aff8300c8784Craig Stout @Override 8762d36d44e03a3dd0632b156615b04563c62e83c1Dake Gu public void onItemFocused(View view, boolean hasFocus) { 8847520b68e50572a9775a662410c5aff8300c8784Craig Stout viewFocused(view, hasFocus); 8947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 9047520b68e50572a9775a662410c5aff8300c8784Craig Stout } 9147520b68e50572a9775a662410c5aff8300c8784Craig Stout 9255c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout private static HeaderItemFocusHighlight sHeaderItemFocusHighlight = 9355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout new HeaderItemFocusHighlight(); 9455c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 95a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn private static ActionItemFocusHighlight sActionItemFocusHighlight = 96a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn new ActionItemFocusHighlight(); 97a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 9847520b68e50572a9775a662410c5aff8300c8784Craig Stout /** 9947520b68e50572a9775a662410c5aff8300c8784Craig Stout * Setup the focus highlight behavior of a focused item in browse list row. 10047520b68e50572a9775a662410c5aff8300c8784Craig Stout * @param adapter adapter of the list row. 10147520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 102b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout public static void setupBrowseItemFocusHighlight(ItemBridgeAdapter adapter, int zoomIndex) { 103b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout adapter.setFocusHighlight(new BrowseItemFocusHighlight(zoomIndex)); 10447520b68e50572a9775a662410c5aff8300c8784Craig Stout } 10555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 10655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout /** 10755c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * Setup the focus highlight behavior of a focused item in header list. 10855c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * @param adapter adapter of the header list. 10955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout */ 11055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout public static void setupHeaderItemFocusHighlight(ItemBridgeAdapter adapter) { 11155c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout adapter.setFocusHighlight(sHeaderItemFocusHighlight); 11255c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 11355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 114a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn /** 115a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * Setup the focus highlight behavior of a focused item in an action list. 116a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * @param adapter adapter of the action list. 117a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn */ 118a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn public static void setupActionItemFocusHighlight(ItemBridgeAdapter adapter) { 119a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn adapter.setFocusHighlight(sActionItemFocusHighlight); 120a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 121a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 122a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn private static class HeaderItemFocusHighlight implements FocusHighlight { 12355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout private boolean mInitialized; 12455c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout private float mSelectScale; 12555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout private float mUnselectAlpha; 12655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout private int mDuration; 12755c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 12855c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout private void initializeDimensions(Resources res) { 12955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout if (!mInitialized) { 13055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout mSelectScale = 13155c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout Float.parseFloat(res.getString(R.dimen.lb_browse_header_select_scale)); 13255c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout mUnselectAlpha = 13355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout Float.parseFloat(res.getString(R.dimen.lb_browse_header_unselect_alpha)); 13455c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout mDuration = 13555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout Integer.parseInt(res.getString(R.dimen.lb_browse_header_select_duration)); 13655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout mInitialized = true; 13755c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 13855c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 13955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 14055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout private void viewFocused(View view, boolean hasFocus) { 14155c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout initializeDimensions(view.getResources()); 14255c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout if (hasFocus) { 14355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout view.animate().scaleX(mSelectScale).scaleY(mSelectScale) 14455c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout .alpha(1f) 14555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout .setDuration(mDuration); 14655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } else { 14755c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout view.animate().scaleX(1f).scaleY(1f) 14855c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout .alpha(mUnselectAlpha) 14955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout .setDuration(mDuration); 15055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 15155c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 15255c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 15355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout @Override 15462d36d44e03a3dd0632b156615b04563c62e83c1Dake Gu public void onItemFocused(View view, boolean hasFocus) { 15555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout viewFocused(view, hasFocus); 15655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 15755c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 158a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 159a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn private static class ActionItemFocusHighlight implements FocusHighlight { 160a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn private boolean mInitialized; 161a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn private int mDuration; 162a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 163a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn private void initializeDimensions(Resources res) { 164a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn if (!mInitialized) { 165a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn mDuration = Integer.parseInt(res.getString(R.dimen.lb_details_overview_action_select_duration)); 166a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 167a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 168a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 169a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn @Override 17062d36d44e03a3dd0632b156615b04563c62e83c1Dake Gu public void onItemFocused(View view, boolean hasFocus) { 171a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn initializeDimensions(view.getResources()); 172a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn TransitionDrawable td = (TransitionDrawable) view.getBackground(); 173a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn if (hasFocus) { 174a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn td.startTransition(mDuration); 175a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } else { 176a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn td.reverseTransition(mDuration); 177a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 178a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 179a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 18047520b68e50572a9775a662410c5aff8300c8784Craig Stout} 181