Android -- AppWidget 高级篇


3.1 AppWidget到底支持哪些view

在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的文件很少,虽然不能说明什么,但按照正常的推理,文件少功能一般也强大不到哪里去,这种想法虽然有些牵强,但暂且就这样认为吧。


3.2 如何自定义RemoteViews

要知道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 呢,我来教你搜一下:

  1. 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",和我前面列出的那些是不是一样的呢?所以,如果你需要自定义一个(或者是一个已定义的复杂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.

  1. 记着在这个Customer Widget类名前加上"@RemoteView"标记.

这 些都做完了,你就已经将一个自定义的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。

  • 1
  • 2
  • 3
  • 下一页

相关内容

    暂无相关文章