diff options
6 files changed, 93 insertions, 168 deletions
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java index 5db9556d91d4..2e649c3ad0f6 100644 --- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java @@ -16,19 +16,15 @@  package android.view; -import com.android.ide.common.rendering.api.LayoutlibCallback;  import com.android.ide.common.rendering.api.LayoutLog; +import com.android.ide.common.rendering.api.LayoutlibCallback;  import com.android.ide.common.rendering.api.MergeCookie;  import com.android.ide.common.rendering.api.ResourceReference;  import com.android.ide.common.rendering.api.ResourceValue;  import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.BridgeConstants;  import com.android.layoutlib.bridge.android.BridgeContext;  import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.android.support.RecyclerViewUtil; -import com.android.layoutlib.bridge.android.support.RecyclerViewUtil.LayoutManagerType;  import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.impl.RenderSessionImpl;  import com.android.resources.ResourceType;  import com.android.util.Pair; @@ -233,22 +229,6 @@ public final class BridgeInflater extends LayoutInflater {              if (viewKey != null) {                  bc.addViewKey(view, viewKey);              } -            if (RenderSessionImpl.isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) { -                String type = attrs.getAttributeValue(BridgeConstants.NS_RESOURCES, -                                BridgeConstants.ATTR_LAYOUT_MANAGER_TYPE); -                if (type != null) { -                    LayoutManagerType layoutManagerType = LayoutManagerType.getByLogicalName(type); -                    if (layoutManagerType == null) { -                        layoutManagerType = LayoutManagerType.getByClassName(type); -                    } -                    if (layoutManagerType == null) { -                        // add the classname itself. -                        bc.addCookie(view, type); -                    } else { -                        bc.addCookie(view, layoutManagerType); -                    } -                } -            }          }      } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 3f553e7a2c3e..2cbbeba2c2c4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -92,6 +92,8 @@ import java.util.IdentityHashMap;  import java.util.List;  import java.util.Map; +import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE; +  /**   * Custom implementation of Context/Activity to handle non compiled resources.   */ @@ -305,7 +307,7 @@ public final class BridgeContext extends Context {          // check if this is a style resource          if (value instanceof StyleResourceValue) {              // get the id that will represent this style. -            outValue.resourceId = getDynamicIdByStyle((StyleResourceValue)value); +            outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value);              return true;          } @@ -783,6 +785,14 @@ public final class BridgeContext extends Context {      } +    @Override +    public String getPackageName() { +        if (mApplicationInfo.packageName == null) { +            mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE); +        } +        return mApplicationInfo.packageName; +    } +      // ------------- private new methods      /** @@ -1190,12 +1200,6 @@ public final class BridgeContext extends Context {      }      @Override -    public String getPackageName() { -        // pass -        return null; -    } - -    @Override      public String getBasePackageName() {          // pass          return null; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java new file mode 100644 index 000000000000..b98f96f27c91 --- /dev/null +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.layoutlib.bridge.android; + +import com.android.ide.common.rendering.api.RenderParams; +import com.android.ide.common.rendering.api.SessionParams.Key; + +/** + * This contains all known keys for the {@link RenderParams#getFlag(Key)}. + * <p/> + * The IDE has its own copy of this class which may be newer or older than this one. + * <p/> + * Constants should never be modified or removed from this class. + */ +public final class RenderParamsFlags { + +    public static final Key<String> FLAG_KEY_ROOT_TAG = +            new Key<String>("rootTag", String.class); +    public static final Key<Boolean> FLAG_KEY_DISABLE_BITMAP_CACHING = +            new Key<Boolean>("disableBitmapCaching", Boolean.class); +    public static final Key<Boolean> FLAG_KEY_RENDER_ALL_DRAWABLE_STATES = +            new Key<Boolean>("renderAllDrawableStates", Boolean.class); +    /** +     * To tell LayoutLib that the IDE supports RecyclerView. +     * <p/> +     * Default is false. +     */ +    public static final Key<Boolean> FLAG_KEY_RECYCLER_VIEW_SUPPORT = +            new Key<Boolean>("recyclerViewSupport", Boolean.class); +    /** +     * The application package name. Used via +     * {@link com.android.ide.common.rendering.api.LayoutlibCallback#getFlag(Key)} +     */ +    public static final Key<String> FLAG_KEY_APPLICATION_PACKAGE = +            new Key<String>("applicationPackage", String.class); + +    // Disallow instances. +    private RenderParamsFlags() {} +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java deleted file mode 100644 index 22b51928f622..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.ide.common.rendering.api.SessionParams; - -/** - * This contains all known keys for the {@link SessionParams#getFlag(SessionParams.Key)}. - * <p/> - * The IDE has its own copy of this class which may be newer or older than this one. - * <p/> - * Constants should never be modified or removed from this class. - */ -public final class SessionParamsFlags { - -    public static final SessionParams.Key<String> FLAG_KEY_ROOT_TAG = -            new SessionParams.Key<String>("rootTag", String.class); -    public static final SessionParams.Key<Boolean> FLAG_KEY_RECYCLER_VIEW_SUPPORT = -            new SessionParams.Key<Boolean>("recyclerViewSupport", Boolean.class); - -    // Disallow instances. -    private SessionParamsFlags() {} -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java index aac5d33e365f..e4c728842275 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java @@ -23,15 +23,16 @@ import com.android.ide.common.rendering.api.LayoutlibCallback;  import com.android.ide.common.rendering.api.SessionParams;  import com.android.layoutlib.bridge.Bridge;  import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.SessionParamsFlags; +import com.android.layoutlib.bridge.android.RenderParamsFlags;  import android.content.Context;  import android.view.View; -import android.widget.LinearLayout;  import java.lang.reflect.Method; -import static com.android.layoutlib.bridge.util.ReflectionUtils.*; +import static com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException; +import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod; +import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;  /**   * Utility class for working with android.support.v7.widget.RecyclerView @@ -39,17 +40,15 @@ import static com.android.layoutlib.bridge.util.ReflectionUtils.*;  @SuppressWarnings("SpellCheckingInspection")  // for "recycler".  public class RecyclerViewUtil { -    /** -     * Used by {@link LayoutManagerType}. -     * <p/> -     * Not declared inside the enum, since it needs to be accessible in the constructor. -     */ -    private static final Object CONTEXT = new Object(); - -    public static final String CN_RECYCLER_VIEW = "android.support.v7.widget.RecyclerView"; +    private static final String RV_PKG_PREFIX = "android.support.v7.widget."; +    public static final String CN_RECYCLER_VIEW = RV_PKG_PREFIX + "RecyclerView";      private static final String CN_LAYOUT_MANAGER = CN_RECYCLER_VIEW + "$LayoutManager";      private static final String CN_ADAPTER = CN_RECYCLER_VIEW + "$Adapter"; +    // LinearLayoutManager related constants. +    private static final String CN_LINEAR_LAYOUT_MANAGER = RV_PKG_PREFIX + "LinearLayoutManager"; +    private static final Class<?>[] LLM_CONSTRUCTOR_SIGNATURE = new Class<?>[]{Context.class}; +      /**       * Tries to create an Adapter ({@code android.support.v7.widget.RecyclerView.Adapter} and a       * LayoutManager {@code RecyclerView.LayoutManager} and assign these to the {@code RecyclerView} @@ -71,39 +70,35 @@ public class RecyclerViewUtil {      private static void setLayoutManager(@NonNull View recyclerView, @NonNull BridgeContext context,              @NonNull LayoutlibCallback callback) throws ReflectionException { -        Object cookie = context.getCookie(recyclerView); -        assert cookie == null || cookie instanceof LayoutManagerType || cookie instanceof String; -        if (!(cookie instanceof LayoutManagerType)) { -            if (cookie != null) { -                // TODO: When layoutlib API is updated, try to load the class with a null -                // constructor or a constructor taking one argument - the context. -                Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED, -                        "LayoutManager (" + cookie + ") not found, falling back to " + -                                "LinearLayoutManager", null); -            } -            cookie = LayoutManagerType.getDefault(); +        if (getLayoutManager(recyclerView) == null) { +            // Only set the layout manager if not already set by the recycler view. +            Object layoutManager = createLayoutManager(context, callback); +            setProperty(recyclerView, CN_LAYOUT_MANAGER, layoutManager, "setLayoutManager");          } -        Object layoutManager = createLayoutManager((LayoutManagerType) cookie, context, callback); -        setProperty(recyclerView, CN_LAYOUT_MANAGER, layoutManager, "setLayoutManager");      } +    /** Creates a LinearLayoutManager using the provided context. */      @Nullable -    private static Object createLayoutManager(@Nullable LayoutManagerType type, -            @NonNull Context context, @NonNull LayoutlibCallback callback) +    private static Object createLayoutManager(@NonNull Context context, +            @NonNull LayoutlibCallback callback)              throws ReflectionException { -        if (type == null) { -            type = LayoutManagerType.getDefault(); -        }          try { -            return callback.loadView(type.getClassName(), type.getSignature(), type.getArgs(context)); +            return callback.loadView(CN_LINEAR_LAYOUT_MANAGER, LLM_CONSTRUCTOR_SIGNATURE, +                    new Object[]{ context});          } catch (Exception e) {              throw new ReflectionException(e);          }      }      @Nullable +    private static Object getLayoutManager(View recyclerview) throws ReflectionException { +        Method getLayoutManager = getMethod(recyclerview.getClass(), "getLayoutManager"); +        return getLayoutManager != null ? invoke(getLayoutManager, recyclerview) : null; +    } + +    @Nullable      private static Object createAdapter(@NonNull SessionParams params) throws ReflectionException { -        Boolean ideSupport = params.getFlag(SessionParamsFlags.FLAG_KEY_RECYCLER_VIEW_SUPPORT); +        Boolean ideSupport = params.getFlag(RenderParamsFlags.FLAG_KEY_RECYCLER_VIEW_SUPPORT);          if (ideSupport != Boolean.TRUE) {              return null;          } @@ -145,74 +140,4 @@ public class RecyclerViewUtil {          }          throw new RuntimeException("invalid object/classname combination.");      } - -    /** Supported LayoutManagers. */ -    public enum LayoutManagerType { -        LINEAR_LAYOUT_MANGER("Linear", -                "android.support.v7.widget.LinearLayoutManager", -                new Class[]{Context.class}, new Object[]{CONTEXT}), -        GRID_LAYOUT_MANAGER("Grid", -                "android.support.v7.widget.GridLayoutManager", -                new Class[]{Context.class, int.class}, new Object[]{CONTEXT, 2}), -        STAGGERED_GRID_LAYOUT_MANAGER("StaggeredGrid", -                "android.support.v7.widget.StaggeredGridLayoutManager", -                new Class[]{int.class, int.class}, new Object[]{2, LinearLayout.VERTICAL}); - -        private String mLogicalName; -        private String mClassName; -        private Class[] mSignature; -        private Object[] mArgs; - -        LayoutManagerType(String logicalName, String className, Class[] signature, Object[] args) { -            mLogicalName = logicalName; -            mClassName = className; -            mSignature = signature; -            mArgs = args; -        } - -        String getClassName() { -            return mClassName; -        } - -        Class[] getSignature() { -            return mSignature; -        } - -        @NonNull -        Object[] getArgs(Context context) { -            Object[] args = new Object[mArgs.length]; -            System.arraycopy(mArgs, 0, args, 0, mArgs.length); -            for (int i = 0; i < args.length; i++) { -                if (args[i] == CONTEXT) { -                    args[i] = context; -                } -            } -            return args; -        } - -        @NonNull -        public static LayoutManagerType getDefault() { -            return LINEAR_LAYOUT_MANGER; -        } - -        @Nullable -        public static LayoutManagerType getByLogicalName(@NonNull String logicalName) { -            for (LayoutManagerType type : values()) { -                if (logicalName.equals(type.mLogicalName)) { -                    return type; -                } -            } -            return null; -        } - -        @Nullable -        public static LayoutManagerType getByClassName(@NonNull String className) { -            for (LayoutManagerType type : values()) { -                if (className.equals(type.mClassName)) { -                    return type; -                } -            } -            return null; -        } -    }  } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index 68b3c1a5cca9..015fae82d468 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -45,7 +45,7 @@ import com.android.layoutlib.bridge.Bridge;  import com.android.layoutlib.bridge.android.BridgeContext;  import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;  import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.android.SessionParamsFlags; +import com.android.layoutlib.bridge.android.RenderParamsFlags;  import com.android.layoutlib.bridge.android.support.RecyclerViewUtil;  import com.android.layoutlib.bridge.bars.AppCompatActionBar;  import com.android.layoutlib.bridge.bars.BridgeActionBar; @@ -403,7 +403,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {              // it can instantiate the custom Fragment.              Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback()); -            String rootTag = params.getFlag(SessionParamsFlags.FLAG_KEY_ROOT_TAG); +            String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG);              boolean isPreference = "PreferenceScreen".equals(rootTag);              View view;              if (isPreference) {  |