淺談如何給appwidget添加複雜view

 

    我們都知道android原生的widget只支持極少數幾個簡單的view,所以功能及其簡單。很多人都希望在AppWidget添加ListView、GridView等複雜的view來實現更爲複雜的功能。我們知道要在AppWidget裏添加 View都是通過RemoteView來做到了,然而RemoteView本身功能很弱,支持的操作很少,而且支持RemoteView的Widget很少:  

A RemoteViews object (and, consequently, an App Widget) can support the following layout classes: 

* FrameLayout 

* LinearLayout 

* RelativeLayout 

And the following widget classes: 

* AnalogClock 

* Button 

* Chronometer 

* ImageButton 

* ImageView 

* ProgressBar 

* TextView 

Descendants of these classes are not supported.  

 

 

   要實現上述功能通常有兩種做法:

1. 修改framework層:

      以上這些view都是在類名前面加了”@RemoteView” ,這樣才被AppWidget所識別。網上有人流傳着既然通過@RemoteView這個標籤來確定RemoteView是否支持view.在view的源文件加上@RemoteView這個標籤就可以支持了。這是錯誤的一個思想,添加RemoteView這個標籤能實現的僅僅是能夠在給AppWidget添加這個view的時候不會報錯,但是確無法實現你所想要的功能。我們知道RemoteView是用來描述一個垮進程顯示的view。 所以你的view還需要做很多有關進程間通信的事情。這個比較複雜,一般只有對framework比較牛的大神纔可以做,如HTC等廠家就支持。android 3.0以後的版本也可以支持一些複雜的RemoteView,可是現在還沒有開源~~~

 

修改framework層的優點是:可以讓所有允許於該平臺的launcher都可以添加這些複雜的AppWidget。

缺點是:需要的知識技能太深,一般人無法匹敵。

 

2. 修改launcher

    我們知道諸如ADW ,GO桌面,launcher plus等主流通用桌面都可以支持帶有listview的AppWidget。他們是如何實現的呢?他們的代碼中都包含有一個mobi.intuitit.android.widget ,代碼發佈於http://code.google.com/p/android-launcher-plus/ 

通過在launcher中添加上述代碼便可以使用針對這個框架實現的一些appwidget,例如桌面滾動聯繫人:ContactWidget。

 具體如何實現,這個網上的資料不是很多,我也沒有研究很深入,有興趣的童鞋可以嘗試着反編譯ContactWidget查看他的實現流程。

 

  上述修改方法的優點是:具有一定的通用性,針對系統開發人員來說,按照上述修改了launcher便可以使用這一個框架的一系列的appwidget。對於應用開發人員來說開發的appwidget可以使用在諸如ADW,go桌面等這一系列的桌面上

缺點:appwidget的編寫較爲複雜 ,在我的資源裏邊有一個使用這個框架編寫的widget,大家有興趣的可以看看~~http://download.csdn.net/source/3305935 

 

3.實現一個僞widget

    如果你需要實現的是一個僅能在你自己的launcher上使用的widget,那麼下面介紹的方法便很適合你。

  不知道大家有沒有見過Dell Stage這個桌面,反編譯(邪惡的笑)後便會驚奇的發現,那些看似widget的widget,其實都不是appwidget,而是一個個activity,震驚!愕然!有木有?

稍稍研究之後便發現其中的奧祕並不複雜,甚至比之前的兩種方式更爲簡單。

public final class Launcher extends Activity implements

View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,

AllAppsView.Watcher {

 原生的launcher.java中Launcher是繼承於Activity的,所以無法在其中嵌入activity,所以我們首先需要修改public final class Launcher extends ActivityGroup implements

View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,

AllAppsView.Watcher {

繼承於 ActivityGroup之後便可以在 Launcher中嵌入activity了。

使用

ActivityGroup.getLocalActivityManager()獲得LocalActivityManager

然後LocalActivityManager.startActivity(id, intent).getDecorView() 

;可以得到指定intent的view。

例如:

我在launcher中自定義了一個activity,test.class:

LocalActivityManager lam;

ActivityGroup group;

lam = group.getLocalActivityManager();

Intent intent = new Intent(group,test.class);

Window w = lam.startActivity(id, intent);

View subactivityView =w.getDecorView();

 

把subactivityView嵌入後便可以得到下面的結果。我按照原來launcher中添加appwidget的添加流程,仿寫了一個添加activity的框架。

 

由於懶得添加新資源,所以使用的是原來系統自帶的資源,哈哈,最上邊的Wallpapers就是我新添加的一個選項~

 

 

原理與這個類似:http://www.cnblogs.com/over140/archive/2010/09/07/1820876.html 

 

只要將這個得到的view嵌入launcher中就可以了,具體如何嵌入的方法可以參看launcher中添加folder,appwidget的流程方法。

 需要注意的是:LocalActivityManager.startActivity(id, intent)能夠添加只是同一個應用裏邊的Activity,如果你試圖加載一個外部的activity就會報錯。難道我們無法像appwidget一樣,將widget與launcher分離開來嗎?其實這個也是有方法的,只要將你外部定義

widget的AndroidManifest.xml中的android:sharedUserId修改成與launcher2的一致,就可以讓你的widget與launcher2運行在同一個進程中,這樣就可以相互調用了。

 

上述做法的優點是:操作簡單,而且理論上可以支持所有activity的view,開發appwidget就像開發普通activity一樣。

 缺點是:這麼操作會讓launcher佔用很多的內存,默認dalvik爲每個應用分配的空間爲16M,如果添加了很多appwidget的話,很可能造成內存溢出。

 

很久沒有寫博客拉,寫得有亂阿~~各位看官輕拍阿~~

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章