1 /* 2 * Copyright (C) 2016 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 17 package androidx.leanback.widget; 18 19 import static androidx.leanback.widget.BaseCardView.LayoutParams.MATCH_PARENT; 20 import static androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO; 21 import static androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN; 22 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertNull; 26 import static org.junit.Assert.assertTrue; 27 import static org.mockito.Matchers.any; 28 import static org.mockito.Mockito.times; 29 import static org.mockito.Mockito.verify; 30 31 import android.support.test.InstrumentationRegistry; 32 import android.support.test.filters.SmallTest; 33 import android.view.View; 34 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 import org.junit.runners.JUnit4; 38 import org.mockito.Mockito; 39 40 @SmallTest 41 @RunWith(JUnit4.class) 42 public class BaseCardViewTest { 43 44 BaseCardView.LayoutParams createLayoutParams(int viewType, int width, int height) { 45 BaseCardView.LayoutParams lp = new BaseCardView.LayoutParams(width, height); 46 lp.viewType = viewType; 47 return lp; 48 } 49 50 void mockInfoHeightAnimation(BaseCardView view, int width, int startHeight, int endHeight) { 51 ((BaseCardView.InfoHeightAnimation) view.getAnimation()).mockStart(); 52 measureAndLayout(view, width, startHeight); 53 ((BaseCardView.InfoHeightAnimation) view.getAnimation()).mockEnd(); 54 assertNull(view.getAnimation()); 55 measureAndLayout(view, width, endHeight); 56 } 57 58 void mockInfoAlphaAnimation(BaseCardView view, View infoView, 59 float startAlpha, float endAlpha) { 60 ((BaseCardView.InfoAlphaAnimation) view.getAnimation()).mockStart(); 61 assertEquals(startAlpha, infoView.getAlpha(), 0.01f); 62 assertEquals(View.VISIBLE, infoView.getVisibility()); 63 ((BaseCardView.InfoAlphaAnimation) view.getAnimation()).mockEnd(); 64 assertNull(view.getAnimation()); 65 assertEquals(endAlpha, infoView.getAlpha(), 0.01f); 66 assertEquals(endAlpha == 0f? View.GONE: View.VISIBLE, infoView.getVisibility()); 67 } 68 69 void measureAndLayout(View view, int expectedWidth, int expectedHeight) { 70 view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); 71 assertEquals(expectedWidth, view.getMeasuredWidth()); 72 assertEquals(expectedHeight, view.getMeasuredHeight()); 73 view.layout(0, 0, expectedWidth, expectedHeight); 74 } 75 76 void verifyLayoutTimes(View.OnLayoutChangeListener listener, int timesCalled) { 77 verify(listener, times(timesCalled)).onLayoutChange(any(View.class), 78 any(Integer.class), any(Integer.class), any(Integer.class), any(Integer.class), 79 any(Integer.class), any(Integer.class), any(Integer.class), any(Integer.class)); 80 } 81 82 @Test 83 public void infoOver_InfoVisibleAlways() { 84 BaseCardView cardView = new BaseCardView(InstrumentationRegistry.getContext()); 85 View main = new View(cardView.getContext()); 86 main.setLayoutParams(createLayoutParams(VIEW_TYPE_MAIN, 500, 500)); 87 cardView.addView(main); 88 View info = new View(cardView.getContext()); 89 View.OnLayoutChangeListener onLayout = Mockito.mock(View.OnLayoutChangeListener.class); 90 info.addOnLayoutChangeListener(onLayout); 91 info.setLayoutParams(createLayoutParams(VIEW_TYPE_INFO, MATCH_PARENT, 200)); 92 cardView.addView(info); 93 cardView.setCardType(BaseCardView.CARD_TYPE_INFO_OVER); 94 cardView.setInfoVisibility(BaseCardView.CARD_REGION_VISIBLE_ALWAYS); 95 96 measureAndLayout(cardView, 500, 500); 97 verifyLayoutTimes(onLayout, 1); 98 assertEquals(1f, info.getAlpha(), 0.01f); 99 100 cardView.setActivated(true); 101 assertFalse(cardView.isLayoutRequested()); 102 assertNull(cardView.getAnimation()); 103 measureAndLayout(cardView, 500, 500); 104 verifyLayoutTimes(onLayout, 1); 105 assertEquals(1f, info.getAlpha(), 0.01f); 106 107 cardView.setActivated(false); 108 assertFalse(cardView.isLayoutRequested()); 109 assertNull(cardView.getAnimation()); 110 measureAndLayout(cardView, 500, 500); 111 verifyLayoutTimes(onLayout, 1); 112 assertEquals(1f, info.getAlpha(), 0.01f); 113 114 cardView.setSelected(true); 115 assertFalse(cardView.isLayoutRequested()); 116 assertNull(cardView.getAnimation()); 117 measureAndLayout(cardView, 500, 500); 118 verifyLayoutTimes(onLayout, 1); 119 assertEquals(1f, info.getAlpha(), 0.01f); 120 121 cardView.setSelected(false); 122 assertFalse(cardView.isLayoutRequested()); 123 assertNull(cardView.getAnimation()); 124 measureAndLayout(cardView, 500, 500); 125 verifyLayoutTimes(onLayout, 1); 126 assertEquals(1f, info.getAlpha(), 0.01f); 127 } 128 129 @Test 130 public void infoUnder_InfoVisibleAlways() { 131 BaseCardView cardView = new BaseCardView(InstrumentationRegistry.getContext()); 132 View main = new View(cardView.getContext()); 133 main.setLayoutParams(createLayoutParams(VIEW_TYPE_MAIN, 500, 500)); 134 cardView.addView(main); 135 View info = new View(cardView.getContext()); 136 View.OnLayoutChangeListener onLayout = Mockito.mock(View.OnLayoutChangeListener.class); 137 info.addOnLayoutChangeListener(onLayout); 138 info.setLayoutParams(createLayoutParams(VIEW_TYPE_INFO, MATCH_PARENT, 200)); 139 cardView.addView(info); 140 cardView.setCardType(BaseCardView.CARD_TYPE_INFO_UNDER); 141 cardView.setInfoVisibility(BaseCardView.CARD_REGION_VISIBLE_ALWAYS); 142 143 measureAndLayout(cardView, 500, 700); 144 verifyLayoutTimes(onLayout, 1); 145 assertEquals(1f, info.getAlpha(), 0.01f); 146 147 cardView.setActivated(true); 148 assertFalse(cardView.isLayoutRequested()); 149 assertNull(cardView.getAnimation()); 150 measureAndLayout(cardView, 500, 700); 151 verifyLayoutTimes(onLayout, 1); 152 assertEquals(1f, info.getAlpha(), 0.01f); 153 154 cardView.setActivated(false); 155 assertFalse(cardView.isLayoutRequested()); 156 assertNull(cardView.getAnimation()); 157 measureAndLayout(cardView, 500, 700); 158 verifyLayoutTimes(onLayout, 1); 159 assertEquals(1f, info.getAlpha(), 0.01f); 160 161 cardView.setSelected(true); 162 assertFalse(cardView.isLayoutRequested()); 163 assertNull(cardView.getAnimation()); 164 measureAndLayout(cardView, 500, 700); 165 verifyLayoutTimes(onLayout, 1); 166 assertEquals(1f, info.getAlpha(), 0.01f); 167 168 cardView.setSelected(false); 169 assertFalse(cardView.isLayoutRequested()); 170 assertNull(cardView.getAnimation()); 171 measureAndLayout(cardView, 500, 700); 172 verifyLayoutTimes(onLayout, 1); 173 assertEquals(1f, info.getAlpha(), 0.01f); 174 } 175 176 @Test 177 public void infoUnder_InfoVisibleActivated() { 178 BaseCardView cardView = new BaseCardView(InstrumentationRegistry.getContext()); 179 View main = new View(cardView.getContext()); 180 main.setLayoutParams(createLayoutParams(VIEW_TYPE_MAIN, 500, 500)); 181 cardView.addView(main); 182 View info = new View(cardView.getContext()); 183 View.OnLayoutChangeListener onLayout = Mockito.mock(View.OnLayoutChangeListener.class); 184 info.addOnLayoutChangeListener(onLayout); 185 info.setLayoutParams(createLayoutParams(VIEW_TYPE_INFO, MATCH_PARENT, 200)); 186 cardView.addView(info); 187 cardView.setCardType(BaseCardView.CARD_TYPE_INFO_UNDER); 188 cardView.setInfoVisibility(BaseCardView.CARD_REGION_VISIBLE_ACTIVATED); 189 190 measureAndLayout(cardView, 500, 500); 191 verifyLayoutTimes(onLayout, 0); 192 assertEquals(1f, info.getAlpha(), 0.01f); 193 194 cardView.setActivated(true); 195 assertTrue(cardView.isLayoutRequested()); 196 measureAndLayout(cardView, 500, 700); 197 verifyLayoutTimes(onLayout, 1); 198 assertEquals(1f, info.getAlpha(), 0.01f); 199 200 cardView.setActivated(false); 201 assertTrue(cardView.isLayoutRequested()); 202 measureAndLayout(cardView, 500, 500); 203 verifyLayoutTimes(onLayout, 1); 204 assertEquals(1f, info.getAlpha(), 0.01f); 205 206 // changing selected does not affect size 207 cardView.setSelected(true); 208 assertFalse(cardView.isLayoutRequested()); 209 measureAndLayout(cardView, 500, 500); 210 verifyLayoutTimes(onLayout, 1); 211 assertEquals(1f, info.getAlpha(), 0.01f); 212 213 // changing selected does not affect size 214 cardView.setSelected(false); 215 assertFalse(cardView.isLayoutRequested()); 216 measureAndLayout(cardView, 500, 500); 217 verifyLayoutTimes(onLayout, 1); 218 assertEquals(1f, info.getAlpha(), 0.01f); 219 } 220 221 @Test 222 public void infoUnder_InfoVisibleSelected() { 223 final BaseCardView cardView = new BaseCardView(InstrumentationRegistry.getContext()); 224 View main = new View(cardView.getContext()); 225 main.setLayoutParams(createLayoutParams(VIEW_TYPE_MAIN, 500, 500)); 226 cardView.addView(main); 227 View info = new View(cardView.getContext()); 228 View.OnLayoutChangeListener onLayout = Mockito.mock(View.OnLayoutChangeListener.class); 229 info.addOnLayoutChangeListener(onLayout); 230 info.setLayoutParams(createLayoutParams(VIEW_TYPE_INFO, MATCH_PARENT, 200)); 231 cardView.addView(info); 232 cardView.setCardType(BaseCardView.CARD_TYPE_INFO_UNDER); 233 cardView.setInfoVisibility(BaseCardView.CARD_REGION_VISIBLE_SELECTED); 234 235 measureAndLayout(cardView, 500, 500); 236 verifyLayoutTimes(onLayout, 0); 237 assertEquals(1f, info.getAlpha(), 0.01f); 238 239 // changing activated does not affect size 240 cardView.setActivated(true); 241 measureAndLayout(cardView, 500, 500); 242 assertNull(cardView.getAnimation()); 243 assertEquals(1f, info.getAlpha(), 0.01f); 244 245 // start info height animation 500 -> 700 246 cardView.setSelected(true); 247 assertEquals(1f, info.getAlpha(), 0.01f); 248 mockInfoHeightAnimation(cardView, 500 /*width*/, 500 /*startHeight*/, 700 /*endHeight*/); 249 250 // changing activated does not affect size 251 cardView.setActivated(false); 252 assertEquals(1f, info.getAlpha(), 0.01f); 253 measureAndLayout(cardView, 500, 700); 254 assertNull(cardView.getAnimation()); 255 256 // start info height animation 700 -> 500 257 cardView.setSelected(false); 258 assertEquals(1f, info.getAlpha(), 0.01f); 259 mockInfoHeightAnimation(cardView, 500 /*width*/, 700 /*startHeight*/, 500 /*endHeight*/); 260 } 261 262 @Test 263 public void infoOver_InfoVisibleSelected() { 264 final BaseCardView cardView = new BaseCardView(InstrumentationRegistry.getContext()); 265 View main = new View(cardView.getContext()); 266 main.setLayoutParams(createLayoutParams(VIEW_TYPE_MAIN, 500, 500)); 267 cardView.addView(main); 268 View info = new View(cardView.getContext()); 269 View.OnLayoutChangeListener onLayout = Mockito.mock(View.OnLayoutChangeListener.class); 270 info.addOnLayoutChangeListener(onLayout); 271 info.setLayoutParams(createLayoutParams(VIEW_TYPE_INFO, MATCH_PARENT, 200)); 272 cardView.addView(info); 273 cardView.setCardType(BaseCardView.CARD_TYPE_INFO_OVER); 274 cardView.setInfoVisibility(BaseCardView.CARD_REGION_VISIBLE_SELECTED); 275 276 measureAndLayout(cardView, 500, 500); 277 verifyLayoutTimes(onLayout, 0); 278 assertFalse(cardView.isSelected()); 279 assertFalse(cardView.isActivated()); 280 assertEquals(0f, info.getAlpha(), 0.01f); 281 282 cardView.setActivated(true); 283 assertFalse(cardView.isLayoutRequested()); 284 assertNull(cardView.getAnimation()); 285 286 assertEquals(info.getVisibility(), View.GONE); 287 assertEquals(0f, info.getAlpha(), 0.01f); 288 // start info animation alpha 0f -> 1f 289 cardView.setSelected(true); 290 // change visibility when start animation causing layout requested 291 assertTrue(cardView.isLayoutRequested()); 292 measureAndLayout(cardView, 500, 500); 293 mockInfoAlphaAnimation(cardView, info, 0f, 1f); 294 assertEquals(1f, info.getAlpha(), 0.01f); 295 296 // start info animation alpha 1f -> 0f 297 cardView.setSelected(false); 298 assertFalse(cardView.isLayoutRequested()); 299 mockInfoAlphaAnimation(cardView, info, 1f, 0f); 300 assertEquals(0f, info.getAlpha(), 0.01f); 301 } 302 303 } 304