本文介绍Widget的显示过程
Widget 就是我们常用的桌面小部件,它常常被显示在桌面上去完成一些功能,那么是如何显示的呢?主要相关的类:
AppWidgetHost:是用来容纳AppWidget的地方,主要有两个功能
(1).用来处理AppWidgetService事件,通过updata、provider_change事件来处理和更新Widget。
(2).创建AppWidgetHostView,用来装AppWidget的容器。
AppWidgetManager:和PackageManager一样,AppWidgetManager用来处理Widget。
AppWidgetProviderInfo:AppWidget 模型类。
示例demo,点击弹出对话框显示所有widget,选择widget显示到界面
MyWidgetHost.java
重写ViewGroup,用来显示AppWidget和计算widget的大小,位置
public class MyWidgetHost extends ViewGroup { private int[] cellInfo = new int[2]; private OnLongClickListener mLongClickListener; public MyWidgetHost(Context context) { this(context, null); } public MyWidgetHost(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyWidgetHost(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } // @1:当长按的时候触发该动作,记录长按的位置 public boolean dispatchTouchEvent(MotionEvent event) { cellInfo[0] = (int) event.getX(); cellInfo[1] = (int) event.getY(); Log.e("event:", cellInfo[0] + "," + cellInfo[1]); return super.dispatchTouchEvent(event); } //当用户选择了某个widget时,触发这个动作,将其所选的widget(child)添加到桌面上 public void addInScreen(View child, int width, int height) { LayoutParams params = new LayoutParams(width, height); params.x = cellInfo[0]; params.y = cellInfo[1]; // params.width = width child.setOnLongClickListener(mLongClickListener); Log.e("size", "x,y,width,height" + params.x + "," + params.y + "," + params.width + "," + params.height); addView(child, params); } //测量每个孩子的宽度和高度 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int count = getChildCount(); LayoutParams lp = null; for (int i = 0; i < count; i++) { View child = getChildAt(i); lp = (LayoutParams) child.getLayoutParams(); Log.e("onMeasure:w,h", lp.width + "," + lp.height); child.measure( MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY)); } setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); } //将每个孩子按照其layoutparams中定义的进行布局 @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); LayoutParams lp = null; for (int i = 0; i < count; i++) { View child = getChildAt(i); lp = (LayoutParams) child.getLayoutParams(); child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height); } } public static class LayoutParams extends ViewGroup.LayoutParams { int x; int y; public LayoutParams(int width, int height) { super(width, height); this.width = width; this.height = height; } } }
设置刚刚我们这自定义的ViewGroup为Activity的ContentView
点击ViewGroup通过发送一个Intent的方式来查询所有的Widget,带上Intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
在onActivityResult中根据返回的Widget 的ID再发一个Intent,通过刚在的ID得到AppWidgetProviderInfo的对象,HostView的WidgetHost.create(Context,id,widgetinfo)创建,然后添加到ViewGroup。
public class MainActivity extends Activity { List<AppWidgetProviderInfo> list; private static final int APPWIDGET_HOST_ID = 0x200; private static final int REQUEST_ADD_WIDGET = 1; private static final int REQUEST_CREATE_WIDGET = 2; AppWidgetHost mAppWidgetHost; AppWidgetManager manager; MyWidgetHost myWidgetHostView; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); mAppWidgetHost = new AppWidgetHost(getApplication(), APPWIDGET_HOST_ID); manager = AppWidgetManager.getInstance(getBaseContext()); myWidgetHostView = new MyWidgetHost(this); myWidgetHostView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub selectWidgets(); } }); setContentView(myWidgetHostView); mAppWidgetHost.startListening(); } protected void selectWidgets() { int widgetId = mAppWidgetHost.allocateAppWidgetId(); Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK); pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); startActivityForResult(pickIntent, REQUEST_ADD_WIDGET); } private void createWidget(Intent data) { // 获取选择的widget的id int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); // 获取所选的Widget的AppWidgetProviderInfo信息 AppWidgetProviderInfo appWidget = manager.getAppWidgetInfo(appWidgetId); // 根据AppWidgetProviderInfo信息,创建HostView View hostView = mAppWidgetHost.createView(this, appWidgetId, appWidget); // View view = hostView.findViewById(appWidget.autoAdvanceViewId); // ((Advanceable)view).fyiWillBeAdvancedByHostKThx(); // 将HostView添加到桌面 myWidgetHostView.addInScreen(hostView, appWidget.minWidth + 100, appWidget.minHeight + 200); myWidgetHostView.requestLayout(); } // 添加选择的widget。需要判断其是否含有配置,如果有,需要首先进入配置 private void addWidget(Intent data) { int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); AppWidgetProviderInfo appWidget = manager.getAppWidgetInfo(appWidgetId); Log.d("AppWidget", "configure:" + appWidget.configure); if (appWidget.configure != null) { // 有配置,弹出配置 Intent intent = new Intent( AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); intent.setComponent(appWidget.configure); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); startActivityForResult(intent, REQUEST_CREATE_WIDGET); } else { // 没有配置,直接添加 onActivityResult(REQUEST_CREATE_WIDGET, RESULT_OK, data); } } public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { switch (requestCode) { case REQUEST_ADD_WIDGET: addWidget(data); break; case REQUEST_CREATE_WIDGET: createWidget(data); break; default: break; } } else if (requestCode == REQUEST_CREATE_WIDGET && resultCode == RESULT_CANCELED && data != null) { int appWidgetId = data.getIntExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, -1); if (appWidgetId != -1) { mAppWidgetHost.deleteAppWidgetId(appWidgetId); } } } }