13bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu/* 23bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Copyright (C) 2017 The Android Open Source Project 33bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 43bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Licensed under the Apache License, Version 2.0 (the "License"); 53bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * you may not use this file except in compliance with the License. 63bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * You may obtain a copy of the License at 73bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 83bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * http://www.apache.org/licenses/LICENSE-2.0 93bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Unless required by applicable law or agreed to in writing, software 113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * distributed under the License is distributed on an "AS IS" BASIS, 123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * See the License for the specific language governing permissions and 143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * limitations under the License. 153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.widget; 173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 18ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 203bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.content.Context; 213bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.graphics.Bitmap; 223bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.util.AttributeSet; 233bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.util.SparseArray; 243bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.View; 253bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.ViewGroup; 263bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.widget.ImageView; 273bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.widget.LinearLayout; 283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 298619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.annotation.RestrictTo; 308619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.R; 318619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas 323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu/** 333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @hide 343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu@RestrictTo(LIBRARY_GROUP) 363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gupublic class ThumbsBar extends LinearLayout { 373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 38e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // initial value for Thumb's number before measuring the screen size 39e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli int mNumOfThumbs = -1; 40e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli int mThumbWidthInPixel; 41e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli int mThumbHeightInPixel; 42e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli int mHeroThumbWidthInPixel; 43e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli int mHeroThumbHeightInPixel; 44e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli int mMeasuredMarginInPixel; 453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final SparseArray<Bitmap> mBitmaps = new SparseArray<>(); 463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 47e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // flag to determine if the number of thumbs in thumbs bar is set by user through 48e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // setNumberofThumbs API or auto-calculated according to android tv design spec. 49e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli private boolean mIsUserSets = false; 50e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli 513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public ThumbsBar(Context context, AttributeSet attrs) { 523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu this(context, attrs, 0); 533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public ThumbsBar(Context context, AttributeSet attrs, int defStyle) { 563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu super(context, attrs, defStyle); 57e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // According to the spec, 58e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // the width of non-hero thumb should be 80% of HeroThumb's Width, i.e. 0.8 * 192dp = 154dp 59e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mThumbWidthInPixel = context.getResources().getDimensionPixelSize( 60e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli R.dimen.lb_playback_transport_thumbs_width); 61e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mThumbHeightInPixel = context.getResources().getDimensionPixelSize( 62e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli R.dimen.lb_playback_transport_thumbs_height); 63e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // According to the spec, the width of HeroThumb should be 192dp 64e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mHeroThumbHeightInPixel = context.getResources().getDimensionPixelSize( 65e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli R.dimen.lb_playback_transport_hero_thumbs_width); 66e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mHeroThumbWidthInPixel = context.getResources().getDimensionPixelSize( 67e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli R.dimen.lb_playback_transport_hero_thumbs_height); 68e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // According to the spec, the margin between thumbs to be 4dp 69e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mMeasuredMarginInPixel = context.getResources().getDimensionPixelSize( 70e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli R.dimen.lb_playback_transport_thumbs_margin); 713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Get hero index which is the middle child. 753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public int getHeroIndex() { 773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return getChildCount() / 2; 783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Set size of thumb view in pixels 823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setThumbSize(int width, int height) { 84e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mThumbHeightInPixel = height; 85e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mThumbWidthInPixel = width; 863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int heroIndex = getHeroIndex(); 873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = 0; i < getChildCount(); i++) { 883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (heroIndex != i) { 893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu View child = getChildAt(i); 903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); 913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean changed = false; 923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (lp.height != height) { 933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu lp.height = height; 943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu changed = true; 953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (lp.width != width) { 973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu lp.width = width; 983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu changed = true; 993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (changed) { 1013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu child.setLayoutParams(lp); 1023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 1083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Set size of hero thumb view in pixels, it is usually larger than other thumbs. 1093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 1103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setHeroThumbSize(int width, int height) { 111e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mHeroThumbHeightInPixel = height; 112e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mHeroThumbWidthInPixel = width; 1133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int heroIndex = getHeroIndex(); 1143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = 0; i < getChildCount(); i++) { 1153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (heroIndex == i) { 1163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu View child = getChildAt(i); 1173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); 1183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean changed = false; 1193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (lp.height != height) { 1203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu lp.height = height; 1213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu changed = true; 1223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (lp.width != width) { 1243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu lp.width = width; 1253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu changed = true; 1263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (changed) { 1283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu child.setLayoutParams(lp); 1293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 135e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * Set the space between thumbs in pixels 136e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli */ 137e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli public void setThumbSpace(int spaceInPixel) { 138e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mMeasuredMarginInPixel = spaceInPixel; 139e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli requestLayout(); 140e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli } 141e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli 142e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli /** 143e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * Set number of thumb views. 1443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 1453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setNumberOfThumbs(int numOfThumbs) { 146e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mIsUserSets = true; 1473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mNumOfThumbs = numOfThumbs; 148e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli setNumberOfThumbsInternal(); 149e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli } 150e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli 151e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli /** 152e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * Helper function for setNumberOfThumbs. 153e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * Will Update the layout settings in ThumbsBar based on mNumOfThumbs 154e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli */ 155e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli private void setNumberOfThumbsInternal() { 1563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu while (getChildCount() > mNumOfThumbs) { 1573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu removeView(getChildAt(getChildCount() - 1)); 1583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu while (getChildCount() < mNumOfThumbs) { 1603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu View view = createThumbView(this); 161e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(mThumbWidthInPixel, 162e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mThumbHeightInPixel); 1633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu addView(view, lp); 1643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int heroIndex = getHeroIndex(); 1663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = 0; i < getChildCount(); i++) { 1673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu View child = getChildAt(i); 1683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); 1693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (heroIndex == i) { 170e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli lp.width = mHeroThumbWidthInPixel; 171e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli lp.height = mHeroThumbHeightInPixel; 1723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 173e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli lp.width = mThumbWidthInPixel; 174e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli lp.height = mThumbHeightInPixel; 1753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu child.setLayoutParams(lp); 1773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1806c41fe6074ffc9d1b472032e5356a7b5e146dc83Dake Gu private static int roundUp(int num, int divisor) { 1816c41fe6074ffc9d1b472032e5356a7b5e146dc83Dake Gu return (num + divisor - 1) / divisor; 1826c41fe6074ffc9d1b472032e5356a7b5e146dc83Dake Gu } 1836c41fe6074ffc9d1b472032e5356a7b5e146dc83Dake Gu 184e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli /** 185e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * Helper function to compute how many thumbs should be put in the screen 186e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * Assume we should put x's non-hero thumbs in the screen, the equation should be 187e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * 192dp (width of hero thumbs) + 188e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * 154dp (width of common thumbs) * x + 189e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * 4dp (width of the margin between thumbs) * x 190e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * = width 191e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * So the calculated number of non-hero thumbs should be (width - 192dp) / 158dp. 192e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * If the calculated number of non-hero thumbs is less than 2, it will be updated to 2 193e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * or if the calculated number or non-hero thumbs is not an even number, it will be 194e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * decremented by one. 195e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * This processing is used to make sure the arrangement of non-hero thumbs 196e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * in ThumbsBar is symmetrical. 197e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * Also there should be a hero thumb in the middle of the ThumbsBar, 198e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * the final result should be non-hero thumbs (after processing) + 1. 199e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * 200e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * @param widthInPixel measured width in pixel 201e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli * @return The number of thumbs 202e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli */ 203e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli private int calculateNumOfThumbs(int widthInPixel) { 2046c41fe6074ffc9d1b472032e5356a7b5e146dc83Dake Gu int nonHeroThumbNum = roundUp(widthInPixel - mHeroThumbWidthInPixel, 2056c41fe6074ffc9d1b472032e5356a7b5e146dc83Dake Gu mThumbWidthInPixel + mMeasuredMarginInPixel); 206e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli if (nonHeroThumbNum < 2) { 207e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // If the calculated number of non-hero thumbs is less than 2, 208e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // it will be updated to 2 209e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli nonHeroThumbNum = 2; 210e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli } else if ((nonHeroThumbNum & 1) != 0) { 211e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // If the calculated number or non-hero thumbs is not an even number, 2126c41fe6074ffc9d1b472032e5356a7b5e146dc83Dake Gu // it will be increased by one. 2136c41fe6074ffc9d1b472032e5356a7b5e146dc83Dake Gu nonHeroThumbNum++; 214e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli } 215e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // Count Hero Thumb to the final result 216e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli return nonHeroThumbNum + 1; 217e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli } 218e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli 2193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 2213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu super.onMeasure(widthMeasureSpec, heightMeasureSpec); 2223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int width = getMeasuredWidth(); 223e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // If the number of thumbs in ThumbsBar is not set by user explicitly, it will be 224e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // recalculated based on Android TV Design Spec 225e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli if (!mIsUserSets) { 226e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli int numOfThumbs = calculateNumOfThumbs(width); 227e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli // Set new number of thumbs when calculation result is different with current number 228e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli if (mNumOfThumbs != numOfThumbs) { 229e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli mNumOfThumbs = numOfThumbs; 230e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli setNumberOfThumbsInternal(); 2313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onLayout(boolean changed, int l, int t, int r, int b) { 2373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu super.onLayout(changed, l, t, r, b); 2383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int heroIndex = getHeroIndex(); 2393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu View heroView = getChildAt(heroIndex); 2403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int heroLeft = getWidth() / 2 - heroView.getMeasuredWidth() / 2; 2413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int heroRight = getWidth() / 2 + heroView.getMeasuredWidth() / 2; 2423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu heroView.layout(heroLeft, getPaddingTop(), heroRight, 2433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getPaddingTop() + heroView.getMeasuredHeight()); 2443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int heroCenter = getPaddingTop() + heroView.getMeasuredHeight() / 2; 2453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = heroIndex - 1; i >= 0; i--) { 247e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli heroLeft -= mMeasuredMarginInPixel; 2483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu View child = getChildAt(i); 2493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu child.layout(heroLeft - child.getMeasuredWidth(), 2503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu heroCenter - child.getMeasuredHeight() / 2, 2513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu heroLeft, 2523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu heroCenter + child.getMeasuredHeight() / 2); 2533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu heroLeft -= child.getMeasuredWidth(); 2543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = heroIndex + 1; i < mNumOfThumbs; i++) { 256e4662073e39ea860efbe9dfe4766e46b2945aee7jingjiangli heroRight += mMeasuredMarginInPixel; 2573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu View child = getChildAt(i); 2583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu child.layout(heroRight, 2593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu heroCenter - child.getMeasuredHeight() / 2, 2603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu heroRight + child.getMeasuredWidth(), 2613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu heroCenter + child.getMeasuredHeight() / 2); 2623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu heroRight += child.getMeasuredWidth(); 2633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 2673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Create a thumb view, it's by default a ImageView. 2683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 2693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected View createThumbView(ViewGroup parent) { 2703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return new ImageView(parent.getContext()); 2713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 2743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Clear all thumb bitmaps set on thumb views. 2753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 2763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void clearThumbBitmaps() { 2773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = 0; i < getChildCount(); i++) { 2783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu setThumbBitmap(i, null); 2793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mBitmaps.clear(); 2813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 2853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Get bitmap of given child index. 2863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 2873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public Bitmap getThumbBitmap(int index) { 2883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mBitmaps.get(index); 2893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 2923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Set thumb bitmap for a given index of child. 2933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 2943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setThumbBitmap(int index, Bitmap bitmap) { 2953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mBitmaps.put(index, bitmap); 2963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ((ImageView) getChildAt(index)).setImageBitmap(bitmap); 2973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu} 299