1. 程式人生 > >android 用java反射修改Activity的元件view的佈局或者屬性

android 用java反射修改Activity的元件view的佈局或者屬性

原因:正所謂技術來源於需求,同時推動需求 , 研究的出發點是,PM發現app的某一個view的元件有些問題,view座標或者顏色、字型大小等,需要rd去修改,但是呢這個元件是第三方的sdk中內建,並沒有提供 對應的介面或者方法,怎麼辦?

以前是這樣的:


方法:反射 。。。反射。。。發射,重要的事情說三遍

具體操作步驟:

反射的原理不必多說了! 網上的demo成堆!

1.拿到當前要修改的Activity的instance例項物件,反射的時候需要用到這個物件,注意這個物件是要展示的那個快銷

 public static Activity getActivity() {
        Class activityThreadClass = null;
        try {
            activityThreadClass = Class.forName("android.app.ActivityThread");
            Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
            Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
            activitiesField.setAccessible(true);
            Map activities = (Map) activitiesField.get(activityThread);
            for (Object activityRecord : activities.values()) {
                Class activityRecordClass = activityRecord.getClass();
                Field pausedField = activityRecordClass.getDeclaredField("paused");
                pausedField.setAccessible(true);
                if (!pausedField.getBoolean(activityRecord)) {
                    Field activityField = activityRecordClass.getDeclaredField("activity");
                    activityField.setAccessible(true);
                    Activity activity = (Activity) activityField.get(activityRecord);
                    return activity;
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

2. 反射走起來,設定屬性
  try {
                    Activity temp = getActivity();
                    Class clazz = temp.getClass();
                    Field idFid = clazz.getDeclaredField("h");
                    idFid.setAccessible(true);
                    RelativeLayout relativeLayout = (RelativeLayout) idFid.get(temp);
                    Field bFid = clazz.getDeclaredField("b");
                    bFid.setAccessible(true);
                    TextView s = (TextView) relativeLayout.findViewById(bFid.getInt(temp));
                    RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) s.getLayoutParams();
                    Field aFid = clazz.getDeclaredField("a");
                    aFid.setAccessible(true);
                    layoutParams.width = -2;
                    layoutParams.height = -1;
                    layoutParams.addRule(RelativeLayout.RIGHT_OF, aFid.getInt(temp));
                    Button back = (Button) relativeLayout.findViewById(aFid.getInt(temp));
                    RelativeLayout.LayoutParams layoutParamsBtn = (RelativeLayout.LayoutParams) back.getLayoutParams();
                    layoutParamsBtn.width = DeviceUtils.dip2px(temp, 40);
                    back.setLayoutParams(layoutParamsBtn);
                    s.setLayoutParams(layoutParams);
                } catch (Exception e) {
                    e.printStackTrace();
                }

3. 走幾步看看??效果圖


4. h 、 a、b等都是成員變數混淆之後變數

設定之後記得:back.setLayoutParams(layoutParamsBtn); 否則不生效哦,原因自己去看view原始碼去吧!
 RelativeLayout的程式碼佈局:layoutParams.addRule(RelativeLayout.RIGHT_OF, aFid.getInt(temp));   第二個引數是anchor,就是相對的元件ID