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 17 package android.graphics.drawable.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertTrue; 23 24 import android.content.Context; 25 import android.content.res.ColorStateList; 26 import android.content.res.Resources; 27 import android.graphics.Bitmap; 28 import android.graphics.Bitmap.Config; 29 import android.graphics.BitmapFactory; 30 import android.graphics.NinePatch; 31 import android.graphics.Picture; 32 import android.graphics.cts.R; 33 import android.graphics.drawable.BitmapDrawable; 34 import android.graphics.drawable.ColorDrawable; 35 import android.graphics.drawable.Drawable; 36 import android.graphics.drawable.DrawableContainer; 37 import android.graphics.drawable.DrawableContainer.DrawableContainerState; 38 import android.graphics.drawable.GradientDrawable; 39 import android.graphics.drawable.LevelListDrawable; 40 import android.graphics.drawable.NinePatchDrawable; 41 import android.graphics.drawable.PaintDrawable; 42 import android.graphics.drawable.PictureDrawable; 43 import android.graphics.drawable.RippleDrawable; 44 import android.graphics.drawable.ShapeDrawable; 45 import android.graphics.drawable.StateListDrawable; 46 import android.graphics.drawable.shapes.RectShape; 47 import android.support.test.InstrumentationRegistry; 48 import android.support.test.annotation.UiThreadTest; 49 import android.support.test.filters.SmallTest; 50 import android.support.test.runner.AndroidJUnit4; 51 import android.util.StateSet; 52 53 import org.junit.Before; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 57 @SmallTest 58 @RunWith(AndroidJUnit4.class) 59 public class DefaultFocusHighlightTest { 60 61 // The target context. 62 private Context mContext; 63 64 @Before 65 public void setup() { 66 mContext = InstrumentationRegistry.getTargetContext(); 67 } 68 69 private static final int A_COLOR = 0x920424; 70 private static final int[] NO_STATE_FOCUSED = new int[] { android.R.attr.state_enabled }; 71 private static final int[] ONLY_STATE_FOCUSED = new int[] { android.R.attr.state_focused }; 72 private static final int[] STATE_FOCUSED_WITH_POS = 73 new int[] { android.R.attr.state_focused, android.R.attr.state_hovered }; 74 private static final int[] STATE_FOCUSED_WITH_NEG = 75 new int[] { android.R.attr.state_focused, -android.R.attr.state_hovered }; 76 private static final int[] STATE_FOCUSED_WITH_ENABLED = 77 new int[] { android.R.attr.state_focused, android.R.attr.state_enabled }; 78 79 final static int[] FOCUSED_STATE = 80 new int[] { android.R.attr.state_focused, android.R.attr.state_enabled }; 81 82 @UiThreadTest 83 @Test 84 public void testStateListDrawable() { 85 Drawable d; 86 // Empty state spec 87 d = DrawableFactory.createStateListDrawable( 88 new int[][] {} 89 ); 90 d.setState(FOCUSED_STATE); 91 assertFalse(d.hasFocusStateSpecified()); 92 93 // Wild card 94 d = DrawableFactory.createStateListDrawable( 95 new int[][] { StateSet.WILD_CARD } 96 ); 97 d.setState(FOCUSED_STATE); 98 assertFalse(d.hasFocusStateSpecified()); 99 100 // No state spec of state_focused=true 101 d = DrawableFactory.createStateListDrawable( 102 new int[][] { NO_STATE_FOCUSED } 103 ); 104 d.setState(FOCUSED_STATE); 105 assertFalse(d.hasFocusStateSpecified()); 106 107 // One state spec of only state_focused=true 108 d = DrawableFactory.createStateListDrawable( 109 new int[][] { ONLY_STATE_FOCUSED } 110 ); 111 d.setState(FOCUSED_STATE); 112 assertTrue(d.hasFocusStateSpecified()); 113 114 // One state spec of state_focused=true and something=true, but no state spec of 115 // state_focused=true and something=false (something is not enabled) 116 d = DrawableFactory.createStateListDrawable( 117 new int[][] { STATE_FOCUSED_WITH_POS } 118 ); 119 d.setState(FOCUSED_STATE); 120 assertTrue(d.hasFocusStateSpecified()); 121 122 // One state spec of state_focused=true and something=true, and one spec of 123 // state_focused=true and something=false (something is not enabled) 124 d = DrawableFactory.createStateListDrawable( 125 new int[][] { STATE_FOCUSED_WITH_POS, STATE_FOCUSED_WITH_NEG } 126 ); 127 d.setState(FOCUSED_STATE); 128 assertTrue(d.hasFocusStateSpecified()); 129 130 // One state spec of state_focused=true and enabled=true 131 d = DrawableFactory.createStateListDrawable( 132 new int[][] { STATE_FOCUSED_WITH_ENABLED } 133 ); 134 d.setState(FOCUSED_STATE); 135 assertTrue(d.hasFocusStateSpecified()); 136 } 137 138 @UiThreadTest 139 @Test 140 public void testRippleDrawable() { 141 Drawable d = DrawableFactory.createRippleDrawable(); 142 d.setState(FOCUSED_STATE); 143 assertTrue(d.hasFocusStateSpecified()); 144 } 145 146 @UiThreadTest 147 @Test 148 public void testPictureDrawable() { 149 Drawable d = DrawableFactory.createPictureDrawable(null); 150 d.setState(FOCUSED_STATE); 151 assertFalse(d.hasFocusStateSpecified()); 152 153 d = DrawableFactory.createPictureDrawable(new Picture()); 154 d.setState(FOCUSED_STATE); 155 assertFalse(d.hasFocusStateSpecified()); 156 } 157 158 @UiThreadTest 159 @Test 160 public void testColorStateListHandledDrawable() { 161 final Drawable[] drawables = new Drawable[] { 162 DrawableFactory.createShapeDrawable(), 163 DrawableFactory.createPaintDrawable(), 164 DrawableFactory.createBitmapDrawable(mContext), 165 DrawableFactory.createColorDrawable(), 166 DrawableFactory.createGradientDrawable(), 167 DrawableFactory.createNinePatchDrawable(mContext), 168 }; 169 final ColorStateList[] stateLists = new ColorStateList[] { 170 // Empty state spec 171 new ColorStateList( 172 new int[][] { }, 173 new int[] { }), 174 // Wild card 175 new ColorStateList( 176 new int[][] { StateSet.WILD_CARD }, 177 new int[] { A_COLOR }), 178 // No state spec of state_focused=true 179 new ColorStateList( 180 new int[][] { NO_STATE_FOCUSED }, 181 new int[] { A_COLOR }), 182 // One state spec of only state_focused=true 183 new ColorStateList( 184 new int[][] { ONLY_STATE_FOCUSED }, 185 new int[] { A_COLOR }), 186 // One state spec of state_focused=true and something=true, 187 // but no state spec of state_focused=true and something=false 188 new ColorStateList( 189 new int[][] { STATE_FOCUSED_WITH_POS }, 190 new int[] { A_COLOR }), 191 // One state spec of state_focused=true and something=true, 192 // and one spec of state_focused=true and something=false 193 new ColorStateList( 194 new int[][] { STATE_FOCUSED_WITH_POS, STATE_FOCUSED_WITH_NEG }, 195 new int[] { A_COLOR, A_COLOR }), 196 }; 197 final boolean[] expectedResults = new boolean[] { 198 // Empty state spec 199 false, 200 // Wild card 201 false, 202 // No state spec of state_focused=true 203 false, 204 // One state spec of only state_focused=true 205 true, 206 // One state spec of state_focused=true and something=true, 207 // but no state spec of state_focused=true and something=false 208 true, 209 // One state spec of state_focused=true and something=true, 210 // and one spec of state_focused=true and something=false 211 true 212 }; 213 assertEquals(stateLists.length, expectedResults.length); 214 for (Drawable drawable : drawables) { 215 // No ColorStateList set 216 String drawableName = drawable.getClass().toString(); 217 String errorMsg = "[" + drawableName + "] Testing no ColorStateList failed."; 218 drawable.setState(FOCUSED_STATE); 219 assertFalse(errorMsg, drawable.hasFocusStateSpecified()); 220 // With ColorStateList set 221 for (int i = 0; i < stateLists.length; i++) { 222 ColorStateList stateList = stateLists[i]; 223 boolean expectedResult = expectedResults[i]; 224 drawable.setTintList(stateList); 225 errorMsg = "[" + drawableName + "] Testing ColorStateList No." + i + " failed."; 226 227 drawable.setState(FOCUSED_STATE); 228 if (expectedResult) { 229 assertTrue(errorMsg, drawable.hasFocusStateSpecified()); 230 } else { 231 assertFalse(errorMsg, drawable.hasFocusStateSpecified()); 232 } 233 } 234 } 235 } 236 237 @UiThreadTest 238 @Test 239 public void testDrawableContainer() { 240 MockDrawableContainer container; 241 DrawableContainerState containerState; 242 243 // Empty 244 container = new MockDrawableContainer(); 245 containerState = (DrawableContainerState) new LevelListDrawable().getConstantState(); 246 assertNotNull(containerState); 247 container.setConstantState(containerState); 248 container.setState(FOCUSED_STATE); 249 assertFalse(container.hasFocusStateSpecified()); 250 251 // No drawable of state_focused=true 252 container = new MockDrawableContainer(); 253 containerState = (DrawableContainerState) new LevelListDrawable().getConstantState(); 254 assertNotNull(containerState); 255 container.setConstantState(containerState); 256 containerState.addChild(DrawableFactory.createPaintDrawable()); 257 containerState.addChild(DrawableFactory.createBitmapDrawable(mContext)); 258 containerState.addChild(DrawableFactory.createColorDrawable()); 259 container.selectDrawable(0); 260 container.setState(FOCUSED_STATE); 261 assertFalse(container.hasFocusStateSpecified()); 262 container.selectDrawable(1); 263 container.setState(FOCUSED_STATE); 264 assertFalse(container.hasFocusStateSpecified()); 265 container.selectDrawable(2); 266 container.setState(FOCUSED_STATE); 267 assertFalse(container.hasFocusStateSpecified()); 268 269 // Only drawables of state_focused=true 270 container = new MockDrawableContainer(); 271 containerState = (DrawableContainerState) new LevelListDrawable().getConstantState(); 272 assertNotNull(containerState); 273 container.setConstantState(containerState); 274 containerState.addChild(DrawableFactory.createRippleDrawable()); 275 containerState.addChild( 276 DrawableFactory.createStateListDrawable( 277 new int[][] { STATE_FOCUSED_WITH_POS, STATE_FOCUSED_WITH_NEG } 278 ) 279 ); 280 container.selectDrawable(0); 281 container.setState(FOCUSED_STATE); 282 assertTrue(container.hasFocusStateSpecified()); 283 container.selectDrawable(1); 284 container.setState(FOCUSED_STATE); 285 assertTrue(container.hasFocusStateSpecified()); 286 287 // Both drawables of state_focused=true and state_focused=false 288 containerState.addChild(DrawableFactory.createColorDrawable()); 289 container.selectDrawable(2); 290 container.setState(FOCUSED_STATE); 291 assertFalse(container.hasFocusStateSpecified()); 292 container.selectDrawable(1); 293 container.setState(FOCUSED_STATE); 294 assertTrue(container.hasFocusStateSpecified()); 295 container.selectDrawable(0); 296 container.setState(FOCUSED_STATE); 297 assertTrue(container.hasFocusStateSpecified()); 298 } 299 300 static class DrawableFactory { 301 static ShapeDrawable createShapeDrawable() { 302 return new ShapeDrawable(new RectShape()); 303 } 304 static PaintDrawable createPaintDrawable() { 305 PaintDrawable paintDrawable = new PaintDrawable(); 306 paintDrawable.setCornerRadius(1.5f); 307 return paintDrawable; 308 } 309 static BitmapDrawable createBitmapDrawable(Context context) { 310 Bitmap bitmap = Bitmap.createBitmap(200, 300, Config.ARGB_8888); 311 BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), bitmap); 312 return bitmapDrawable; 313 } 314 static ColorDrawable createColorDrawable() { 315 return new ColorDrawable(A_COLOR); 316 } 317 static GradientDrawable createGradientDrawable() { 318 GradientDrawable gradientDrawable = new GradientDrawable(); 319 gradientDrawable.setColor(A_COLOR); 320 gradientDrawable.setCornerRadius(10f); 321 return gradientDrawable; 322 } 323 static NinePatchDrawable createNinePatchDrawable(Context context) { 324 Resources res = context.getResources(); 325 Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.ninepatch_0); 326 NinePatch np = new NinePatch(bitmap, bitmap.getNinePatchChunk(), null); 327 NinePatchDrawable ninePatchDrawable = new NinePatchDrawable(res, np); 328 return ninePatchDrawable; 329 } 330 static RippleDrawable createRippleDrawable() { 331 RippleDrawable rippleDrawable = 332 new RippleDrawable(ColorStateList.valueOf(A_COLOR), null, null); 333 return rippleDrawable; 334 } 335 static PictureDrawable createPictureDrawable(Picture picture) { 336 PictureDrawable pictureDrawable = new PictureDrawable(picture); 337 return pictureDrawable; 338 } 339 static StateListDrawable createStateListDrawable(int[][] stateList) { 340 StateListDrawable drawable = new StateListDrawable(); 341 ColorDrawable colorDrawable = DrawableFactory.createColorDrawable(); 342 for (int i = 0; i < stateList.length; i++) { 343 drawable.addState(stateList[i], colorDrawable); 344 } 345 return drawable; 346 } 347 } 348 349 // We're calling protected methods in DrawableContainer. 350 // So we have to extend it here to make it accessible. 351 private class MockDrawableContainer extends DrawableContainer { 352 @Override 353 protected void setConstantState(DrawableContainerState state) { 354 super.setConstantState(state); 355 } 356 } 357 358 } 359