FocusHighlightHelper.java revision b55f0880c367c0b7e4132e7d954b60725e01e0b2
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package android.support.v17.leanback.widget;
15
16import android.graphics.drawable.TransitionDrawable;
17import android.support.v17.leanback.R;
18import android.view.View;
19import android.content.res.Resources;
20
21import static android.support.v17.leanback.widget.FocusHighlight.ZOOM_FACTOR_NONE;
22import static android.support.v17.leanback.widget.FocusHighlight.ZOOM_FACTOR_SMALL;
23import static android.support.v17.leanback.widget.FocusHighlight.ZOOM_FACTOR_MEDIUM;
24import static android.support.v17.leanback.widget.FocusHighlight.ZOOM_FACTOR_LARGE;
25
26
27/**
28 * Setup the behavior how to highlight when a item gains focus.
29 */
30public class FocusHighlightHelper {
31
32    static class BrowseItemFocusHighlight implements FocusHighlight {
33        private static final int DURATION_MS = 150;
34
35        private static float[] sScaleFactor = new float[4];
36
37        private int mScaleIndex;
38
39        BrowseItemFocusHighlight(int zoomIndex) {
40            mScaleIndex = (zoomIndex >= 0 && zoomIndex < sScaleFactor.length) ?
41                    zoomIndex : ZOOM_FACTOR_MEDIUM;
42        }
43
44        private void lazyInit(Resources resources) {
45            if (sScaleFactor[ZOOM_FACTOR_NONE] == 0f) {
46                sScaleFactor[ZOOM_FACTOR_NONE] = 1f;
47                sScaleFactor[ZOOM_FACTOR_SMALL] =
48                        resources.getFraction(R.fraction.lb_focus_zoom_factor_small, 1, 1);
49                sScaleFactor[ZOOM_FACTOR_MEDIUM] =
50                        resources.getFraction(R.fraction.lb_focus_zoom_factor_medium, 1, 1);
51                sScaleFactor[ZOOM_FACTOR_LARGE] =
52                        resources.getFraction(R.fraction.lb_focus_zoom_factor_large, 1, 1);
53            }
54        }
55
56        private float getScale(View view) {
57            lazyInit(view.getResources());
58            return sScaleFactor[mScaleIndex];
59        }
60
61        private void viewFocused(View view, boolean hasFocus) {
62            view.setSelected(hasFocus);
63            if (hasFocus) {
64                final float scale = getScale(view);
65                view.animate().scaleX(scale).scaleY(scale).setDuration(DURATION_MS);
66            } else {
67                view.animate().scaleX(1f).scaleY(1f).setDuration(DURATION_MS);
68            }
69            if (view instanceof ListRowCardWrapper) {
70                ListRowCardWrapper wrapper = (ListRowCardWrapper) view;
71                if (wrapper.mShadowNormal != null) {
72                    if (hasFocus) {
73                        wrapper.mShadowFocused.animate().alpha(1f)
74                                .setDuration(DURATION_MS).start();
75                        wrapper.mShadowNormal.animate().alpha(0f)
76                                .setDuration(DURATION_MS).start();
77                    } else {
78                        wrapper.mShadowFocused.animate().alpha(0f)
79                                .setDuration(DURATION_MS).start();
80                        wrapper.mShadowNormal.animate().alpha(1f)
81                                .setDuration(DURATION_MS).start();
82                    }
83                }
84            }
85        }
86
87        @Override
88        public void onItemFocused(View view, boolean hasFocus) {
89            viewFocused(view, hasFocus);
90        }
91    }
92
93    private static HeaderItemFocusHighlight sHeaderItemFocusHighlight =
94            new HeaderItemFocusHighlight();
95
96    private static ActionItemFocusHighlight sActionItemFocusHighlight =
97            new ActionItemFocusHighlight();
98
99    /**
100     * Setup the focus highlight behavior of a focused item in browse list row.
101     * @param adapter  adapter of the list row.
102     */
103    public static void setupBrowseItemFocusHighlight(ItemBridgeAdapter adapter, int zoomIndex) {
104        adapter.setFocusHighlight(new BrowseItemFocusHighlight(zoomIndex));
105    }
106
107    /**
108     * Setup the focus highlight behavior of a focused item in header list.
109     * @param adapter  adapter of the header list.
110     */
111    public static void setupHeaderItemFocusHighlight(ItemBridgeAdapter adapter) {
112        adapter.setFocusHighlight(sHeaderItemFocusHighlight);
113    }
114
115    /**
116     * Setup the focus highlight behavior of a focused item in an action list.
117     * @param adapter  adapter of the action list.
118     */
119    public static void setupActionItemFocusHighlight(ItemBridgeAdapter adapter) {
120        adapter.setFocusHighlight(sActionItemFocusHighlight);
121    }
122
123    private static class HeaderItemFocusHighlight implements FocusHighlight {
124        private boolean mInitialized;
125        private float mSelectScale;
126        private float mUnselectAlpha;
127        private int mDuration;
128
129        private void initializeDimensions(Resources res) {
130            if (!mInitialized) {
131                mSelectScale =
132                        Float.parseFloat(res.getString(R.dimen.lb_browse_header_select_scale));
133                mUnselectAlpha =
134                        Float.parseFloat(res.getString(R.dimen.lb_browse_header_unselect_alpha));
135                mDuration =
136                        Integer.parseInt(res.getString(R.dimen.lb_browse_header_select_duration));
137                mInitialized = true;
138            }
139        }
140
141        private void viewFocused(View view, boolean hasFocus) {
142            initializeDimensions(view.getResources());
143            if (hasFocus) {
144                view.animate().scaleX(mSelectScale).scaleY(mSelectScale)
145                        .alpha(1f)
146                        .setDuration(mDuration);
147            } else {
148                view.animate().scaleX(1f).scaleY(1f)
149                        .alpha(mUnselectAlpha)
150                        .setDuration(mDuration);
151            }
152        }
153
154        @Override
155        public void onItemFocused(View view, boolean hasFocus) {
156            viewFocused(view, hasFocus);
157        }
158    }
159
160    private static class ActionItemFocusHighlight implements FocusHighlight {
161        private boolean mInitialized;
162        private int mDuration;
163
164        private void initializeDimensions(Resources res) {
165            if (!mInitialized) {
166                mDuration = Integer.parseInt(res.getString(R.dimen.lb_details_overview_action_select_duration));
167            }
168        }
169
170        @Override
171        public void onItemFocused(View view, boolean hasFocus) {
172            initializeDimensions(view.getResources());
173            TransitionDrawable td = (TransitionDrawable) view.getBackground();
174            if (hasFocus) {
175                td.startTransition(mDuration);
176            } else {
177                td.reverseTransition(mDuration);
178            }
179        }
180    }
181}
182