IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android所有应用widget以列表形式显示 -> 正文阅读

[移动开发]Android所有应用widget以列表形式显示

微件显示在自定义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)}
    //当用户添加某个WidgetHostView,使用此方法,将其添加到MyWidgetHostView容器中
    public void addInScreen(View child, int width, int height){
    	MyLayoutParams params = new MyLayoutParams(widgth, height);
    	//cellCoorfinate[0],cellCoorfinate[1]默认为0
    	params.x = cellCoorfinate[0];
    	params.y = cellCoorfinate[1];
    	this.width = params.width;
    	this.height = params.height;
    	addView(child, params);
    }
    
    //测量当前view下所有childView的高度和宽度
	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))
	}
	
	//将每个childView按照MyLayoutParams定义重新布局
	@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);
    	}
    }
   
   //自定义LayoutParams
   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;
 	//存储所有已安装AppWdiget对应的hostview
 	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());
 		//存储所有已安装AppWidget的providers
 		appWidgetProviderInfoList = mAppWidgetManager.getInstalledProviders();
 		myListWidgetAdapt = new MyListWidgetAdapt(this, viewList);
 		listView.setAdapter(myListWidgetAdapt);
 	}

 	protected void bindWidgetId(){
		//将AppWidgetID递归循环绑定appWidgetProviderInfoList中的AppWdiget
 		if(count < appWidgetProviderInfoList.size()){
    		//通过AppWidgetHost硬编码分配唯一AppIwdgetId
    		AppWidgetProviderInfo providerInfo = appWidgetProviderInfoList.get(count);
    		//过滤Gmail Appwidget,避免不必要的谷歌账号登录
			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();
		//每次一个appWidget绑定完成时,都会重新调用onResume()
		bindWidgetId();
	}
	
	private void createWidget(Intent data) {
        // 获取选择的widget的id
        int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,	-1);
        // 获取所选的Widget的AppWidgetProviderInfo信息
        AppWidgetProviderInfo appWidget = mAppWidgetManger.getAppWidgetInfo(appWidgetId);
        // 根据AppWidgetProviderInfo信息,创建HostView

        View hostView = mAppWidgetHost.createView(this, appWidgetId, appWidget);
        // View view = hostView.findViewById(appWidget.autoAdvanceViewId);
        // ((Advanceable)view).fyiWillBeAdvancedByHostKThx();
        // 将HostView添加到自定义view容器,定义大小(+100, +200)
        MyWidgetHostView myWidgetHostView = new MyWidgetHostView(this);
        myWidgetHostView.addInScreen(hostView, appWidget.minWidth + 100,
                appWidget.minHeight+200);

		//请求MyWidgetHostView重新布局
        myWidgetHostView.requestLayout();
        viewList.add(myWidgetHostView);
        Log.d(TAG,"viewlist length = " + viewList.size());
    }

    // 添加选择的widget。需要判断其是否含有配置,如果有,需要首先进入配置

    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();
        }
        //异常所有子MyHostView
        viewHolder.linearLayout.removeAllViews();
        MyWidgetHostView.MyLayoutParams layoutParams = new MyWidgetHostView.MyLayoutParams(lists.get(position).width,lists.get(position).height);
        //重新添加新的MyHostView
        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.总结

  1. 首先获取AppWidgetManger单例对象,通过AppWidgetManget获取所有已安装的AppWidgetProviderInfoList。
  2. 实例化AppWidgetHost并绑定唯一的编码值。通过allocateAppWidgetId(),不断产生唯一的appWidgetId;
  3. 通过启动AppWidgetManager.ACTION_APPWIDGET_BIND意图,将产生的AppWidgetId和AppWidgetProvider绑定。
  4. 返回绑定结果,通过appwidgetId获取对应的AppWidgetProvider,并通过AppWidgetHostView生成AppWidget显示容器,在添加到我们自定义容器中进行重新布局。
  5. 将重新布局的appWidget显示容器,收集到list中,通过listview进行显示。
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-22 11:03:19  更:2021-10-22 11:05:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:05:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码