android下apkplug通用主題(皮膚)切換解決方案之主應用-01

    該文章是基於apkplug V1.6.8 進行說明的 java

    咱們提供了一個demo作爲參考,項目下載地址爲:http://git.oschina.net/plug/IMThemeDemo android

 IMThemeDemo 實現了簡單的聊天泡泡切換功能,同時主題包(插件)是託管在apkplug的雲服務器上的。因此要閱讀項目的完整代碼能夠先看插件託管服務開發系列文章 <插件託管服務開發指南> git

demo運行效果圖: 服務器

  一,apkplug的主題說明 app

    apkplug主題解決方案摒棄了以往以圖片替換的形式切換效果的方式,轉而使用android原生資源和素材來切換UI樣式和效果。因此從體驗效果上是一次極大的提高。 框架

二,apkplug主題(皮膚)切換適用範圍 ide

    apkplug主題解決方案適用安卓界面的整個層次。其包括通用主題樣式,和自定義控件樣式切換兩個層面 佈局

    1.通用主題樣式 post

        與系統主題類似(Activity.setTheme()) 咱們在系統與app(插件)之間可新增一層主題,三層主題已疊加的形式造成最終結果 this

    

    2.自定義控件樣式

        大部分狀況下咱們的app都會本身設計主題,或者針對某寫控件設計本身的樣式,在這種模式下以上的通用主題便缺乏

其存在的意義了。所以apkplug也提供一種簡單有效的方案,容許開發者根據本身的需求定義自定義UI控件樣式的替換規則

在不失通用性兼容性簡潔性的狀況下達到最好的體驗。

三,主題(皮膚)切換流程

    1.通用主題樣式

        通用主題樣式有apkplug框架在底層適配,app開發過程當中無需過多考慮,只要主題包設置了通用主題樣式,app中的Activity 主題將自定替換(最前面的Activity需刷新後才能體現)

    2.自定義控件樣式

        自定義控件樣式的替換因爲每一個app的特殊性的緣由,無法作統一的規範。但apkplug通過幾個月的努力研發出一套簡單有效的實施方案,容許開發者自由定製適合本身app的替換接口。而主題包設計者根據該接口簡單配置便可。

四,自定義控件樣式替換接口舉例

    1.定義替換接口

        以 IMThemeDemo項目爲例,咱們須要替換聊天界面的聊天泡泡,因此自定義瞭如下的這樣一個接口

    com.apkplug.imthemedemo.themeinterface.chatstyles   

public interface chatstyles {
	//咱們協定若是 返回值小於0爲未設置狀態
	//主題樣式版本,若是主題樣式接口有所改變就利用這來判斷
	public int Version();
	//聊天界面右側Item 背景樣式
	public int chat_right_msg_background();
	//聊天界面左側Item 背景樣式
	public int chat_left_msg_background();
	//聊天界面背景
	public int chatbackground();
}

以上接口返回值是一個資源ID,它多是一張圖片或者一個xml佈局樣式。但它將由主題包(插件)提供。    

    2.主程序監聽主題切換事件

        以上咱們定義了一套UI樣式的切換接口,但咱們主應用並不知道合適會有主題包來替換咱們現有的樣式。因此咱們須要一個監聽器來監聽這個接口事件,一下是模板代碼 (此處設計一些OSGI服務方面的知識,不明白的同窗可看 OSGI服務基本原理),但咱們提供模板代碼,開發者能夠先實如今研究其原理。

        定義一個專門監聽接口事件變化的單例類

        com.apkplug.imthemedemo.ThemeChengFactory       

mcontext.addServiceListener(
	new ServiceListener(){
	@Override
	public void serviceChanged(ServiceEvent event) {
		switch  (event.getType()) {
			case  ServiceEvent.REGISTERED:
				if  (ref  ==   null ) {
					//當有主題包註冊了該接口,意味着它爲咱們提供樣式切換的具體資源了
					ref  =  event.getServiceReference();
					service  =  (chatstyles) mcontext.getService(ref);
				}
				break ;
			case  ServiceEvent.UNREGISTERING:
				if  (ref  ==  event.getServiceReference()) {
					//主題包註銷了該接口,意味着它再也不提供切換的具體資源了
					mcontext.ungetService(ref);  
					service  =   null ;
					ref  =   null ;
				}
				break ;
		}
							
	}
},String.format("(objectclass=%s)",chatstyles.class.getCanonicalName()) );


    3.界面建立時判斷是否切換樣式

        上一步咱們已經實現了監聽接口註冊與註銷事件,但咱們尚未將切換的樣式綁定到具體的控件上來。這一步咱們將完成這一塊工做

        根據上一段代碼咱們得知 ThemeChengFactory類中的chatstyles service 成員變量在主題包註冊之後不爲空,沒有註冊時爲空。這樣咱們便經過判斷 serice是否爲空來判斷是否有主題樣式可切換。同時咱們判斷返回值是否爲-1來判斷主題包提供的樣式是否完整

        注:咱們約定主題包可能只提供了接口的部分控件樣式,其餘樣式返回-1 表示沒有提供相應資源

   4.在建立控件時設置樣式

      1)聊天泡泡樣式

         com.apkplug.imthemedemo.adapter.ChatMsgViewAdapter 

chatstyles cs=ThemeChengFactory.getInstance(null).getService();
if(cs!=null){
   //chatstyles 不爲空表示有主題包提供替換的資源
   ViewHolder v= (ViewHolder)convertView.getTag();
   if(isComMsg){
	if(cs.chat_left_msg_background()!=-1){
	//主題包提供的該控件資源ID
	    v.tvContent.setBackgroundResource(cs.chat_left_msg_background());
	}
    }else{
	if(cs.chat_right_msg_background()!=-1){
	    //主題包提供的該控件資源ID
	    v.tvContent.setBackgroundResource(cs.chat_right_msg_background());
	}
    }
}

    2)聊天界面背景圖片樣式

       com.apkplug.imthemedemo.activity.ChatActivity

chatstyles cs=ThemeChengFactory.getInstance(null).getService();
if(cs!=null){
    //有主題包提供接口樣式
    if(cs.chatbackground()!=-1){
	   //提供該控件樣式資源ID
	   mListView.setBackgroundResource(cs.chatbackground());
    }
}

    5.監聽主題切換事件,重刷UI

       第四步咱們完成了在UI建立刷新時判斷並替換新的樣式,但目前爲止咱們還不僅到何時應該刷新UI。如下將解決這個問題

       當主題包設置了可替換主題之後,apkplug會給監聽器發送主題切換事件,咱們可註冊這樣一個監聽器實時監聽主題切換事件刷新activity從而實現實時換膚的功能。

      com.apkplug.imthemedemo.activity.MainActivity

public void ListenerTheme(){
BundleContext context=frame.getSystemBundleContext();
ServiceReference reference=context.getServiceReference(RegThemeChengeListener.class.getName());
   if(null!=reference){
    //查詢主題切換事件監聽器註冊服務
    final RegThemeChengeListener service=(RegThemeChengeListener) context.getService(reference);
    if(service!=null){
    	//找到服務註冊一個監聽器,實時監聽主題切換動態
    	service.registerOnThemeListener(
    		new OnThemeChengeListener(){
			@SuppressLint("NewApi")
			@Override
			public void afterChenged(org.osgi.framework.Bundle arg0, int arg1) {
				//主題切換之後咱們重刷Activity
				MainActivity.this.recreate();
				System.out.println("afterChenged");
				//把上一個監聽器註銷,由於界面被重刷之後咱們又註冊了一個新的監聽器
				service.unregisterOnThemeListener(this);
			}
			@Override
			public void beforeChenge(
				org.osgi.framework.Bundle bb, int arg1,org.osgi.framework.Bundle tob, int arg2) {
								
			}
    	});
    }
    context.ungetService(reference);
   }
}    


      咱們沒有在ChatActivity界面設置監聽器重刷的緣由是,每次設置主題咱們都會到主題包的Activity中,而且返回之後每次都從新進入ChatActivity界面,因此ChatActivity不須要重刷(由於它每次都是新的)

完成以上步驟之後主應用完成了,但這還不夠由於咱們尚未開發主題包(插件)呢。下一節將講解怎麼開發主題包,它一樣簡單快捷

相關文章
相關標籤/搜索