Last active
August 20, 2016 18:05
-
-
Save ilwsm/410bea2401dcf53c10cd856e38b5d515 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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