Skip to content

Instantly share code, notes, and snippets.

@ilwsm
Last active August 20, 2016 18:05
Show Gist options
  • Save ilwsm/410bea2401dcf53c10cd856e38b5d515 to your computer and use it in GitHub Desktop.
Save ilwsm/410bea2401dcf53c10cd856e38b5d515 to your computer and use it in GitHub Desktop.
package org.kinocat.testlib;
import android.annotation.SuppressLint;
import android.content.res.Resources;
import android.os.Build;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import static android.view.Gravity.CLIP_HORIZONTAL;
import static android.view.Gravity.CLIP_VERTICAL;
public class XMLdeparser {
private static final String ANDROID = "android:";
private static final String APP = "app:";
private static final String ANDROID_SCHEMA = "xmlns:android=\"http://schemas.android.com/apk/res/android\"";
private final View mView;
private final StringBuilder sb = new StringBuilder();
private Resources mResources;
private String mSep;
private float mDensity;
private boolean printHiddenViews;
boolean printSchemas = true;
private XMLdeparser(View v) {
this.mView = v;
if (v != null) {
mResources = v.getContext().getResources();
mDensity = mResources.getDisplayMetrics().density;
}
}
public static void printView(View v) {
XMLdeparser xmLdeparser = new XMLdeparser(v);
xmLdeparser.printHiddenViews = false;
xmLdeparser.print();
}
private void print() {
if (mView == null) {
android.util.Log.d("FreakMurderer", "View is null");
return;
}
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
parseViewFirst(mView, "");
android.util.Log.d("FreakMurderer", "<><><><><>");
android.util.Log.d("FreakMurderer", sb.toString());
android.util.Log.d("FreakMurderer", "<><><><><>");
}
private void parseViewFirst(View v, String sep) {
if (!printHiddenViews && v.getVisibility() == View.GONE) return;
printAttrs(v, sep);
printSchemas = false;
if (v instanceof ViewGroup) {
int count = ((ViewGroup) v).getChildCount();
for (int i = 0; i < count; i++) {
View view = ((ViewGroup) v).getChildAt(i);
if (printHiddenViews || view.getVisibility() != View.GONE) {
sb.append("\n\n");
parseView(view, sep + "\t");
}
}
sb.append("\n\n").append(sep).append("</").append(v.getClass().getName()).append(">");
}
}
private void parseView(View v, String sep) {
printAttrs(v, sep);
if (v instanceof ViewGroup) {
int count = ((ViewGroup) v).getChildCount();
for (int i = 0; i < count; i++) {
View view = ((ViewGroup) v).getChildAt(i);
if (printHiddenViews || view.getVisibility() != View.GONE) {
sb.append("\n\n");
parseView(view, sep + "\t");
}
}
sb.append("\n\n").append(sep).append("</").append(v.getClass().getName()).append(">");
}
}
private void printAttrs(View v, String sep) {
sb.append(sep).append("<").append(v.getClass().getName());
sb.append("\n");
mSep = sep + "\t";
if (printSchemas) {
sb.append(mSep).append(ANDROID_SCHEMA).append("\n");
}
if (v.getId() > View.NO_ID) {
parseId(sb, v.getId());
}
int visibility = v.getVisibility();
switch (visibility){
case View.GONE:
androidAttrLn("visibility", "gone");
break;
case View.INVISIBLE:
androidAttrLn("visibility", "invisible");
break;
}
if (v instanceof LinearLayout) {
final LinearLayout llv = (LinearLayout) v;
int orientation = llv.getOrientation();
if (orientation == LinearLayout.HORIZONTAL) {
androidAttrLn("orientation", "horizontal");
} else {
androidAttrLn("orientation", "vertical");
}
try {
Field field = LinearLayout.class.getDeclaredField("mGravity");
field.setAccessible(true);
int gravity = field.getInt(v);
printGravityLn("gravity", gravity);
} catch (Exception ignored) {
//println(ignored.toString() + ", " + v.getClass() + ", [gravity]");
}
if (llv.getWeightSum() != -1) androidAttrLn("weightSum", llv.getWeightSum());
}
if (v instanceof TextView) {
String text = ((TextView)v).getText().toString();
if (!TextUtils.isEmpty(text)) androidAttrLn("text", text);
printGravityLn("gravity", ((TextView)v).getGravity());
}
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
androidAttrLn("layout_width", getSize(layoutParams.width));
androidAttrLn("layout_height", getSize(layoutParams.height));
try {
int gravity = layoutParams.getClass().getField("gravity").getInt(layoutParams);
printGravityLn("layout_gravity", gravity);
} catch (Exception ignored) {
//println(ignored.toString() + ", " + layoutParams.getClass() + ", [layout_gravity]");
}
if (layoutParams instanceof LinearLayout.LayoutParams ){
float weight = ((LinearLayout.LayoutParams) layoutParams).weight;
if (weight > 0) androidAttrLn("layout_weight", weight);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
if (v.getMinimumWidth() > 0) androidAttrLn("minWidth", getDp(v.getMinimumWidth()));
if (v.getMinimumHeight() > 0) androidAttrLn("minHeight", getDp(v.getMinimumHeight()));
}
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) layoutParams;
if (params.leftMargin > 0) androidAttrLn("layout_marginLeft", getDp(params.leftMargin));
if (params.topMargin > 0) androidAttrLn("layout_marginTop", getDp(params.topMargin));
if (params.rightMargin > 0) androidAttrLn("layout_marginRight", getDp(params.rightMargin));
if (params.bottomMargin > 0) androidAttrLn("layout_marginBottom", getDp(params.bottomMargin));
}
int padding = v.getPaddingLeft();
if (padding > 0) androidAttrLn("paddingLeft", getDp(padding));
padding = v.getPaddingTop();
if (padding > 0) androidAttrLn("paddingTop", getDp(padding));
padding = v.getPaddingRight();
if (padding > 0) androidAttrLn("paddingRight", getDp(padding));
padding = v.getPaddingBottom();
if (padding > 0) androidAttrLn("paddingBottom", getDp(padding));
sb.deleteCharAt(sb.length() - 1);
if (v instanceof ViewGroup) {
sb.append(">");
} else {
sb.append("/>");
}
}
private void printGravityLn(String attr, int gravity) {
if (gravity <= Gravity.NO_GRAVITY || gravity == (Gravity.TOP | Gravity.START)) return;
sb.append(mSep).append(ANDROID).append(attr).append("=\"");
printGravity(gravity);
sb.append("\"\n");
}
@SuppressLint("RtlHardcoded")
private void printGravity (int gravity) {
StringBuilder s = this.sb;
int len = s.length();
switch (gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
case Gravity.CENTER_HORIZONTAL:
s.append("center_horizontal|");
break;
case Gravity.LEFT:
s.append("left|");
break;
case Gravity.START:
s.append("start|");
break;
case Gravity.RIGHT:
s.append("right|");
break;
case Gravity.END:
s.append("end|");
break;
case Gravity.START | Gravity.END:
s.append("start|end|");
break;
}
switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
case Gravity.TOP:
s.append("top|");
break;
case Gravity.CENTER_VERTICAL:
s.append("center_vertical|");
break;
case Gravity.BOTTOM:
s.append("bottom|");
break;
}
switch (gravity & Gravity.FILL) {
case Gravity.FILL:
s.append("fill|");
break;
case Gravity.FILL_VERTICAL:
s.append("fill_vertical|");
break;
case Gravity.FILL_HORIZONTAL:
if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) != (Gravity.START | Gravity.END)) {
s.append("fill_horizontal|");
}
break;
}
switch (gravity & (CLIP_HORIZONTAL | CLIP_VERTICAL) & ~Gravity.FILL) {
case Gravity.CLIP_HORIZONTAL :
s.append("clip_horizontal|");
break;
case Gravity.CLIP_VERTICAL:
s.append("clip_vertical|");
break;
case CLIP_HORIZONTAL | CLIP_VERTICAL:
s.append("clip_horizontal|clip_vertical|");
break;
}
if (len == s.length()) {
s.append("0x").append(Integer.toHexString(gravity));
} else {
s.deleteCharAt(s.length() - 1);
}
}
private String getDp(float px) {
return (int) (px / mDensity) + "dp";
}
private String getSize(int value) {
switch (value) {
case ViewGroup.LayoutParams.MATCH_PARENT:
return "match_parent";
case ViewGroup.LayoutParams.WRAP_CONTENT:
return "wrap_content";
default:
return getDp(value);
}
}
private void androidAttrLn(String attr, Object obj) {
sb.append(mSep).append(ANDROID).append(attr).append("=\"").append(obj).append("\"\n");
}
private void androidAttr(String attr, Object obj) {
sb.append(mSep).append(ANDROID).append(attr).append("=\"").append(obj).append("\"");
}
private void print(String string) {
sb.append(mSep).append(string);
}
private void println(String string) {
sb.append(mSep).append(string).append("\n");
}
private void parseId(StringBuilder out, int id) {
out.append(mSep);
out.append(ANDROID).append("id=\"");
final Resources r = mResources;
if (resourceHasPackage(id) && r != null) {
try {
String pkgname;
switch (id & 0xff000000) {
case 0x7f000000:
pkgname = "";
break;
case 0x01000000:
pkgname = ANDROID;
break;
default:
pkgname = r.getResourcePackageName(id);
break;
}
String typename = r.getResourceTypeName(id);
String entryname = r.getResourceEntryName(id);
out.append("@");
if (!pkgname.equals(ANDROID)) out.append("+");
out.append(pkgname);
out.append(typename);
out.append("/");
out.append(entryname);
} catch (Resources.NotFoundException ignored) {
out.append("0x").append(Integer.toHexString(id));
}
} else {
out.append("0x").append(Integer.toHexString(id));
}
out.append("\"\n");
}
private boolean resourceHasPackage(int id) {
boolean res;
try {
Method m = Resources.class.getDeclaredMethod("resourceHasPackage", int.class);
m.setAccessible(true);
res = (boolean) m.invoke(null, id);
return res;
} catch (Exception ignored) {
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment