Widget~~1--主类

Android 2.2 SDK中我们可能首次启动模拟器可以看到和以前不一样的是多出了一个绿色的小机器人提示信息,Google给我们了演示了Android中如何通过 RemoteView和简单的图片轮换方式实现动画效果在桌面小工具中,appWidget的基类时AppWidgetProvider类,不过 Widget本身的生命周期管理并非Activity,相对于的而是BroadcastReceiver广播方式处理的,Android 2.2新增的Widget的实现大家可以从中学习到很多有用的知识。

OK废话少说就一个ProtipWidget.java类继承于AppWidgetProvider

 

1 public class ProtipWidget extends AppWidgetProvider {
2     public static final String ACTION_NEXT_TIP = " com.android.misterwidget.NEXT_TIP " ; // 定义action切换到下一条提示
3       public static final String ACTION_POKE = " com.android.misterwidget.HEE_HEE " ; // 唤醒小机器人
4  
5     public static final String EXTRA_TIMES = " times " ;
6
7     public static final String PREFS_NAME = " Protips " ;
8     public static final String PREFS_TIP_NUMBER = " widget_tip " ;
9
10     private static Random sRNG = new Random(); // 轮换图片用到的,生成一个静态的随机数生成器
11
12     private static final Pattern sNewlineRegex = Pattern.compile( " *\\n * " );
13     private static final Pattern sDrawableRegex = Pattern.compile( " *@(drawable/[a-z0-9_]+) * " ); 
14
15     // 初始化时Droid是眼睛没有睁开,同时没有信息提示
16     private int mIconRes = R.drawable.droidman_open;
17     private int mMessage = 0 ;
18
19     private AppWidgetManager mWidgetManager = null ;
20     private int [] mWidgetIds;
21     private Context mContext;
22
23     private CharSequence[] mTips;
24
25     private void setup(Context context) {
26         mContext = context;
27         mWidgetManager = AppWidgetManager.getInstance(context);
28         mWidgetIds = mWidgetManager.getAppWidgetIds( new ComponentName(context, ProtipWidget. class ));
29
30         SharedPreferences pref = context.getSharedPreferences(PREFS_NAME, 0 );
31         mMessage = pref.getInt(PREFS_TIP_NUMBER, 0 );
32
33         mTips = context.getResources().getTextArray(R.array.tips);
34
35         if (mTips != null ) {
36             if (mMessage >= mTips.length) mMessage = 0 ;
37         } else {
38             mMessage = - 1 ;
39         }
40
41     }
42
43     public void goodmorning() {  // Android开发网提示线程中轮换图片,使用了500,200,100等这样的0.5秒休眠,0.2秒休眠实现了动画的间隔效果
44         mMessage = - 1 ;
45         try {
46             setIcon(R.drawable.droidman_down_closed);
47             Thread.sleep( 500 );
48             setIcon(R.drawable.droidman_down_open);
49             Thread.sleep( 200 );
50             setIcon(R.drawable.droidman_down_closed);
51             Thread.sleep( 100 );
52             setIcon(R.drawable.droidman_down_open);
53             Thread.sleep( 600 );
54         } catch (InterruptedException ex) {
55         }
56         mMessage = 0 ;
57         mIconRes = R.drawable.droidman_open;
58         refresh();
59     }
60
61     @Override
62     public void onReceive(Context context, Intent intent) { // 上面已经讲到了,appWidget是基于broadcastreceiver类的,所以说需要响应onReceive通过 action来驱动事件。
63         setup(context);
64
65         if (intent.getAction().equals(ACTION_NEXT_TIP)) {
66             mMessage = getNextMessageIndex();
67             SharedPreferences.Editor pref = context.getSharedPreferences(PREFS_NAME, 0 ).edit();
68             pref.putInt(PREFS_TIP_NUMBER, mMessage);
69             pref.commit();
70             refresh();
71         } else if (intent.getAction().equals(ACTION_POKE)) {
72             blink(intent.getIntExtra(EXTRA_TIMES, 1 ));
73         } else if (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_ENABLED)) {
74             goodmorning();
75         } else {
76             mIconRes = R.drawable.droidman_open;
77             refresh();
78         }
79     }
80
81     private void refresh() {  // 管理如果有多个本widget执行需要逐个更新
82         RemoteViews rv = buildUpdate(mContext);
83         for ( int i : mWidgetIds) {
84             mWidgetManager.updateAppWidget(i, rv);
85         }
86     }
87
88     private void setIcon( int resId) {
89         mIconRes = resId;
90         refresh();
91     }
92
93     private int getNextMessageIndex() {
94         return (mMessage + 1 ) % mTips.length;
95     }
96
97     private void blink( int blinks) {
98             if (mMessage < 0 ) return ;
99
100     // 比较有意思的就是小绿人眼睛的一开一闭,这里使用的是图片轮换方式来实现动画效果,在appWidget中我们可以用的控件十分少
101
102         setIcon(R.drawable.droidman_closed);
103         try {
104             Thread.sleep( 100 );
105             while ( 0 <-- blinks) {
106                 setIcon(R.drawable.droidman_open);
107                 Thread.sleep( 200 );
108                 setIcon(R.drawable.droidman_closed);
109                 Thread.sleep( 100 );
110             }
111         } catch (InterruptedException ex) { }
112         setIcon(R.drawable.droidman_open);
113     }
114
115     public RemoteViews buildUpdate(Context context) {
116         RemoteViews updateViews = new RemoteViews(
117             context.getPackageName(), R.layout.widget); // 映射布局,widget.xml文件的源码在下面可以找到
118
119         // 按下bubble的事件,对应action_next_tip动作
120         Intent bcast = new Intent(context, ProtipWidget. class );
121         bcast.setAction(ACTION_NEXT_TIP);
122         PendingIntent pending = PendingIntent.getBroadcast(
123             context, 0 , bcast, PendingIntent.FLAG_UPDATE_CURRENT);
124         updateViews.setOnClickPendingIntent(R.id.tip_bubble, pending);
125
126       // 这里为action_poke
127         bcast = new Intent(context, ProtipWidget. class );
128         bcast.setAction(ACTION_POKE);
129         bcast.putExtra(EXTRA_TIMES, 1 );
130         pending = PendingIntent.getBroadcast(
131             context, 0 , bcast, PendingIntent.FLAG_UPDATE_CURRENT);
132         updateViews.setOnClickPendingIntent(R.id.bugdroid, pending);
133
134         // Tip bubble text
135         if (mMessage >= 0 ) {
136             String[] parts = sNewlineRegex.split(mTips[mMessage], 2 );
137             String title = parts[ 0 ];
138             String text = parts.length > 1 ? parts[ 1 ] : "" ;
139
140             // Look for a callout graphic referenced in the text
141             Matcher m = sDrawableRegex.matcher(text);
142             if (m.find()) {
143                 String imageName = m.group( 1 );
144                 int resId = context.getResources().getIdentifier(
145
146                     imageName, null , context.getPackageName());
147                 updateViews.setImageViewResource(R.id.tip_callout, resId);
148                 updateViews.setViewVisibility(R.id.tip_callout, View.VISIBLE);
149                 text = m.replaceFirst( "" );
150             } else {
151                 updateViews.setImageViewResource(R.id.tip_callout, 0 );
152                 updateViews.setViewVisibility(R.id.tip_callout, View.GONE);
153             }
154
155             updateViews.setTextViewText(R.id.tip_message,
156                 text);
157             updateViews.setTextViewText(R.id.tip_header,
158                 title);
159             updateViews.setTextViewText(R.id.tip_footer,
160                 context.getResources().getString(
161                     R.string.pager_footer,
162                     ( 1 + mMessage), mTips.length));
163             updateViews.setViewVisibility(R.id.tip_bubble, View.VISIBLE);
164         } else {
165             updateViews.setViewVisibility(R.id.tip_bubble, View.INVISIBLE);
166         }
167
168         updateViews.setImageViewResource(R.id.bugdroid, mIconRes);
169
170         return updateViews;
171     }
172 }
173

 

 

你可能感兴趣的:(widget)