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

本文详细介绍了如何在APKPlug V1.6.9中实现自定义控件样式切换,包括通用主题与自定义控件样式两部分,以及如何通过定义接口、导出Jar包、主题包填充模板并传递给主应用,最终在主应用中根据模板刷新界面。重点阐述了如何通过OSGI服务代理监听主题切换事件,实现界面的动态更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文基于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) {
								
	}
    });
### PyCharm 打开文件显示全的解决方案 当遇到PyCharm打开文件显示全的情况时,可以尝试以下几种方法来解决问题。 #### 方法一:清理缓存并重启IDE 有时IDE内部缓存可能导致文件加载异常。通过清除缓存再启动程序能够有效改善此状况。具体操作路径为`File -> Invalidate Caches / Restart...`,之后按照提示完成相应动作即可[^1]。 #### 方法二:调整编辑器字体设置 如果是因为字体原因造成的内容显示问题,则可以通过修改编辑区内的文字样式来进行修复。进入`Settings/Preferences | Editor | Font`选项卡内更改合适的字号大小以及启用抗锯齿功能等参数配置[^2]。 #### 方法三:检查项目结构配置 对于某些特定场景下的源码视图缺失现象,可能是由于当前工作空间未能正确识别全部模块所引起。此时应该核查Project Structure的Content Roots设定项是否涵盖了整个工程根目录;必要时可手动添加遗漏部分,并保存变更生效[^3]。 ```python # 示例代码用于展示如何获取当前项目的根路径,在实际应用中可根据需求调用该函数辅助排查问题 import os def get_project_root(): current_file = os.path.abspath(__file__) project_dir = os.path.dirname(current_file) while not os.path.exists(os.path.join(project_dir, '.idea')): parent_dir = os.path.dirname(project_dir) if parent_dir == project_dir: break project_dir = parent_dir return project_dir print(f"Current Project Root Directory is {get_project_root()}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值