在Android 2.2 SDK中我們首次啟動模擬器可以看到和以前不一樣的是多出了一個綠色的小機器人提示信息,Google給我們了演示了Android中如何通過 RemoteView和簡單的圖片輪換方式實現動畫效果在桌面小工具中,appWidget的基類時AppWidgetProvider類,不過 Widget本身的生命周期管理並非Activity,相對於的而是BroadcastReceiver廣播方式處理的。一直想知道如何在AppWidget裡面添加 ListView,EditText 這些復雜的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.
從這裡可以知道,為什麼在AppWidget裡添加 EditText會顯示LoadError了,因為本身它就不支持這些復雜的 Widget.
但我們又會有疑問了, 為什麼Google Search會有EditText呢?其實這些都是假象,並不是AppWidget支持EditText。細心的你應該會發現, AnalogClock也不是如Button,TextView的簡單Widget ,其實 AnalogClock也是Google自定義的RemoteViews。
在網上可以看到,AppWidget很多特效,它確實支持了復雜Widget,比如:ListView/GridView,EditText. 這些確實是我們可以看到的,但它是怎麼做到的呢?我也很想知道,AppWidget支持到那麼強大,甚至超過了本身AP的功能,很搶眼。但不管是怎麼實現 的,我想人家肯定是花了大力氣去做到了,我猜想可能是將Google 提供的AppWidget進行了比較大的改動。我們查看一下framework下的appwidget:
:ls frameworks/base/core/java/android/appwidget/ -lh
total 60K
-rw-r--r-- 1 pjq users 7.9K 2009-09-29 21:49 AppWidgetHost.java
-rw-r--r-- 1 pjq users 12K 2009-09-29 21:49 AppWidgetHostView.java
-rw-r--r-- 1 pjq users 14K 2009-09-29 21:49 AppWidgetManager.java
-rw-r--r-- 1 pjq users 691 2009-09-29 21:49 AppWidgetProviderInfo.aidl
-rw-r--r-- 1 pjq users 5.6K 2009-09-29 21:49 AppWidgetProviderInfo.java
-rwxr-xr-x 1 pjq users 6.3K 2009-09-29 21:49 AppWidgetProvider.java
-rw-r--r-- 1 pjq users 1.5K 2009-09-29 21:49 package.html
可以看 到,appwidget的文件很少,雖然不能說明什麼,但按照正常的推理,文件少功能一般也強大不到哪裡去,這種想法雖然有些牽強,但暫且就這樣認為吧。
要知道RemoteView的功能很少,特別是對事件處理的能力,都需要通過PendingIntent,傳到BroadcastReceiver去處理。所以這裡對一些事件處理也僅限於比較簡單事 件:比如說:Button Clicked,其它的我好像還沒怎麼用過,對復雜的View:比如!ListView(當然這裡還不支持,打個比方),!ListView裡面那麼多Item,要設置Listener,要傳值,這些 RemoteView都不能像一個單純的Activity那樣處理,如果要實現,則需要更加復雜的手段,通過廣播實現。
由於日歷小部件需要實現onClick事件,顯示日歷,動畫效果等復雜的操作和效果,AppWidget支持的操作遠遠不能滿足,這就需要修改framework裡的代碼,目前我已經在AppWidget裡顯示CalendarView(日歷)、Viewflipper復雜的Widget,同時實現了如何讓這些自定義的RemoteViews與AppWidget進行交互。現在讓我詳細介紹如何在AppWidget裡自定義CalendarView(當然是繼承自view咯 ^_^)和Viewflipper(只是在原基礎上做了修改)這些復雜的 Widget.
我們知道AppWidget只支持RemoteView,哪些Widget是RemoteView 呢,我來教你搜一下:
就是這些了,類名前面加了"@RemoteView",和我前面列出的那些是不是一樣的呢?所以,如果你需要自定義一個(或者是一個已定義的復雜View如listview)作為RemoteViews使用,你就必須在其類名前加"@RemoteView"標識。
關於如何自定義一個Widget你完全可以參照frameworks/base/core/java/android/widget已有的這些Widget,照樣寫一個。
其實如果你需要自定義一個Widget,比如說支持ListView,你可以先在一個activity裡實現它,然後將它移到framework下面去。
這 裡說一下可能需要注意的地方:
1.如果有多個文件,需要Package的時候,名字最好按照這樣的形 式:android.widget.CalendarView
其中CalendarView就是你要添加一個Widget存放的地方,這樣的話你就可以在 frameworks/base/core/java/android/widget 目錄下新增CalendarView文件夾,將java文件放在這個目錄下。
如果你新增的Widget只有一個java文件就可以不用這樣了,可以 完全按照已經存在的Widget的樣子,直接將java文件放到frameworks/base/core/java/android/widget目錄 下。
2.資源文件存放:
frameworks/base/core/res/res
資 源文件都放到這個目錄下。
3.資源的引用:
要用這樣的方式引用:com.android.internal.R.drawable.
這 些都做完了,你就已經將一個自定義的Widget添加到framework了。之後要做的工作就是編譯整個工程了(在這裡教一個比較懶的方法,直接編譯frameworks 就OK,命令:
:mmm frameworks/base/
:adb push out/target/product/msm7627_ffa/system/framework/
framework.jar /system/framework/)。
最後你就可以在AppWidget引用你自定義的這個Widget了:
com.widget.CalendarView。