简单使用AppWidgetHostView显示和创建 AppWidget

本文介绍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;
		}

	}

}

 


MainActivity中使用:

设置刚刚我们这自定义的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);
			}
		}
	}
}


这仅仅是一个简单的创建和显示,在桌面程序中显示Widget的业务逻辑远远要比这复杂。

 

posted @ 2014-12-25 17:22  顾明伟  阅读(2107)  评论(0编辑  收藏  举报