首页 > 代码库 > apkplug主题皮肤切换之自定义样式-05

apkplug主题皮肤切换之自定义样式-05

本文基于apkplug V1.6.9讲解

一 何为apkplug自定义样式切换

    apkplug主题切换包含两个层次

    1.通用主题,与系统主题相似

    2.自定义控件样式切换

根据上一篇文章讲解我们可以判定通用主题有其局限性,在很多情况下我们需要替换的是与我们应用本事相结合的自定义控件样式。如QQ聊天挂件

QQ皮肤,QQ聊天泡泡等。针对这种情况我们为apkplug新设计了一套接口,以满足开发者这方面的需求。

 

二 自定义控件样式切换

    自定义控件样式,顾名思义是我们开发者要求的自定义,因为它与开发的应用本身有关,不同的应用有不同的设计要求和格式。所以不是可提前统一定义的。

 

三 定义自定义控件样式替换接口

    根据apkplug的要求,开发者要替换某些自定义控件的样式就应该提前定义一套替换接口(模板),主题包可以根据该模板填充相应的样式ID传递给主应用。不过apkplug并没有要求模板的定义格式唯一规定的是该模板必须是一个java interface 如下:

public interface chatstyles {
	//我们协定如果 返回值小于0为未设置状态
	//主题样式版本,如果主题样式接口有所改变就利用这来判断
	public int Version();
	//聊天界面右侧Item 背景样式
	public int chat_right_msg_background();
	//聊天界面左侧Item 背景样式
	public int chat_left_msg_background();
	//聊天界面背景
	public int chatbackground();
}

四 将模板导出为一个jar包提供给主题包使用

五 主题包填充模板并传递给主应用

    1.主题包外部导入模板 jar包(类似osgi.jar包)

 

    2.填充模板 

public class chatstylesImp implements chatstyles{
	@Override
	public int chat_left_msg_background() {
		return R.drawable.chat_btn_left;
	}
	@Override
	public int chat_right_msg_background() {
		return R.drawable.chat_btn_right;
	}
	@Override
	public int Version() {
		return 0;
	}
	@Override
	public int chatbackground() {
		return R.drawable.menu_background;
	}
}


    3.将模板传递注册到apkplug中,以备将来某时被主应用引用

    

OSGIServiceAgent<ThemeControl> agent=new OSGIServiceAgent<ThemeControl>(mcontext,ThemeControl.class.getName());
//自定义控件样式切换
agent.getService().addStyles(mcontext, chatstyles.class.getName(), 
					new chatstylesImp()); 
//通用样式切换
agent.getService().setTheme(mcontext,mcontext.getBundle(), R.style.AppTheme_Another);

注:此处有一个小点需要注意的是 只有通用样式切换设置为该主题包其自定义控件样式才会生效

4.主应用在绘制界面时判断是否与可替换的主题样式 ?

    因为我们不知道何时可能有主题包会提供主题替换的样式,所以我们就假定在UI创建的时候对模板进行判断,如果有就用模板的样式ID设置到对应的UI控件上,如果没有就用默认的。所以主题样式切换需要刷新Activity


apkplug v1.6.9提供一个org.apkplug.Bundle.ThemeAgent类,它可以为我们自定监听模板变化状态
ThemeAgent<chatstyles> ta=new ThemeAgent<chatstyles>(mcontext,chatstyles.class);
chatstyles ct=ta.getService();
if(ct!=null){
	//表示有主题包提供可替换的主题样式
}else{
	//表示没有可替换的主题样式
}
自定义UI控件替换样式代码示例
chatstyles cs=ThemeChengFactory.getInstance(null).getService();
if(cs!=null){
	ViewHolder v= (ViewHolder)convertView.getTag();
	if(isComMsg){
	    if(cs.chat_left_msg_background()!=-1){
	    	v.tvContent.setBackgroundResource(cs.chat_left_msg_background());
	    }
	}else{
	    if(cs.chat_right_msg_background()!=-1){
		v.tvContent.setBackgroundResource(cs.chat_right_msg_background());
	    }
	}
}

5.主应用怎知有主题包提供了一套切换样式并重绘界面?

     样式是随时切换的,且可以通过网络下主题包动态切换.所以我们的主应用需要一套机制来判断合适切换UI样式。目前apkplug主题切换样式需要Activity重启来实现,我们提供以下接口来监听主题切换事件并在适当时机重启刷新Activity

BundleContext context=frame.getSystemBundleContext();
//RegThemeChengeListener 服务代理
OSGIServiceAgent<RegThemeChengeListener> agent=new OSGIServiceAgent<RegThemeChengeListener>
(context,RegThemeChengeListener.class.getName());
final RegThemeChengeListener service=agent.getService();
//插件启动级别为1(会自启) 并且不检查插件版本是否相同都安装
service.registerOnThemeListener(
    new OnThemeChengeListener(){
	@SuppressLint("NewApi")
	@Override
	public void afterChenged(
	org.osgi.framework.Bundle arg0, int arg1) {
		//主题切换了刷新界面
		MainActivity.this.recreate();
	//监听完注销该监听器,因为界面重刷以后会注册新的
		service.unregisterOnThemeListener(this);
	}
	@Override
	public void beforeChenge(
	org.osgi.framework.Bundle bb, int arg1,org.osgi.framework.Bundle tob, int arg2) {
								
	}
    });