微件显示在自定义activity
1. 相关背景知识介绍 大多数 Android 设备上的 Android 主屏幕都允许用户嵌入应用微件,以便快速访问内容。如果您要构建主屏幕替代应用或类似的应用,还可以通过实现 AppWidgetHost 允许用户嵌入应用微件。
**AppWidgetHost**:提供用户窗口与widget互动的接口,并提供常用方法:
*int allocateAppWidgetId()*:此方法用来给widget微件分配唯一id
*AppWidgetHostView createView(Context context,int appWidgetId,AppWidgetProviderInfo appWidget)*:此方法用来创建对应id的widget显示容器。
创建AppwidgetHost对象,需要两个参数。
new AppwidgetHost(Context context,Int hostid)
context指定窗口对象,hostid是生成widget唯一id的硬编码值(此值必须唯一)
**AppWidgetManger**:提供AppWidget的相关信息管理类,通过静态单例模式实例化。常用方法如下:
*List<AppWidgetProviderInfo> getIntalledProviders()*:此方法返会所有已安装的AppWidget的providers。
*AppWidgetManager.ACTION_APPWIDGET_BIND*:提供将widgetID和对应AppWidget绑定的Action,支持Android4.1以上版本。需要在AndroidManifest.xml绑定权限:
<uses-permission android:name="android.permission.BIND_APPWIDGET" />
*APPWidgetManaget.ACTION_APPWIDGET_PICK*:提供将widgetID和widgets dialog所选择的AppWidget绑定的Action。
2. 代码示例
自定义AppWidgetHostViewd的显示容器
public class MyWidgetHostView extends ViewGroup{
private int[] cellCoordinate = new int[2];
public int height = 0;
public int width = 0;
public MyWidgetHostView(Context context){super(context)}
public MyWidgetHostView(Context context, AttributeSet attrs){super(context, attrs)}
public MyWidgetHostView(Context context, AttributeSet attrs, int defStyleAttr){super(context, attrs, defStyleAttr)}
public void addInScreen(View child, int width, int height){
MyLayoutParams params = new MyLayoutParams(widgth, height);
params.x = cellCoorfinate[0];
params.y = cellCoorfinate[1];
this.width = params.width;
this.height = params.height;
addView(child, params);
}
public void onMeaure(int widthMeasureSpec, int heightMeasureSpec){
final int count = getChildCount();
MyLayoutParams lp = null;
for(int i = 0; i< count; i++){
view child = getChildAt(i);
lp = (MyLayoutParam)child.getLayoutParams();
child.measure(
MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY))
}
setMeasureDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec))
}
@Override
protected void onLayout(boolean changed,int left, int top , int right ,int bottom){
final int count = getChildCount();
MyLayoutParams lp = null;
for(int i = 0; i < count; i++){
View child = getChildAt(i);
lp = (MyLayoutParams) child.getLayoutParams();
child.layout(lp.x,lp.y, lp.x + lp.width, lp.y + lp.height);
}
}
public static class MyLayoutParams extends ViewGroup.LayoutParams{
public int x;
public int y;
public MyLayoutParams(int width, int height){
this.width = width;
this.height = height;
}
}
}
自定义ListWidgetActicity,将所有AppWidget显示在ListView中
public class ListWdigetActivity extends Activity{
private static final String TAG = ListWidgeActivity.class.getSimpleName();
private static final int REQUEST_ADD_WIDGET = 1;
private static final int REQUEST_CREATE_WIDGET = 2;
private static final int HOST_ID = 0x300;
private AppWidgetHost mAppWidgetHost;
private AppWidgetManager mAppWidgetManager;
private ListView listView;
private MyListWidgetAdapt myListWidgetAdapt;
private List<AppWidgetProviderInfo> appWidgetProviderInfoList = null;
private List<MyWidgetHostView> viewList = new ArrayList<MyWidgetHostView>();
private int count = 0;
@override
public void onCreate(Bundle saveInstanceState){
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_list_widget);
listView = findViewById(R.id.my_listciew);
mAppWidgetHost = new AppWidgetHost(this.getApplicaton(),HOST_ID);
mAppWidgetManager = AppWidgetManager.getInstance(this.getApplication());
appWidgetProviderInfoList = mAppWidgetManager.getInstalledProviders();
myListWidgetAdapt = new MyListWidgetAdapt(this, viewList);
listView.setAdapter(myListWidgetAdapt);
}
protected void bindWidgetId(){
if(count < appWidgetProviderInfoList.size()){
AppWidgetProviderInfo providerInfo = appWidgetProviderInfoList.get(count);
if(filterProvider(providerInfo, "com.google.android.gm.widget.GmailWidgetProvider")){
count++;
bindWidgetId();
}
int appWidgetId = mAppWidgetHost.allocateAppWdigetId();
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, providerInfo.provider);
startActivityForResult(intent, REQUEST_ADD_WIDGET);
}else{
myListWidgetAdapt.setLists(viewList);
myListWidgetAdapt.notifyDataSetChanged();
}
}
private boolean filterProvider(AppWidgetProviderInfo providerInfo, String className){
if(providerInfo.provider.getClassName().equals(className) || provderInfo == null){
return true;
}else{
return false;
}
}
@Override
protected void onResume(){
super.onResume();
bindWidgetId();
}
private void createWidget(Intent data) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
AppWidgetProviderInfo appWidget = mAppWidgetManger.getAppWidgetInfo(appWidgetId);
View hostView = mAppWidgetHost.createView(this, appWidgetId, appWidget);
MyWidgetHostView myWidgetHostView = new MyWidgetHostView(this);
myWidgetHostView.addInScreen(hostView, appWidget.minWidth + 100,
appWidget.minHeight+200);
myWidgetHostView.requestLayout();
viewList.add(myWidgetHostView);
Log.d(TAG,"viewlist length = " + viewList.size());
}
private void addWidget(Intent data) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
-1);
AppWidgetProviderInfo appWidget = mAppWidgetManger.getAppWidgetInfo(appWidgetId);
Log.d(TAG, "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);
}
}
super.onActivityResult(requestCode,resultCode,data);
}
}
activity_list_widget.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ListWidgetActivity"
android:background="@color/black">
<ListView android:id="@+id/my_listview"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
自定义适配器MyListWidgetAdapt
public class MyListWidgetAdapt extends BaseAdapter {
private Context mContext;
private List<MyWidgetHostView> lists = new ArrayList<>();
private static final int APPWIDGET_HOST_ID = 0x200;
public MyListWidgetAdapt(Context context,List<MyWidgetHostView> list){
mContext = context;
if(this.lists.size() > 0){
lists.clear();
}
lists.addAll(list);
}
public void setLists(List<MyWidgetHostView> list){
if(this.lists.size() > 0){
lists.clear();
}
lists.addAll(list);
}
@Override
public int getCount() {
return lists.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
View view;
if(convertView == null){
view = LayoutInflater.from(mContext).inflate(R.layout.list_item,null);
LinearLayout linearLayout = view.findViewById(R.id.parent_linearlayout);
viewHolder = new ViewHolder(linearLayout);
view.setTag(viewHolder);
}else{
view =convertView;
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.linearLayout.removeAllViews();
MyWidgetHostView.MyLayoutParams layoutParams = new MyWidgetHostView.MyLayoutParams(lists.get(position).width,lists.get(position).height);
viewHolder.linearLayout.addView(lists.get(position),layoutParams);
viewHolder.linearLayout.requestLayout();
return view;
}
public class ViewHolder{
public LinearLayout linearLayout;
public ViewHolder(LinearLayout l){
linearLayout = l;
}
}
}
自定义list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parent_linearlayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
3.总结
- 首先获取AppWidgetManger单例对象,通过AppWidgetManget获取所有已安装的AppWidgetProviderInfoList。
- 实例化AppWidgetHost并绑定唯一的编码值。通过allocateAppWidgetId(),不断产生唯一的appWidgetId;
- 通过启动AppWidgetManager.ACTION_APPWIDGET_BIND意图,将产生的AppWidgetId和AppWidgetProvider绑定。
- 返回绑定结果,通过appwidgetId获取对应的AppWidgetProvider,并通过AppWidgetHostView生成AppWidget显示容器,在添加到我们自定义容器中进行重新布局。
- 将重新布局的appWidget显示容器,收集到list中,通过listview进行显示。
|