android中appwidget設置支持復雜布局的方法


一直想知道如何在AppWidget里面添加 ListView,EditText 這些復雜的View.我們知道要在AppWidget里添加 View都是通過RemoteView來做到了,然而RemoteView本身功能很弱,支持的操作很少,而且支持RemoteView的Widget很少:
在Dev Guide中有下面這段:

復制代碼
 1 A RemoteViews object (and, consequently, an App Widget) can support the following layout classes:
2
3 * FrameLayout
4 * LinearLayout
5 * RelativeLayout
6
7 And the following widget classes:
8
9 * AnalogClock
10 * Button
11 * Chronometer
12 * ImageButton
13 * ImageView
14 * ProgressBar
15 * TextView
16
17 Descendants of these classes are not supported.
復制代碼

所以從這里可以知道,為什么在AppWidget里添加EditText會顯示LoadError了,因為本身它就不支持這些復雜的 Widget.

 

但我們又會有疑問了,為什么Google Search會有EditText呢?其實這些都是假象,並不是AppWidget支持EditText.

具體怎么回事,我猜有兩種情況:

1.一種確實是EditText但確不是AppWidget 支持的,而是集成到Home里面去了。

具體可以參考這里:http://www.eoeandroid.com/archiver/tid-1729.html

2.最新的SDK 1.6中,顯示在桌面的EditText只是一個ImageView,而這個ImageView的背景就是EditText的截圖了。我們點中這個“EditText”后,會調起一個Activity,

而這個Activity就是復雜輸入的EditText,並且會全屏顯示。所以我們就誤以會那是一個單純的EditText.

最近看過HTC Hero Sense UI的人都看到了,它的AppWidget是確實支持復雜Widget的,比如:Bookmark Widget:ListView/GridView,Twitter Widget:EditText. 這些確實是我們可以看到的,但它是怎么做到的呢?我也很想知道,AppWidget支持到那么強大,甚至超過了本身AP的功能,很搶眼。但不管是怎么實現的,我想人家肯定是花了大力氣去做到了,我猜想可能是將Google 提供的AppWidget進行了比較大的改動。我們查看一下framework下的appwidget:

復制代碼
1 pjq@gentoo-pjq ~/android/donut $ ls frameworks/base/core/java/android/appwidget/ -lh
2 total 60K
3 -rw-r--r-- 1 pjq users 7.9K 2009-09-29 21:49 AppWidgetHost.java
4 -rw-r--r-- 1 pjq users 12K 2009-09-29 21:49 AppWidgetHostView.java
5 -rw-r--r-- 1 pjq users 14K 2009-09-29 21:49 AppWidgetManager.java
6 -rw-r--r-- 1 pjq users 691 2009-09-29 21:49 AppWidgetProviderInfo.aidl
7 -rw-r--r-- 1 pjq users 5.6K 2009-09-29 21:49 AppWidgetProviderInfo.java
8 -rwxr-xr-x 1 pjq users 6.3K 2009-09-29 21:49 AppWidgetProvider.java
9 -rw-r--r-- 1 pjq users 1.5K 2009-09-29 21:49 package.html
復制代碼

可以看到,appwidget的文件很少,雖然不能說明什么,但按照正常的推理,文件少功能一般也強大不到哪里去,這種想法雖然有些牽強,但暫且就這樣認為吧。

所以我想HTC一定是將這里給改動了,以支持復雜的Widget,有知道內情的透露一點最好了。

要知道RemoteView的功能很少,特別是對事件處理的能力,都需要通過PendingIntent,傳到BroadcastReceiver去處理。所以這里對一些事件處理也僅限於比較簡單事件:比如說:Button Clicked,其它的我好像還沒怎么用過,orz…. 對復雜的View:比如ListView(當然這里還不支持,打個比方),ListView里面那么多Item,要設置Listener,要傳值,這些 RemoteView都不能像一個單純的Activity那樣處理,呵呵 ,扯遠了,如果能的話,我也就沒有必要這么費勁的寫這篇博客了。

寫這篇文章的時候,我已經實現了在 AppWidget里顯示ListView/GridView這些復雜的Widget了,我這里只說顯示,並不是說我已經能讓AppWidget支持 ListView/GridView了。所以我這里更傾向於教你如何在AppWidget里支持顯示ListView/GridView這些復雜的 Widget.

我們知道AppWidget只支持RemoteView,那哪些Widget是RemoteView呢,我來教你搜一下:

復制代碼
 1 pjq@gentoo-pjq ~/android/donut/frameworks/base/core/java/android/widget $ grep -i -n -A 1  @remoteview *.java
2 AbsoluteLayout.java:40:@RemoteView
3 AbsoluteLayout.java-41-public class AbsoluteLayout extends ViewGroup {
4 --
5 AnalogClock.java:39:@RemoteView
6 AnalogClock.java-40-public class AnalogClock extends View {
7 --
8 Button.java:58:@RemoteView
9 Button.java-59-public class Button extends TextView {
10 --
11 Chronometer.java:45:@RemoteView
12 Chronometer.java-46-public class Chronometer extends TextView {
13 --
14 FrameLayout.java:47:@RemoteView
15 FrameLayout.java-48-public class FrameLayout extends ViewGroup {
16 --
17 ImageButton.java:66:@RemoteView
18 ImageButton.java-67-public class ImageButton extends ImageView {
19 --
20 ImageView.java:55:@RemoteView
21 ImageView.java-56-public class ImageView extends View {現在沒什么問題。
22 --
23 LinearLayout.java:44:@RemoteView
24 LinearLayout.java-45-public class LinearLayout extends ViewGroup {
25 --
26 ProgressBar.java:122:@RemoteView
27 ProgressBar.java-123-public class ProgressBar extends View {
28 --
29 RelativeLayout.java:66:@RemoteView
30 RelativeLayout.java-67-public class RelativeLayout extends ViewGroup {
31 --
32 TextView.java:186:@RemoteView
33 TextView.java-187-public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
復制代碼

就是這些了,類名前面加了”@RemoteView”,和我前面列出的那些是不是一樣的呢?–對了,就是這些了,所以以后你想知道你在AppWidget支持哪些Widget就可以像我這樣去搜一下就知道了,這樣最適時。

寫到這里我已經將最關鍵的內容都已經寫出來了,還不明白?

其實簡單點講就是在一個Widget類前面加上”@RemoteView”,加上了它就等於說RemoteView可以支持它, RemoteView支持就等於是AppWidget支持這它了。

好了,現在你只需要自定義一些你需要的Widget,加上”@RemoteView”標記,你就可以在AppWidget里使用它了。

關於如何自定義一個Widget你完全可以參照frameworks/base/core/java/android/widget已有的這些Widget.依樣加一個。

其實如果你需要自定義一個Widget,比如說支持ListView,你可以先在一個activity里實現它,然后將它移到framework下面去。

這里說一下可能需要注意的地方:

1.如果有多個文件,需要Package的時候,名字最好按照這樣的形式:android.widget.bookmark

其中bookmark就是你要添加一個Widget存放的地方,這樣的話你就可以在frameworks/base/core/java/android/widget 目錄下新增bookmark文件夾,將java文件放在這個目錄下。

如果你新增的Widget只有一個java文件就可以不用這樣了,可以完全按照已經存在的Widget的樣子,直接將java文件放到frameworks/base/core/java/android/widget目錄下。

2.資源文件存放:

frameworks/base/core/res/res

資源文件都放到這個目錄下。

3.資源的引用:

要用這樣的方式引用:com.android.internal.R.drawable.**

4.記着在這個Customer Widget類名前加上”@RemoteView”標記.

這些都做完了,你就已經將一個自定義的Widget添加到framework了。之后要做的工作就是編譯整個工程了,重新生成SDK。

最后你就可以在AppWidget引用你新加的這個Widget了:com.widget.bookmark.***。

至此,你已經用上了你新加的這個Widget,並且可以加到AppWidget.

在新加Widget的時候可能會遇到的一些問題:

1.構造函數初始化問題。

如果在XML里寫的layout不能直接指定哪個構造函數進行初始化,如果你不確定會跑哪個構造函數,最好在每個構造函數里對加上log,這樣你就知道初始化時會跑哪個構造函數,並將初始化的工作加到里面。我當時就遇到了這個問題,因為用XML寫layout,你不能顯示調用哪個構造函數進行初始化,如果你將初始化的操作放到一個不會自動跑到的構造函數里面,那面你運行的時候就好像沒添加到Widget一樣。

2.其它的再說吧。

后繼我可能會寫如何添加Bookmark Widget(支持ListView/GridView,見過HTC Hero Sense UI嗎,就是那個樣子)到AppWidget,敬請期待!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM