<span style="font-family: Arial, Helvetica, sans-serif;">Widget (微件、小组件)</span>
1)写布局文件对于widget的布局文件有限制!不是所有的组件都能够使用的。 容器类视图目前只支持四种:LinearLayout,RelativeLayout,FrameLayout,GridLayout容器类目前支持的视图组件:AnalogClock 模拟时钟ChronoMeter 电子时钟、计时器ButtonImageButtonTextViewImageViewViewFlipper等(随着SDK版本的迭代,可支持的视图数量在增加)不能用的:自定义视图一概不能用(View) 上述可用视图的子类一概不能用 (比如EditText)2)写一个描述文件,用来描述widget的一些属性 写在res/xml文件下
有四个属性必须声明:minWidht/minHeight:小组件拖动到屏幕上之后,系统会根据你指定的这两个值估算会占用多少格。屏幕上会被系统划分为4*4个格子,每个格子具体尺寸,根据屏幕尺寸和密度的不同会有所差异。Google早期给出了一个minWidth/minHeight的经验计算公式:70*n-30 dp在高密度大尺寸屏幕下还有一个经验公式:74*n-2
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="250dp"
android:minHeight="110dp"
android:updatePeriodMillis="1800000"
android:initialLayout="@layout/widget_layout"
>
</appwidget-provider>
updatePeriodMillis 系统会按照该时间间隔,通过发送系统广播的方式,来更新Widget的显示内容。发送的系统广播的action是android.appwidget.action.APPWIDGET_UPDATE,widget一旦受到该广播,会调用onUpdate方法。
updatePeriodMillis指定的时间间隔不得低于30分钟所对应的毫秒值。低于该值,则设定无效,系统依然会每隔半小时发送一次广播。
3)写一个类,继承自AppWidgetProvider类
XML文件
<TextView
android:id="@+id/tv_widget_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:padding="8dp"
android:text="XXX"
/>
<TextView
android:id="@+id/tv_widget_number2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:padding="8dp"
android:text="XXX"
/>
<Button
android:id="@+id/btn_widget_getnumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="获取随机数字" />
5个方法:
例:点击button获取随机数和每隔一段时间自动生成随机数
onReceive:用来收广播
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String action=intent.getAction();
if("com.tarena.UPDATE_WIDGET".equals(action)){
int number=intent.getIntExtra("number", -1);
RemoteViews views=new RemoteViews(context.getPackageName(), R.layout.widget_layout);
views.setTextViewText(R.id.tv_widget_number2, number+"");
AppWidgetManager manger=AppWidgetManager.getInstance(context);
manger.updateAppWidget(new ComponentName(context, MyWidget.class), views);
}
}
onEnable:当前仅当,第一个Widget被拖到桌面上的时候,该方法会被调用。在第一个widget被拖到到桌面的时候,系统会发送系统广播,onReceive方法收到该广播后会调用onEnable方法。
onUpdate:当Widget被拖动桌面上,该方法都会被调用一次。widget被拖到到桌面的时候,
系统会发送系统广播,onReceive方法收到该广播后会调用onUpdate方法。然后,每隔updatePerioidMillis时间,系统还会发送一次系统广播,该方法依然会被调用一次。
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
//要先创建一个RemoteView的对象
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
//为按钮绑定监听器
//点击按钮刷新TextView中的内容
Intent intent = new Intent(context,MyService.class);//用来启动service的intent
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.btn_widget_getnumber, pendingIntent);
//利用AppWidgetManager把RemoteViews“提交”给安卓,安卓在Widget时
//会按照你为RemoteViews指定的方式来进行
ComponentName provider = new ComponentName(context, MyWidget.class);
appWidgetManager.updateAppWidget(provider, remoteViews);
}
onDeleted:当一个Widget从桌面上被删除的时候,该Widget的onDeleted方法会被调用。
onDisable:当且仅当最后一个Widget从桌面上删除的时候,该Widget除了onDeleted方法会被调用之外,它的onDisable方法也会被调用
4)在AndroidManifest文件中,“注册”第3步写好的类
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/mywidget" />
5)创建<span style="font-family: Arial, Helvetica, sans-serif;">Service</span>
public class MyService extends Service {
<span style="white-space:pre"> </span>Thread thread;
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>public MyService() {
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void onCreate() {
<span style="white-space:pre"> </span>super.onCreate();
<span style="white-space:pre"> </span>thread=new Thread(){
<span style="white-space:pre"> </span>public void run() {
<span style="white-space:pre"> </span>try{
<span style="white-space:pre"> </span>while (!Thread.interrupted()) {
<span style="white-space:pre"> </span>Intent intent=new Intent("com.tarena.UPDATE_WIDGET");
<span style="white-space:pre"> </span>intent.putExtra("number", new Random().nextInt(100));
<span style="white-space:pre"> </span>sendBroadcast(intent);
<span style="white-space:pre"> </span>Thread.sleep(2000);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}catch (Exception e) {
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>};
<span style="white-space:pre"> </span>};
<span style="white-space:pre"> </span>thread.start();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void onDestroy() {
<span style="white-space:pre"> </span>super.onDestroy();
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public int onStartCommand(Intent intent, int flags, int startId) {
<span style="white-space:pre"> </span>//刷新Widget中TextView内容的代码
<span style="white-space:pre"> </span>//要先创建一个RemoteView的对象
<span style="white-space:pre"> </span>RemoteViews views = new RemoteViews(getPackageName(), R.layout.widget_layout);
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>//为按钮绑定监听器
<span style="white-space:pre"> </span>//点击按钮刷新TextView中的内容
<span style="white-space:pre"> </span>views.setTextViewText(R.id.tv_widget_number, new Random().nextInt(1000)+"");
<span style="white-space:pre"> </span>views.setTextColor(R.id.tv_widget_number, Color.rgb(new Random().nextInt(256), new Random().nextInt(256),new Random().nextInt(256)));
<span style="white-space:pre"> </span>//利用AppWidgetManager把RemoteView "提交"给安卓,安卓早Widget的时候
<span style="white-space:pre"> </span>//会按照你为RemoteView指定的方式来进行
<span style="white-space:pre"> </span>AppWidgetManager manager = AppWidgetManager.getInstance(this);
<span style="white-space:pre"> </span>manager.updateAppWidget(new ComponentName(this, MyWidget.class), views);
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>return super.onStartCommand(intent, flags, startId);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public IBinder onBind(Intent intent) {
<span style="white-space:pre"> </span>throw new UnsupportedOperationException("Not yet implemented");
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
}