1 /* 2 * Copyright (C) 2015 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; 18 19 import com.android.tools.layoutlib.annotations.LayoutlibDelegate; 20 21 import android.graphics.Path; 22 import android.graphics.drawable.GradientDrawable.GradientState; 23 24 import java.lang.reflect.Field; 25 26 /** 27 * Delegate implementing the native methods of {@link GradientDrawable} 28 * 29 * Through the layoutlib_create tool, the original native methods of GradientDrawable have been 30 * replaced by calls to methods of the same name in this delegate class. 31 */ 32 public class GradientDrawable_Delegate { 33 34 /** 35 * The ring can be built either by drawing full circles, or by drawing arcs in case the 36 * circle isn't complete. LayoutLib cannot handle drawing full circles (requires path 37 * subtraction). So, if we need to draw full circles, we switch to drawing 99% circle. 38 */ 39 @LayoutlibDelegate buildRing(GradientDrawable thisDrawable, GradientState st)40 /*package*/ static Path buildRing(GradientDrawable thisDrawable, GradientState st) { 41 boolean useLevel = st.mUseLevelForShape; 42 int level = thisDrawable.getLevel(); 43 // 10000 is the max level. See android.graphics.drawable.Drawable#getLevel() 44 float sweep = useLevel ? (360.0f * level / 10000.0f) : 360f; 45 Field mLevel = null; 46 if (sweep >= 360 || sweep <= -360) { 47 st.mUseLevelForShape = true; 48 // Use reflection to set the value of the field to prevent setting the drawable to 49 // dirty again. 50 try { 51 mLevel = Drawable.class.getDeclaredField("mLevel"); 52 mLevel.setAccessible(true); 53 mLevel.setInt(thisDrawable, 9999); // set to one less than max. 54 } catch (NoSuchFieldException e) { 55 // The field has been removed in a recent framework change. Fall back to old 56 // buggy behaviour. 57 } catch (IllegalAccessException e) { 58 // We've already set the field to be accessible. 59 assert false; 60 } 61 } 62 Path path = thisDrawable.buildRing_Original(st); 63 st.mUseLevelForShape = useLevel; 64 if (mLevel != null) { 65 try { 66 mLevel.setInt(thisDrawable, level); 67 } catch (IllegalAccessException e) { 68 assert false; 69 } 70 } 71 return path; 72 } 73 } 74