Android 反射实战 - 更换APP皮肤<1>

本文探讨Android如何实现动态更换应用皮肤,强调理解View及Activity加载过程的重要性。通过实现Factory接口,示例代码展示如何获取并保存APP中所有UI的属性,为后续动态更新替换做准备。
摘要由CSDN通过智能技术生成

Android 动态更换APP皮肤,个人感觉更多的是开发者对View理解能力,以及Activity等这种容器是如何加载各种视图view的过程,这个view包括系统UI,自定UI等view.这个地方首先就需要先熟悉Factory这个接口,看一看下面做一个测试工程:

<1> : 新建一个Android 工程项目,目录树如下:

<2> : OneplusFactoryImpl.java 类程序如下:

/**
 * 
 */
package impl;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater.Factory;
import android.view.LayoutInflater;
import android.view.View;

/**
 * @author zhibao.liu
 * @date 2015-12-8
 * @company : oneplus.Inc
 */
public class OneplusFactoryImpl implements Factory {

    private final static String TAG="oneplus";
    /*
     * (non-Javadoc)
     * 
     * @see android.view.LayoutInflater.Factory#onCreateView(java.lang.String,
     * android.content.Context, android.util.AttributeSet)
     */
    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        // TODO Auto-generated method stub

        View view = createView(context, name, attrs);

        return null;
    }

    private View createView(Context context, String name, AttributeSet attrs) {
        View view = null;

        Log.i(TAG,"create name : " + name);

        try {
            if (-1 == name.indexOf('.')) {
                if ("View".equals(name)) {
                    view = LayoutInflater.from(context).createView(name,
                            "android.view.", attrs);
                }
                if (view == null) {
                    view = LayoutInflater.from(context).createView(name,
                            "android.widget.", attrs);
                }
                if (view == null) {
                    view = LayoutInflater.from(context).createView(name,
                            "android.webkit.", attrs);
                }
            } else {
                view = LayoutInflater.from(context).createView(name, null,
                        attrs);
            }
        } catch (Exception e) {
            Log.i(TAG, "error while create " + name + " : " + e.getMessage());
            view = null;
        }
        return view;
    }

}

做一个实现factory接口的类.

<2> : 再新建OneplusBaseActivity.java:

/**
 * 
 */
package com.oneplus.base;

import impl.OneplusFactoryImpl;

import java.lang.reflect.Field;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;

/**
 * @author zhibao.liu
 * @date 2015-12-8
 * @company : oneplus.Inc
 */
public class OneplusBaseActivity extends Activity {

    private OneplusFactoryImpl mFactory;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        try {
            Field field = LayoutInflater.class.getDeclaredField("mFactorySet");
            field.setAccessible(true);
            try {
                field.setBoolean(getLayoutInflater(), false);

                mFactory = new OneplusFactoryImpl();
                getLayoutInflater().setFactory(mFactory);

            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

<3> : OneplusFactoryActivity主类继承上面的基类:

package com.oneplus.factoryimplapp;

import com.oneplus.base.OneplusBaseActivity;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
/**
 * 
 */

/**
 * @author zhibao.liu
 * @date 2015-12-8
 * @company : oneplus.Inc
 */
public class OneplusFactoryActivity extends OneplusBaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.oneplus_factory);
        
        
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.oneplus_factory, menu);
        return true;
    }
    
}

然后运行上面程序,结果如下:



一眼看不出来,但是仔细看一下,这个APP所有继承OneplusBaseActivity基类用到的UI信息都包含在里面了,设置包括状态栏.如果还不能够立即,我们在主类的布局增加一个上面没有的一个View,如果Button UI :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".OneplusFactoryActivity" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    
    <Button 
        android:id="@+id/button"
        android:layout_below="@id/text"
        android:text="hello"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</RelativeLayout>


截取其中一部分结果如下:



也就是说,通过上面的方法,在实现Factory接口的类中,可以获取出所有APP中包含的所有UI的种类和属性,我们获取了他们信息,就可以在APP启动的时候,获取并且保存起来,一边供后面获取资源后对所有UI的属性进行动态的更新替换.





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值