1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.support.v17.leanback.widget; 17 18 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; 19 20 import android.content.Context; 21 import android.graphics.Bitmap; 22 import android.support.annotation.RestrictTo; 23 import android.util.AttributeSet; 24 import android.util.SparseArray; 25 import android.view.View; 26 import android.view.ViewGroup; 27 import android.widget.ImageView; 28 import android.widget.LinearLayout; 29 30 /** 31 * @hide 32 */ 33 @RestrictTo(LIBRARY_GROUP) 34 public class ThumbsBar extends LinearLayout { 35 36 static final int DEFAULT_NUM_OF_THUMBS = 7; 37 38 int mMinimalMargin = 16; 39 int mNumOfThumbs; 40 int mThumbWidth = 160; 41 int mThumbHeight = 160; 42 int mHeroThumbWidth = 240; 43 int mHeroThumbHeight = 240; 44 int mMeasuredMargin; 45 final SparseArray<Bitmap> mBitmaps = new SparseArray<>(); 46 47 public ThumbsBar(Context context, AttributeSet attrs) { 48 this(context, attrs, 0); 49 } 50 51 public ThumbsBar(Context context, AttributeSet attrs, int defStyle) { 52 super(context, attrs, defStyle); 53 setNumberOfThumbs(DEFAULT_NUM_OF_THUMBS); 54 } 55 56 /** 57 * Get hero index which is the middle child. 58 */ 59 public int getHeroIndex() { 60 return getChildCount() / 2; 61 } 62 63 /** 64 * Set size of thumb view in pixels 65 */ 66 public void setThumbSize(int width, int height) { 67 mThumbHeight = height; 68 mThumbWidth = width; 69 int heroIndex = getHeroIndex(); 70 for (int i = 0; i < getChildCount(); i++) { 71 if (heroIndex != i) { 72 View child = getChildAt(i); 73 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); 74 boolean changed = false; 75 if (lp.height != height) { 76 lp.height = height; 77 changed = true; 78 } 79 if (lp.width != width) { 80 lp.width = width; 81 changed = true; 82 } 83 if (changed) { 84 child.setLayoutParams(lp); 85 } 86 } 87 } 88 } 89 90 /** 91 * Set size of hero thumb view in pixels, it is usually larger than other thumbs. 92 */ 93 public void setHeroThumbSize(int width, int height) { 94 mHeroThumbHeight = height; 95 mHeroThumbWidth = width; 96 int heroIndex = getHeroIndex(); 97 for (int i = 0; i < getChildCount(); i++) { 98 if (heroIndex == i) { 99 View child = getChildAt(i); 100 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); 101 boolean changed = false; 102 if (lp.height != height) { 103 lp.height = height; 104 changed = true; 105 } 106 if (lp.width != width) { 107 lp.width = width; 108 changed = true; 109 } 110 if (changed) { 111 child.setLayoutParams(lp); 112 } 113 } 114 } 115 } 116 117 /** 118 * Set number of thumb views. It must be odd or it will be increasing one. 119 */ 120 public void setNumberOfThumbs(int numOfThumbs) { 121 if (numOfThumbs < 0) { 122 throw new IllegalArgumentException(); 123 } 124 if ((numOfThumbs & 1) == 0) { 125 // make it odd number 126 numOfThumbs++; 127 } 128 mNumOfThumbs = numOfThumbs; 129 while (getChildCount() > mNumOfThumbs) { 130 removeView(getChildAt(getChildCount() - 1)); 131 } 132 while (getChildCount() < mNumOfThumbs) { 133 View view = createThumbView(this); 134 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(mThumbWidth, mThumbHeight); 135 addView(view, lp); 136 } 137 int heroIndex = getHeroIndex(); 138 for (int i = 0; i < getChildCount(); i++) { 139 View child = getChildAt(i); 140 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); 141 if (heroIndex == i) { 142 lp.width = mHeroThumbWidth; 143 lp.height = mHeroThumbHeight; 144 } else { 145 lp.width = mThumbWidth; 146 lp.height = mThumbHeight; 147 } 148 child.setLayoutParams(lp); 149 } 150 } 151 152 @Override 153 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 154 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 155 int width = getMeasuredWidth(); 156 int spaceForMargin = 0; 157 while (mNumOfThumbs > 1) { 158 spaceForMargin = width - mHeroThumbWidth - mThumbWidth * (mNumOfThumbs - 1); 159 if (spaceForMargin < mMinimalMargin * (mNumOfThumbs - 1)) { 160 setNumberOfThumbs(mNumOfThumbs - 2); 161 } else { 162 break; 163 } 164 } 165 mMeasuredMargin = mNumOfThumbs > 0 ? spaceForMargin / (mNumOfThumbs - 1) : 0; 166 } 167 168 @Override 169 protected void onLayout(boolean changed, int l, int t, int r, int b) { 170 super.onLayout(changed, l, t, r, b); 171 int heroIndex = getHeroIndex(); 172 View heroView = getChildAt(heroIndex); 173 int heroLeft = getWidth() / 2 - heroView.getMeasuredWidth() / 2; 174 int heroRight = getWidth() / 2 + heroView.getMeasuredWidth() / 2; 175 heroView.layout(heroLeft, getPaddingTop(), heroRight, 176 getPaddingTop() + heroView.getMeasuredHeight()); 177 int heroCenter = getPaddingTop() + heroView.getMeasuredHeight() / 2; 178 179 for (int i = heroIndex - 1; i >= 0; i--) { 180 heroLeft -= mMeasuredMargin; 181 View child = getChildAt(i); 182 child.layout(heroLeft - child.getMeasuredWidth(), 183 heroCenter - child.getMeasuredHeight() / 2, 184 heroLeft, 185 heroCenter + child.getMeasuredHeight() / 2); 186 heroLeft -= child.getMeasuredWidth(); 187 } 188 for (int i = heroIndex + 1; i < mNumOfThumbs; i++) { 189 heroRight += mMeasuredMargin; 190 View child = getChildAt(i); 191 child.layout(heroRight, 192 heroCenter - child.getMeasuredHeight() / 2, 193 heroRight + child.getMeasuredWidth(), 194 heroCenter + child.getMeasuredHeight() / 2); 195 heroRight += child.getMeasuredWidth(); 196 } 197 } 198 199 /** 200 * Create a thumb view, it's by default a ImageView. 201 */ 202 protected View createThumbView(ViewGroup parent) { 203 return new ImageView(parent.getContext()); 204 } 205 206 /** 207 * Clear all thumb bitmaps set on thumb views. 208 */ 209 public void clearThumbBitmaps() { 210 for (int i = 0; i < getChildCount(); i++) { 211 setThumbBitmap(i, null); 212 } 213 mBitmaps.clear(); 214 } 215 216 217 /** 218 * Get bitmap of given child index. 219 */ 220 public Bitmap getThumbBitmap(int index) { 221 return mBitmaps.get(index); 222 } 223 224 /** 225 * Set thumb bitmap for a given index of child. 226 */ 227 public void setThumbBitmap(int index, Bitmap bitmap) { 228 mBitmaps.put(index, bitmap); 229 ((ImageView) getChildAt(index)).setImageBitmap(bitmap); 230 } 231 } 232