Home | History | Annotate | Download | only in drawable
      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
     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