Initial commit 🎉
fbshipit-source-id: b6fc29740c6875d2e78953b8a7123890a67930f2 Co-authored-by: Sebastian McKenzie <sebmck@fb.com> Co-authored-by: John Knox <jknox@fb.com> Co-authored-by: Emil Sjölander <emilsj@fb.com> Co-authored-by: Pritesh Nandgaonkar <prit91@fb.com>
This commit is contained in:
708
android/plugins/inspector/descriptors/ViewDescriptor.java
Normal file
708
android/plugins/inspector/descriptors/ViewDescriptor.java
Normal file
@@ -0,0 +1,708 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.facebook.sonar.plugins.inspector.descriptors;
|
||||
|
||||
import static com.facebook.sonar.plugins.inspector.InspectorValue.Type.Color;
|
||||
import static com.facebook.sonar.plugins.inspector.InspectorValue.Type.Enum;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.support.v4.view.MarginLayoutParamsCompat;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewGroup.MarginLayoutParams;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import com.facebook.sonar.core.SonarDynamic;
|
||||
import com.facebook.sonar.core.SonarObject;
|
||||
import com.facebook.sonar.plugins.inspector.HighlightedOverlay;
|
||||
import com.facebook.sonar.plugins.inspector.InspectorValue;
|
||||
import com.facebook.sonar.plugins.inspector.Named;
|
||||
import com.facebook.sonar.plugins.inspector.NodeDescriptor;
|
||||
import com.facebook.sonar.plugins.inspector.Touch;
|
||||
import com.facebook.sonar.plugins.inspector.descriptors.utils.AccessibilityUtil;
|
||||
import com.facebook.sonar.plugins.inspector.descriptors.utils.EnumMapping;
|
||||
import com.facebook.stetho.common.android.ResourcesUtil;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ViewDescriptor extends NodeDescriptor<View> {
|
||||
|
||||
private static Field sKeyedTagsField;
|
||||
private static Field sListenerInfoField;
|
||||
private static Field sOnClickListenerField;
|
||||
|
||||
static {
|
||||
try {
|
||||
sKeyedTagsField = View.class.getDeclaredField("mKeyedTags");
|
||||
sKeyedTagsField.setAccessible(true);
|
||||
|
||||
sListenerInfoField = View.class.getDeclaredField("mListenerInfo");
|
||||
sListenerInfoField.setAccessible(true);
|
||||
|
||||
final String viewInfoClassName = View.class.getName() + "$ListenerInfo";
|
||||
sOnClickListenerField = Class.forName(viewInfoClassName).getDeclaredField("mOnClickListener");
|
||||
sOnClickListenerField.setAccessible(true);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final View node) {}
|
||||
|
||||
@Override
|
||||
public String getId(View node) {
|
||||
return Integer.toString(System.identityHashCode(node));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(View node) {
|
||||
return node.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildCount(View node) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object getChildAt(View node, int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Named<SonarObject>> getData(View node) {
|
||||
final SonarObject.Builder viewProps =
|
||||
new SonarObject.Builder()
|
||||
.put("height", InspectorValue.mutable(node.getHeight()))
|
||||
.put("width", InspectorValue.mutable(node.getWidth()))
|
||||
.put("alpha", InspectorValue.mutable(node.getAlpha()))
|
||||
.put("visibility", sVisibilityMapping.get(node.getVisibility()))
|
||||
.put("background", fromDrawable(node.getBackground()))
|
||||
.put("tag", InspectorValue.mutable(node.getTag()))
|
||||
.put("keyedTags", getTags(node))
|
||||
.put("layoutParams", getLayoutParams(node))
|
||||
.put(
|
||||
"state",
|
||||
new SonarObject.Builder()
|
||||
.put("enabled", InspectorValue.mutable(node.isEnabled()))
|
||||
.put("activated", InspectorValue.mutable(node.isActivated()))
|
||||
.put("focused", node.isFocused())
|
||||
.put("selected", InspectorValue.mutable(node.isSelected())))
|
||||
.put(
|
||||
"bounds",
|
||||
new SonarObject.Builder()
|
||||
.put("left", InspectorValue.mutable(node.getLeft()))
|
||||
.put("right", InspectorValue.mutable(node.getRight()))
|
||||
.put("top", InspectorValue.mutable(node.getTop()))
|
||||
.put("bottom", InspectorValue.mutable(node.getBottom())))
|
||||
.put(
|
||||
"padding",
|
||||
new SonarObject.Builder()
|
||||
.put("left", InspectorValue.mutable(node.getPaddingLeft()))
|
||||
.put("top", InspectorValue.mutable(node.getPaddingTop()))
|
||||
.put("right", InspectorValue.mutable(node.getPaddingRight()))
|
||||
.put("bottom", InspectorValue.mutable(node.getPaddingBottom())))
|
||||
.put(
|
||||
"rotation",
|
||||
new SonarObject.Builder()
|
||||
.put("x", InspectorValue.mutable(node.getRotationX()))
|
||||
.put("y", InspectorValue.mutable(node.getRotationY()))
|
||||
.put("z", InspectorValue.mutable(node.getRotation())))
|
||||
.put(
|
||||
"scale",
|
||||
new SonarObject.Builder()
|
||||
.put("x", InspectorValue.mutable(node.getScaleX()))
|
||||
.put("y", InspectorValue.mutable(node.getScaleY())))
|
||||
.put(
|
||||
"pivot",
|
||||
new SonarObject.Builder()
|
||||
.put("x", InspectorValue.mutable(node.getPivotX()))
|
||||
.put("y", InspectorValue.mutable(node.getPivotY())));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
viewProps
|
||||
.put("layoutDirection", sLayoutDirectionMapping.get(node.getLayoutDirection()))
|
||||
.put("textDirection", sTextDirectionMapping.get(node.getTextDirection()))
|
||||
.put("textAlignment", sTextAlignmentMapping.get(node.getTextAlignment()));
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
viewProps.put("elevation", InspectorValue.mutable(node.getElevation()));
|
||||
}
|
||||
|
||||
SonarObject.Builder translation =
|
||||
new SonarObject.Builder()
|
||||
.put("x", InspectorValue.mutable(node.getTranslationX()))
|
||||
.put("y", InspectorValue.mutable(node.getTranslationY()));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
translation.put("z", InspectorValue.mutable(node.getTranslationZ()));
|
||||
}
|
||||
viewProps.put("translation", translation);
|
||||
|
||||
SonarObject.Builder position =
|
||||
new SonarObject.Builder()
|
||||
.put("x", InspectorValue.mutable(node.getX()))
|
||||
.put("y", InspectorValue.mutable(node.getY()));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
position.put("z", InspectorValue.mutable(node.getZ()));
|
||||
}
|
||||
viewProps.put("position", position);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
viewProps.put("foreground", fromDrawable(node.getForeground()));
|
||||
}
|
||||
|
||||
return Arrays.asList(
|
||||
new Named<>("View", viewProps.build()),
|
||||
new Named<>("Accessibility", getAccessibilityData(node)));
|
||||
}
|
||||
|
||||
private static SonarObject getAccessibilityData(View view) {
|
||||
final SonarObject.Builder accessibilityProps = new SonarObject.Builder();
|
||||
|
||||
// This needs to be an empty string to be mutable. See t20470623.
|
||||
CharSequence contentDescription =
|
||||
view.getContentDescription() != null ? view.getContentDescription() : "";
|
||||
accessibilityProps.put("content-description", InspectorValue.mutable(contentDescription));
|
||||
accessibilityProps.put("focusable", InspectorValue.mutable(view.isFocusable()));
|
||||
accessibilityProps.put("node-info", AccessibilityUtil.getAccessibilityNodeInfoProperties(view));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
accessibilityProps.put(
|
||||
"important-for-accessibility",
|
||||
AccessibilityUtil.sImportantForAccessibilityMapping.get(
|
||||
view.getImportantForAccessibility()));
|
||||
}
|
||||
|
||||
AccessibilityUtil.addTalkbackProperties(accessibilityProps, view);
|
||||
|
||||
return accessibilityProps.build();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
@Override
|
||||
public void setValue(View node, String[] path, SonarDynamic value) {
|
||||
if (path[0].equals("Accessibility")) {
|
||||
setAccessibilityValue(node, path, value);
|
||||
}
|
||||
|
||||
if (!path[0].equals("View")) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (path[1]) {
|
||||
case "elevation":
|
||||
node.setElevation(value.asFloat());
|
||||
break;
|
||||
case "alpha":
|
||||
node.setAlpha(value.asFloat());
|
||||
break;
|
||||
case "visibility":
|
||||
node.setVisibility(sVisibilityMapping.get(value.asString()));
|
||||
break;
|
||||
case "layoutParams":
|
||||
setLayoutParams(node, Arrays.copyOfRange(path, 1, path.length), value);
|
||||
break;
|
||||
case "layoutDirection":
|
||||
node.setLayoutDirection(sLayoutDirectionMapping.get(value.asString()));
|
||||
break;
|
||||
case "textDirection":
|
||||
node.setTextDirection(sTextDirectionMapping.get(value.asString()));
|
||||
break;
|
||||
case "textAlignment":
|
||||
node.setTextAlignment(sTextAlignmentMapping.get(value.asString()));
|
||||
break;
|
||||
case "background":
|
||||
node.setBackground(new ColorDrawable(value.asInt()));
|
||||
break;
|
||||
case "foreground":
|
||||
node.setForeground(new ColorDrawable(value.asInt()));
|
||||
break;
|
||||
case "state":
|
||||
switch (path[2]) {
|
||||
case "enabled":
|
||||
node.setEnabled(value.asBoolean());
|
||||
break;
|
||||
case "activated":
|
||||
node.setActivated(value.asBoolean());
|
||||
break;
|
||||
case "selected":
|
||||
node.setSelected(value.asBoolean());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "bounds":
|
||||
switch (path[2]) {
|
||||
case "left":
|
||||
node.setLeft(value.asInt());
|
||||
break;
|
||||
case "top":
|
||||
node.setTop(value.asInt());
|
||||
break;
|
||||
case "right":
|
||||
node.setRight(value.asInt());
|
||||
break;
|
||||
case "bottom":
|
||||
node.setBottom(value.asInt());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "padding":
|
||||
switch (path[2]) {
|
||||
case "left":
|
||||
node.setPadding(
|
||||
value.asInt(),
|
||||
node.getPaddingTop(),
|
||||
node.getPaddingRight(),
|
||||
node.getPaddingBottom());
|
||||
break;
|
||||
case "top":
|
||||
node.setPadding(
|
||||
node.getPaddingLeft(),
|
||||
value.asInt(),
|
||||
node.getPaddingRight(),
|
||||
node.getPaddingBottom());
|
||||
break;
|
||||
case "right":
|
||||
node.setPadding(
|
||||
node.getPaddingLeft(),
|
||||
node.getPaddingTop(),
|
||||
value.asInt(),
|
||||
node.getPaddingBottom());
|
||||
break;
|
||||
case "bottom":
|
||||
node.setPadding(
|
||||
node.getPaddingLeft(), node.getPaddingTop(), node.getPaddingRight(), value.asInt());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "rotation":
|
||||
switch (path[2]) {
|
||||
case "x":
|
||||
node.setRotationX(value.asFloat());
|
||||
break;
|
||||
case "y":
|
||||
node.setRotationY(value.asFloat());
|
||||
break;
|
||||
case "z":
|
||||
node.setRotation(value.asFloat());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "translation":
|
||||
switch (path[2]) {
|
||||
case "x":
|
||||
node.setTranslationX(value.asFloat());
|
||||
break;
|
||||
case "y":
|
||||
node.setTranslationY(value.asFloat());
|
||||
break;
|
||||
case "z":
|
||||
node.setTranslationZ(value.asFloat());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "position":
|
||||
switch (path[2]) {
|
||||
case "x":
|
||||
node.setX(value.asFloat());
|
||||
break;
|
||||
case "y":
|
||||
node.setY(value.asFloat());
|
||||
break;
|
||||
case "z":
|
||||
node.setZ(value.asFloat());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "scale":
|
||||
switch (path[2]) {
|
||||
case "x":
|
||||
node.setScaleX(value.asFloat());
|
||||
break;
|
||||
case "y":
|
||||
node.setScaleY(value.asFloat());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "pivot":
|
||||
switch (path[2]) {
|
||||
case "x":
|
||||
node.setPivotY(value.asFloat());
|
||||
break;
|
||||
case "y":
|
||||
node.setPivotX(value.asFloat());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "width":
|
||||
LayoutParams lpw = node.getLayoutParams();
|
||||
lpw.width = value.asInt();
|
||||
node.setLayoutParams(lpw);
|
||||
break;
|
||||
case "height":
|
||||
LayoutParams lph = node.getLayoutParams();
|
||||
lph.height = value.asInt();
|
||||
node.setLayoutParams(lph);
|
||||
break;
|
||||
}
|
||||
|
||||
invalidate(node);
|
||||
}
|
||||
|
||||
private void setAccessibilityValue(View node, String[] path, SonarDynamic value) {
|
||||
switch (path[1]) {
|
||||
case "focusable":
|
||||
node.setFocusable(value.asBoolean());
|
||||
break;
|
||||
case "important-for-accessibility":
|
||||
node.setImportantForAccessibility(
|
||||
AccessibilityUtil.sImportantForAccessibilityMapping.get(value.asString()));
|
||||
break;
|
||||
case "content-description":
|
||||
node.setContentDescription(value.asString());
|
||||
break;
|
||||
}
|
||||
invalidate(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Named<String>> getAttributes(View node) throws Exception {
|
||||
final List<Named<String>> attributes = new ArrayList<>();
|
||||
|
||||
final String resourceId = getResourceId(node);
|
||||
if (resourceId != null) {
|
||||
attributes.add(new Named<>("id", resourceId));
|
||||
}
|
||||
|
||||
if (sListenerInfoField != null && sOnClickListenerField != null) {
|
||||
final Object listenerInfo = sListenerInfoField.get(node);
|
||||
if (listenerInfo != null) {
|
||||
final OnClickListener clickListener =
|
||||
(OnClickListener) sOnClickListenerField.get(listenerInfo);
|
||||
if (clickListener != null) {
|
||||
attributes.add(new Named<>("onClick", clickListener.getClass().getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getResourceId(View node) {
|
||||
final int id = node.getId();
|
||||
|
||||
if (id == View.NO_ID) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ResourcesUtil.getIdStringQuietly(node.getContext(), node.getResources(), id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHighlighted(View node, boolean selected) {
|
||||
// We need to figure out whether the given View has a parent View since margins are not
|
||||
// included within a View's bounds. So, in order to display the margin values for a particular
|
||||
// view, we need to apply an overlay on its parent rather than itself.
|
||||
final View targetView;
|
||||
final ViewParent parent = node.getParent();
|
||||
if (parent instanceof View) {
|
||||
targetView = (View) parent;
|
||||
} else {
|
||||
targetView = node;
|
||||
}
|
||||
|
||||
if (!selected) {
|
||||
HighlightedOverlay.removeHighlight(targetView);
|
||||
return;
|
||||
}
|
||||
|
||||
final Rect padding =
|
||||
new Rect(
|
||||
ViewCompat.getPaddingStart(node),
|
||||
node.getPaddingTop(),
|
||||
ViewCompat.getPaddingEnd(node),
|
||||
node.getPaddingBottom());
|
||||
|
||||
final Rect margin;
|
||||
final ViewGroup.LayoutParams params = node.getLayoutParams();
|
||||
if (params instanceof ViewGroup.MarginLayoutParams) {
|
||||
final ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) params;
|
||||
margin =
|
||||
new Rect(
|
||||
MarginLayoutParamsCompat.getMarginStart(marginParams),
|
||||
marginParams.topMargin,
|
||||
MarginLayoutParamsCompat.getMarginEnd(marginParams),
|
||||
marginParams.bottomMargin);
|
||||
} else {
|
||||
margin = new Rect();
|
||||
}
|
||||
|
||||
final int left = node.getLeft();
|
||||
final int top = node.getTop();
|
||||
final Rect contentBounds = new Rect(left, top, left + node.getWidth(), top + node.getHeight());
|
||||
if (targetView == node) {
|
||||
// If the View doesn't have a parent View that we're applying the overlay to, then
|
||||
// we need to ensure that it is aligned to 0, 0, rather than its relative location to its
|
||||
// parent
|
||||
contentBounds.offset(-left, -top);
|
||||
}
|
||||
|
||||
HighlightedOverlay.setHighlighted(targetView, margin, padding, contentBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hitTest(View node, Touch touch) {
|
||||
touch.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getDecoration(View obj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String query, View node) throws Exception {
|
||||
final String resourceId = getResourceId(node);
|
||||
|
||||
if (resourceId != null && resourceId.toLowerCase().contains(query)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final NodeDescriptor objectDescriptor = descriptorForClass(Object.class);
|
||||
return objectDescriptor.matches(query, node);
|
||||
}
|
||||
|
||||
private SonarObject getTags(final View node) {
|
||||
final SonarObject.Builder tags = new SonarObject.Builder();
|
||||
if (sKeyedTagsField == null) {
|
||||
return tags.build();
|
||||
}
|
||||
|
||||
new ErrorReportingRunnable() {
|
||||
@Override
|
||||
protected void runOrThrow() throws Exception {
|
||||
final SparseArray keyedTags = (SparseArray) sKeyedTagsField.get(node);
|
||||
if (keyedTags != null) {
|
||||
for (int i = 0, count = keyedTags.size(); i < count; i++) {
|
||||
final String id =
|
||||
ResourcesUtil.getIdStringQuietly(
|
||||
node.getContext(), node.getResources(), keyedTags.keyAt(i));
|
||||
tags.put(id, keyedTags.valueAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}.run();
|
||||
|
||||
return tags.build();
|
||||
}
|
||||
|
||||
private static InspectorValue fromDrawable(Drawable d) {
|
||||
if (d instanceof ColorDrawable) {
|
||||
return InspectorValue.mutable(Color, ((ColorDrawable) d).getColor());
|
||||
}
|
||||
return InspectorValue.mutable(Color, 0);
|
||||
}
|
||||
|
||||
private static SonarObject getLayoutParams(View node) {
|
||||
final LayoutParams layoutParams = node.getLayoutParams();
|
||||
final SonarObject.Builder params = new SonarObject.Builder();
|
||||
|
||||
params.put("width", fromSize(layoutParams.width));
|
||||
params.put("height", fromSize(layoutParams.height));
|
||||
|
||||
if (layoutParams instanceof MarginLayoutParams) {
|
||||
final MarginLayoutParams marginLayoutParams = (MarginLayoutParams) layoutParams;
|
||||
params.put(
|
||||
"margin",
|
||||
new SonarObject.Builder()
|
||||
.put("left", InspectorValue.mutable(marginLayoutParams.leftMargin))
|
||||
.put("top", InspectorValue.mutable(marginLayoutParams.topMargin))
|
||||
.put("right", InspectorValue.mutable(marginLayoutParams.rightMargin))
|
||||
.put("bottom", InspectorValue.mutable(marginLayoutParams.bottomMargin)));
|
||||
}
|
||||
|
||||
if (layoutParams instanceof FrameLayout.LayoutParams) {
|
||||
final FrameLayout.LayoutParams frameLayoutParams = (FrameLayout.LayoutParams) layoutParams;
|
||||
params.put("gravity", sGravityMapping.get(frameLayoutParams.gravity));
|
||||
}
|
||||
|
||||
if (layoutParams instanceof LinearLayout.LayoutParams) {
|
||||
final LinearLayout.LayoutParams linearLayoutParams = (LinearLayout.LayoutParams) layoutParams;
|
||||
params
|
||||
.put("weight", InspectorValue.mutable(linearLayoutParams.weight))
|
||||
.put("gravity", sGravityMapping.get(linearLayoutParams.gravity));
|
||||
}
|
||||
|
||||
return params.build();
|
||||
}
|
||||
|
||||
private void setLayoutParams(View node, String[] path, SonarDynamic value) {
|
||||
final LayoutParams params = node.getLayoutParams();
|
||||
|
||||
switch (path[0]) {
|
||||
case "width":
|
||||
params.width = toSize(value.asString());
|
||||
break;
|
||||
case "height":
|
||||
params.height = toSize(value.asString());
|
||||
break;
|
||||
case "weight":
|
||||
final LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) params;
|
||||
linearParams.weight = value.asFloat();
|
||||
break;
|
||||
}
|
||||
|
||||
if (params instanceof MarginLayoutParams) {
|
||||
final MarginLayoutParams marginParams = (MarginLayoutParams) params;
|
||||
|
||||
switch (path[0]) {
|
||||
case "margin":
|
||||
switch (path[1]) {
|
||||
case "left":
|
||||
marginParams.leftMargin = value.asInt();
|
||||
break;
|
||||
case "top":
|
||||
marginParams.topMargin = value.asInt();
|
||||
break;
|
||||
case "right":
|
||||
marginParams.rightMargin = value.asInt();
|
||||
break;
|
||||
case "bottom":
|
||||
marginParams.bottomMargin = value.asInt();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (params instanceof FrameLayout.LayoutParams) {
|
||||
final FrameLayout.LayoutParams frameLayoutParams = (FrameLayout.LayoutParams) params;
|
||||
|
||||
switch (path[0]) {
|
||||
case "gravity":
|
||||
frameLayoutParams.gravity = sGravityMapping.get(value.asString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (params instanceof LinearLayout.LayoutParams) {
|
||||
final LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) params;
|
||||
|
||||
switch (path[0]) {
|
||||
case "weight":
|
||||
linearParams.weight = value.asFloat();
|
||||
break;
|
||||
case "gravity":
|
||||
linearParams.gravity = sGravityMapping.get(value.asString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
node.setLayoutParams(params);
|
||||
}
|
||||
|
||||
private static InspectorValue fromSize(int size) {
|
||||
switch (size) {
|
||||
case LayoutParams.WRAP_CONTENT:
|
||||
return InspectorValue.mutable(Enum, "WRAP_CONTENT");
|
||||
case LayoutParams.MATCH_PARENT:
|
||||
return InspectorValue.mutable(Enum, "MATCH_PARENT");
|
||||
default:
|
||||
return InspectorValue.mutable(Enum, Integer.toString(size));
|
||||
}
|
||||
}
|
||||
|
||||
private static int toSize(String size) {
|
||||
switch (size) {
|
||||
case "WRAP_CONTENT":
|
||||
return LayoutParams.WRAP_CONTENT;
|
||||
case "MATCH_PARENT":
|
||||
return LayoutParams.MATCH_PARENT;
|
||||
default:
|
||||
return Integer.parseInt(size);
|
||||
}
|
||||
}
|
||||
|
||||
private static final EnumMapping sVisibilityMapping =
|
||||
new EnumMapping("VISIBLE") {
|
||||
{
|
||||
put("VISIBLE", View.VISIBLE);
|
||||
put("INVISIBLE", View.INVISIBLE);
|
||||
put("GONE", View.GONE);
|
||||
}
|
||||
};
|
||||
|
||||
private static final EnumMapping sLayoutDirectionMapping =
|
||||
new EnumMapping("LAYOUT_DIRECTION_INHERIT") {
|
||||
{
|
||||
put("LAYOUT_DIRECTION_INHERIT", View.LAYOUT_DIRECTION_INHERIT);
|
||||
put("LAYOUT_DIRECTION_LOCALE", View.LAYOUT_DIRECTION_LOCALE);
|
||||
put("LAYOUT_DIRECTION_LTR", View.LAYOUT_DIRECTION_LTR);
|
||||
put("LAYOUT_DIRECTION_RTL", View.LAYOUT_DIRECTION_RTL);
|
||||
}
|
||||
};
|
||||
|
||||
private static final EnumMapping sTextDirectionMapping =
|
||||
new EnumMapping("TEXT_DIRECTION_INHERIT") {
|
||||
{
|
||||
put("TEXT_DIRECTION_INHERIT", View.TEXT_DIRECTION_INHERIT);
|
||||
put("TEXT_DIRECTION_FIRST_STRONG", View.TEXT_DIRECTION_FIRST_STRONG);
|
||||
put("TEXT_DIRECTION_ANY_RTL", View.TEXT_DIRECTION_ANY_RTL);
|
||||
put("TEXT_DIRECTION_LTR", View.TEXT_DIRECTION_LTR);
|
||||
put("TEXT_DIRECTION_RTL", View.TEXT_DIRECTION_RTL);
|
||||
put("TEXT_DIRECTION_LOCALE", View.TEXT_DIRECTION_LOCALE);
|
||||
put("TEXT_DIRECTION_FIRST_STRONG_LTR", View.TEXT_DIRECTION_FIRST_STRONG_LTR);
|
||||
put("TEXT_DIRECTION_FIRST_STRONG_RTL", View.TEXT_DIRECTION_FIRST_STRONG_RTL);
|
||||
}
|
||||
};
|
||||
|
||||
private static final EnumMapping sTextAlignmentMapping =
|
||||
new EnumMapping("TEXT_ALIGNMENT_INHERIT") {
|
||||
{
|
||||
put("TEXT_ALIGNMENT_INHERIT", View.TEXT_ALIGNMENT_INHERIT);
|
||||
put("TEXT_ALIGNMENT_GRAVITY", View.TEXT_ALIGNMENT_GRAVITY);
|
||||
put("TEXT_ALIGNMENT_TEXT_START", View.TEXT_ALIGNMENT_TEXT_START);
|
||||
put("TEXT_ALIGNMENT_TEXT_END", View.TEXT_ALIGNMENT_TEXT_END);
|
||||
put("TEXT_ALIGNMENT_CENTER", View.TEXT_ALIGNMENT_CENTER);
|
||||
put("TEXT_ALIGNMENT_VIEW_START", View.TEXT_ALIGNMENT_VIEW_START);
|
||||
put("TEXT_ALIGNMENT_VIEW_END", View.TEXT_ALIGNMENT_VIEW_END);
|
||||
}
|
||||
};
|
||||
|
||||
private static final EnumMapping sGravityMapping =
|
||||
new EnumMapping("NO_GRAVITY") {
|
||||
{
|
||||
put("NO_GRAVITY", Gravity.NO_GRAVITY);
|
||||
put("LEFT", Gravity.LEFT);
|
||||
put("TOP", Gravity.TOP);
|
||||
put("RIGHT", Gravity.RIGHT);
|
||||
put("BOTTOM", Gravity.BOTTOM);
|
||||
put("CENTER", Gravity.CENTER);
|
||||
put("CENTER_VERTICAL", Gravity.CENTER_VERTICAL);
|
||||
put("FILL_VERTICAL", Gravity.FILL_VERTICAL);
|
||||
put("CENTER_HORIZONTAL", Gravity.CENTER_HORIZONTAL);
|
||||
put("FILL_HORIZONTAL", Gravity.FILL_HORIZONTAL);
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user