diff options
author | Deepanshu Gupta <deepanshu@google.com> | 2015-08-26 20:20:30 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2015-08-26 20:20:30 +0000 |
commit | a556d7566b09e4743f859f3ca0878f2084448cfc (patch) | |
tree | 8777d1e6de066c36983280edb346d65a2fd06f7f /tools | |
parent | 413d41aac4d573ad4f0270c0fefd94ef4e864225 (diff) | |
parent | 8bfc5a9d14000a436e54350099bd460f55418f27 (diff) | |
download | frameworks_base-a556d7566b09e4743f859f3ca0878f2084448cfc.zip frameworks_base-a556d7566b09e4743f859f3ca0878f2084448cfc.tar.gz frameworks_base-a556d7566b09e4743f859f3ca0878f2084448cfc.tar.bz2 |
am 8bfc5a9d: am b1e21330: Implement tools:list_item for RecyclerView. [DO NOT MERGE]
* commit '8bfc5a9d14000a436e54350099bd460f55418f27':
Implement tools:list_item for RecyclerView. [DO NOT MERGE]
Diffstat (limited to 'tools')
5 files changed, 79 insertions, 51 deletions
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java index 72d660c..cbbc463 100644 --- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java @@ -25,7 +25,9 @@ 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.impl.ParserFactory; +import com.android.layoutlib.bridge.util.ReflectionUtils; import com.android.resources.ResourceType; import com.android.util.Pair; @@ -112,14 +114,8 @@ public final class BridgeInflater extends LayoutInflater { } // Finally try again using the custom view loader - try { - if (view == null) { - view = loadCustomView(name, attrs); - } - } catch (ClassNotFoundException e) { - // If the class was not found, we throw the exception directly, because this - // method is already expected to throw it. - throw e; + if (view == null) { + view = loadCustomView(name, attrs); } } catch (Exception e) { // Wrap the real exception in a ClassNotFoundException, so that the calling method @@ -242,6 +238,25 @@ public final class BridgeInflater extends LayoutInflater { bc.setScrollYPos(view, value); } } + if (ReflectionUtils.isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) { + Integer resourceId = null; + String attrVal = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI, + BridgeConstants.ATTR_LIST_ITEM); + if (attrVal != null && !attrVal.isEmpty()) { + ResourceValue resValue = bc.getRenderResources().findResValue(attrVal, false); + if (resValue.isFramework()) { + resourceId = Bridge.getResourceId(resValue.getResourceType(), + resValue.getName()); + } else { + resourceId = mLayoutlibCallback.getResourceId(resValue.getResourceType(), + resValue.getName()); + } + } + if (resourceId == null) { + resourceId = 0; + } + RecyclerViewUtil.setAdapter(view, bc, mLayoutlibCallback, resourceId); + } } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java index 1af6998..661c08b 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java @@ -41,6 +41,7 @@ public class BridgeConstants { /** App auto namespace */ public final static String NS_APP_RES_AUTO = "http://schemas.android.com/apk/res-auto"; + public final static String NS_TOOLS_URI = "http://schemas.android.com/tools"; public final static String R = "com.android.internal.R"; @@ -50,5 +51,5 @@ public class BridgeConstants { public final static String WRAP_CONTENT = "wrap_content"; /** Attribute in the tools namespace used to specify layout manager for RecyclerView. */ - public static final String ATTR_LAYOUT_MANAGER_TYPE = "layoutManager"; + public static final String ATTR_LIST_ITEM = "list_item"; } 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 5e5b3c9..4182cd9 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 @@ -18,7 +18,6 @@ package com.android.layoutlib.bridge.android.support; import com.android.ide.common.rendering.api.LayoutLog; 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.RenderParamsFlags; @@ -37,7 +36,6 @@ import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke; /** * Utility class for working with android.support.v7.widget.RecyclerView */ -@SuppressWarnings("SpellCheckingInspection") // for "recycler". public class RecyclerViewUtil { private static final String RV_PKG_PREFIX = "android.support.v7.widget."; @@ -57,23 +55,34 @@ public class RecyclerViewUtil { * Any exceptions thrown during the process are logged in {@link Bridge#getLog()} */ public static void setAdapter(@NonNull View recyclerView, @NonNull BridgeContext context, - @NonNull SessionParams params) { + @NonNull LayoutlibCallback layoutlibCallback, int adapterLayout) { try { - setLayoutManager(recyclerView, context, params.getLayoutlibCallback()); - Object adapter = createAdapter(params); - setProperty(recyclerView, CN_ADAPTER, adapter, "setAdapter"); + setLayoutManager(recyclerView, context, layoutlibCallback); + Object adapter = createAdapter(layoutlibCallback); + if (adapter != null) { + setProperty(recyclerView, CN_ADAPTER, adapter, "setAdapter"); + setProperty(adapter, int.class, adapterLayout, "setLayoutId"); + } } catch (ReflectionException e) { + Throwable cause = getCause(e); Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Error occured while trying to setup RecyclerView.", e, null); + "Error occurred while trying to setup RecyclerView.", cause, null); } } + private static Throwable getCause(Throwable throwable) { + Throwable cause = throwable.getCause(); + return cause == null ? throwable : cause; + } + private static void setLayoutManager(@NonNull View recyclerView, @NonNull BridgeContext context, @NonNull LayoutlibCallback callback) throws ReflectionException { 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"); + if (layoutManager != null) { + setProperty(recyclerView, CN_LAYOUT_MANAGER, layoutManager, "setLayoutManager"); + } } } @@ -84,41 +93,46 @@ public class RecyclerViewUtil { throws ReflectionException { try { return callback.loadView(CN_LINEAR_LAYOUT_MANAGER, LLM_CONSTRUCTOR_SIGNATURE, - new Object[]{ context}); + 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; + 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(RenderParamsFlags.FLAG_KEY_RECYCLER_VIEW_SUPPORT); + private static Object createAdapter(@NonNull LayoutlibCallback layoutlibCallback) + throws ReflectionException { + Boolean ideSupport = + layoutlibCallback.getFlag(RenderParamsFlags.FLAG_KEY_RECYCLER_VIEW_SUPPORT); if (ideSupport != Boolean.TRUE) { return null; } try { - return params.getLayoutlibCallback().loadView(CN_ADAPTER, new Class[0], new Object[0]); + return layoutlibCallback.loadClass(CN_ADAPTER, new Class[0], new Object[0]); } catch (Exception e) { throw new ReflectionException(e); } } - private static void setProperty(@NonNull View recyclerView, @NonNull String propertyClassName, + private static void setProperty(@NonNull Object object, @NonNull String propertyClassName, + @NonNull Object propertyValue, @NonNull String propertySetter) + throws ReflectionException { + Class<?> propertyClass = getClassInstance(propertyValue, propertyClassName); + setProperty(object, propertyClass, propertyValue, propertySetter); + } + + private static void setProperty(@NonNull Object object, @NonNull Class<?> propertyClass, @Nullable Object propertyValue, @NonNull String propertySetter) throws ReflectionException { - if (propertyValue != null) { - Class<?> layoutManagerClass = getClassInstance(propertyValue, propertyClassName); - Method setLayoutManager = getMethod(recyclerView.getClass(), - propertySetter, layoutManagerClass); - if (setLayoutManager != null) { - invoke(setLayoutManager, recyclerView, propertyValue); - } + Method setter = getMethod(object.getClass(), propertySetter, propertyClass); + if (setter != null) { + invoke(setter, object, propertyValue); } } 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 9ef5156..e6d8ae9 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,6 @@ import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; import com.android.layoutlib.bridge.android.RenderParamsFlags; import com.android.layoutlib.bridge.android.support.DesignLibUtil; -import com.android.layoutlib.bridge.android.support.RecyclerViewUtil; import com.android.layoutlib.bridge.bars.AppCompatActionBar; import com.android.layoutlib.bridge.bars.BridgeActionBar; import com.android.layoutlib.bridge.bars.Config; @@ -116,6 +115,7 @@ import static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLA import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; import static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; +import static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf; /** * Class implementing the render session. @@ -1351,8 +1351,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { } } } - } else if (isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) { - RecyclerViewUtil.setAdapter(view, getContext(), getParams()); } else if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; final int count = group.getChildCount(); @@ -1457,22 +1455,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { } /** - * Check if the object is an instance of a class named {@code className}. This doesn't work - * for interfaces. - */ - public static boolean isInstanceOf(Object object, String className) { - Class superClass = object.getClass(); - while (superClass != null) { - String name = superClass.getName(); - if (name.equals(className)) { - return true; - } - superClass = superClass.getSuperclass(); - } - return false; - } - - /** * Sets up a {@link TabHost} object. * @param tabHost the TabHost to setup. * @param layoutlibCallback The project callback object to access the project R class. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java index b324451..b78b613 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java @@ -52,6 +52,22 @@ public class ReflectionUtils { } /** + * Check if the object is an instance of a class named {@code className}. This doesn't work + * for interfaces. + */ + public static boolean isInstanceOf(Object object, String className) { + Class superClass = object.getClass(); + while (superClass != null) { + String name = superClass.getName(); + if (name.equals(className)) { + return true; + } + superClass = superClass.getSuperclass(); + } + return false; + } + + /** * Wraps all reflection related exceptions. Created since ReflectiveOperationException was * introduced in 1.7 and we are still on 1.6 */ |