RemoteView 自定義桌面小部件
效果如上圖, class AppWidgetProvider extends BroadcastReceiver,不難看出桌面小部件本質上是一個廣播,至於爲什麼是一個廣播的形勢,我猜...是因爲桌面小部件運行在SystemService進程中,通過PendingIntent這種方式傳遞,避免了自己寫IPC通信。
自定義小部件統共分幾步
1.定義小部件界面
在layout 下創建xml 文件
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/tv_content"
android:src="@mipmap/ic_launcher"
android:gravity="center"
android:textSize="20sp"
android:layout_width="100dp"
android:layout_height="100dp" />
</RelativeLayout>
2.定義小部件配置信息
通過as自帶的創建app widget功能會自動創建該文件,否則需要手動指定,定義小部件刷新,最小寬高等信息
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="@layout/new_app_widget"
android:initialLayout="@layout/new_app_widget"
android:minHeight="110dp"
android:minWidth="110dp"
android:previewImage="@mipmap/ic_launcher"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen" />
- resizeMode 小部件可伸縮方向
- minHeight,minWidth 小部件最寬高
- previewImage 拖動到桌面前的預覽圖片
- nitialLayout初始化佈局
- updatePeriodMillis小部件的刷新間隔,單位是秒,默認是一天
3. 繼承AppWidgetProvider
public class NewAppWidget extends AppWidgetProvider {
private static final String fs="com.example.admin.customview.click";
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent clickIntent = new Intent();
clickIntent.setAction(fs);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, clickIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.tv_content,pendingIntent);
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
@Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
@Override
public void onReceive(final Context context, Intent intent) {
super.onReceive(context, intent);
Log.d("88888888888", "onReceive: ");
String action = intent.getAction();
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
//判斷是否是自定義點擊action
if (action.equals(fs)){
Toast.makeText(context, "clicked it", Toast.LENGTH_SHORT).show();
new Thread(new Runnable() {
@Override
public void run() {
AppWidgetManager manager = AppWidgetManager.getInstance(context);
for (int i = 0; i < 37; i++) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
remoteViews.setImageViewBitmap(R.id.tv_content,rotateBitmap(bitmap,i*10));
Intent clickIntent = new Intent();
clickIntent.setAction(fs);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, clickIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.tv_content,pendingIntent);
Log.d("8888888", "run: ");
manager.updateAppWidget(new ComponentName(context,NewAppWidget.class),remoteViews);
SystemClock.sleep(30);
}
}
}).start();
}
}
private Bitmap rotateBitmap(Bitmap bitmap,float degree) {
Matrix matrix = new Matrix();
matrix.reset();
matrix.setRotate(degree);
Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return bm;
}
}
- onEnabled 當小部件第一次添加到桌面時調用
- onUpdate 當小部件被添加或者更新時調用
- onReceive 作爲一個廣播,當接接受到Intent消息的時候調用
4.在AndroidManifest 中聲明小部件
<receiver android:name=".NewAppWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.example.admin.customview.click" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/new_app_widget_info" />
</receiver>
第一個action 作爲小部件的標記存在,在安裝時系統讓系統檢測到包含小部件組件
第二個action 用於BrocastReceiver 接受點擊事件