1. 一个AppWidgetProviderInfo对象
这个对象通常是在 res/xml目录里设置的
2. 一个AppWidgetProvider类的实现
通常是需要创建一个AppWidgetProvider类的子类,来实现自定义小应用update, enabled, disabled和删除时触发的方法。
3. 一个布局
这个布局是widget初始启动时出现的布局。
举一个最最简单的例子:
1. 先在AndroidManifest.xml中定义桌面小应用
<receiver android:name=".android.widget.NoteWidgetProvider" android:label="@string/app_widget_notes" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_note_info" /> </receiver>
2. 在 res / xml 目录下设置应用的基本信息
xml/widget_note_info.xml
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/widget_note" android:minWidth="294dip" android:minHeight="294dip"> </appwidget-provider>
3. 在 res / layout 目录下设置应用启动的初始布局
layout/widget_note.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="294dip" android:layout_height="294dip"> <ImageView android:id="@+id/widget_bg_image" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <TextView android:id="@+id/widget_text" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingTop="40dip" android:paddingLeft="15dip" android:paddingRight="15dip" android:textSize="14sp" android:textColor="#FF663300" android:maxLines="12" android:lineSpacingMultiplier="1.2" /> </FrameLayout>
4. java源码实现AppWidgetProvider类中的自定义update, enable, disable, delete方法
public class NoteWidgetProvider extends AppWidgetProvider { private static final String TAG = NoteWidgetProvider.class.getSimpleName(); @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { ComponentName thisWidget = new ComponentName(context, NoteWidgetProvider.class); int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); for (int i = 0; i < allWidgetIds.length; i++) { int widgetId = allWidgetIds[i]; RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_note); remoteViews.setImageViewResource(R.id.widget_bg_image, R.drawable.empty_sketchy); Intent intent = new Intent(context, NoteWidgetProvider.class); intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); appWidgetManager.updateAppWidget(widgetId, remoteViews); } } }
5. 如果要点击 widget 启动一个 activity, 需要修改4中的代码如下:
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { ComponentName thisWidget = new ComponentName(context, NoteWidgetProvider.class); int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); for (int i = 0; i < allWidgetIds.length; i++) { int widgetId = allWidgetIds[i]; Intent intent = new Intent(context, NoteEditActivity.class); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_note); remoteViews.setImageViewResource(R.id.widget_bg_image, R.drawable.empty_sketchy); remoteViews.setOnClickPendingIntent(R.id.widget_text, pendingIntent); appWidgetManager.updateAppWidget(widgetId, remoteViews); } }
6. NoteEditActivity的布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/widget83" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"> <LinearLayout android:id="@+id/layout_notes" android:layout_width="fill_parent" android:layout_height="388dp" android:orientation="vertical"> <EditText android:id="@+id/edit_notes" android:layout_width="fill_parent" android:layout_height="fill_parent" android:hint="Please input!" android:textSize="18sp" /> </LinearLayout> <Button android:id="@+id/button_save" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Save" android:gravity="center" android:layout_gravity="right" /> </LinearLayout>
7. 点击 NoteEditActivity 的按钮,返回widget页面的方法
public class NoteNote extends Activity { private static final String TAG = NoteNote.class.getSimpleName(); private int mAppWidgetId; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); this.setContentView(R.layout.note_edit); Intent t = getIntent(); mAppWidgetId = t.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); Log.i(TAG,"mAppWidgetId=" + mAppWidgetId); Button b = (Button) this.findViewById(R.id.button_save); b.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { RemoteViews views = new RemoteViews(getApplicationContext().getPackageName(), R.layout.widget_note); views.setImageViewResource(R.id.widget_bg_image, R.drawable.empty_sketchy); //设置完成后需要获取AppWidgetManager,对指定的widget进行更新,才能使设置生效。 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext()); appWidgetManager.updateAppWidget(mAppWidgetId, views); finish(); } }); }
8. 在WIDGET里输入点内容,使用最简单的方法保存起来,然后更新WIDGET时显示被修改的内容。
public class NoteWidgetProvider extends AppWidgetProvider { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { for (int i = 0; i < allWidgetIds.length; i++) { int widgetId = allWidgetIds[i]; // 显示保存的输入内容 SharedPreferences settings = context.getSharedPreferences("MyPrefsFile", Context.MODE_PRIVATE); String notes = settings.getString("my_abcdefg", ""); Log.i(TAG,"NOTES=" + notes); Intent intent = new Intent(context, NoteNote.class); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_note); remoteViews.setImageViewResource(R.id.widget_bg_image, R.drawable.empty_sketchy); // 将保存的输入内容显示在WIDGET的TEXTVIEW里。 remoteViews.setTextViewText(R.id.widget_text, notes); remoteViews.setOnClickPendingIntent(R.id.widget_text, pendingIntent); appWidgetManager.updateAppWidget(widgetId, remoteViews); } } } // 将输入的信息保存起来 public class NoteNote extends Activity { ....... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.note_edit); Intent t = getIntent(); mAppWidgetId = t.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); // 将保存的信息显示在输入框内 SharedPreferences settings = getSharedPreferences("MyPrefsFile", Context.MODE_PRIVATE); notes = settings.getString("my_abcdefg", ""); Log.i(TAG,"NOTES=" + notes); et = (EditText) findViewById(R.id.edit_notes); et.setText(notes); Button b = (Button) this.findViewById(R.id.button_save); b.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { if(et!=null) notes = et.getText().toString(); Log.i(TAG,"after onclick, text is =" + notes); // 将修改后的输入信息保存起来 SharedPreferences.Editor editor = getSharedPreferences("MyPrefsFile", Context.MODE_PRIVATE).edit(); editor.putString("my_abcdefg", notes); editor.commit(); // 调用widget页面,并将修改后的内容显示在widget内。 RemoteViews views = new RemoteViews(getApplicationContext().getPackageName(), R.layout.widget_note); views.setImageViewResource(R.id.widget_bg_image, R.drawable.empty_sketchy); views.setTextViewText(R.id.widget_text, notes); //设置完成后需要获取AppWidgetManager,对指定的widget进行更新,才能使设置生效。 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext()); appWidgetManager.updateAppWidget(mAppWidgetId, views); finish(); } }); } }