Android 自定义桌面空间 AppWidget

7 篇文章 0 订阅
1 篇文章 0 订阅

本篇文章主要是记录自己学习Android自定义桌面悬浮控件,AppWidget的过程。

现在很多App都支持悬浮桌面的控件,我们可以通过系统菜单长按,或者别的方式来设置,例如自带的备忘录,就可以写完后挂在手机桌面上。
现在我们看看运行效果:

在安装应用后,设置桌面悬浮的时候会看到我们刚才安装的应用:

这里写图片描述

然后我们点击这个控件,让他显示在桌面上:

这里写图片描述

可以看到他已经现在我们桌面上了,而且长按可以拖动摆放他的位置。

现在来记录一下学习过程,
一.设置简单的自定义桌面控件:

1.在Layout下新建widget_setting.xml文件,用于设置桌面控件属性:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:initialLayout="@layout/layout_widget"
    android:minHeight="140dp"
    android:minWidth="140dp"
    android:previewImage="@mipmap/ic_launcher"
    android:updatePeriodMillis="20000"
    android:widgetCategory="home_screen"
    >
</appwidget-provider>

这里面设置了minHeight minWidth 和previreImage还有他的update函数时间间隔。

2.设计自己的AppWidget界面:

layout_widget.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
   <LinearLayout
       android:orientation="horizontal"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/iamge_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>
    <Button
        android:id="@+id/btn"
        android:textAllCaps="false"
        android:text="sure"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
   </LinearLayout>
    <TextView
        android:id="@+id/text_view"
        android:textSize="20sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

这里我们的界面设计就是图二显示在桌面上的布局设计。

3.建立TestWidget类继承自AppWidgetProvider并且建立服务并且按时更新界面
就和广播一样,我们需要实现其方法onReceive;
在AppWidgetManager中有很多系统广播,例如ACTION_APPWIDGET_UPDATE,
ACTION_APPWIDGET_DELETED
等,会在桌面控件更新,创建,和删除时候发出广播给广播接收器,我们可以在里面做一些操作。

TestWidget.java

public class TestWedigt extends AppWidgetProvider {
    private static final String WIDGET_BTN_ACTION = "WIDGET_BTN_ACTION";
    private static final int UPDATE_DURATION = 2 * 1000;
    private PendingIntent pendingIntent = null;
   static  int time =0;
    private WedigetService service  ;
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        String action = intent.getAction();//获取到广播的Action
        if(intent!=null&& TextUtils.equals(intent.getAction(),WIDGET_BTN_ACTION))//广播的Action为按钮按下
        {
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//注意:需要【重新】构造一个RemoteViewstime++;
            remoteViews.setTextViewText(R.id.text_view,"Hello Andoird"+time);
            remoteViews.setTextColor(R.id.text_view, Color.GRAY);
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);// 单例模式
            ComponentName componentName = new ComponentName(context,TestWedigt.class);
            appWidgetManager.updateAppWidget(componentName, remoteViews);//setText之后,记得更新一下,传入自定义界面
        }
        if(AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)){//广播为更新广播
            Bundle bundle = intent.getExtras();
            if(bundle!=null){
                int[] appWidgetIds = bundle.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
                if( appWidgetIds!=null&&appWidgetIds.length>0){
                    this.onUpdate(context,AppWidgetManager.getInstance(context),appWidgetIds);
                }
            }
        }else if(AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)){//广播为删除控件广播
            Bundle bundle =  intent.getExtras();
            if(bundle!=null&&bundle.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)){
                final int appWidgetIds = bundle.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
                this.onDeleted(context,new int[]{appWidgetIds});
            }
        }
    }
/*
* 重写onUpdate方法,
* */
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);
        Intent intent = new Intent();
        intent.setClass(context, TestWedigt.class);
        intent.setAction(WIDGET_BTN_ACTION);//设置广播Action为BuutonAction
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
        remoteViews.setOnClickPendingIntent(R.id.btn, pendingIntent);//设置按钮的点击监听
        appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
        context.startService(new Intent(context, WedigetService.class));//开启服务
    }

}

因为AppWidget的更新时间系统有个默认值,好像是二三十分钟,所以我们为了实现到时间自动更新,我们就要自己设置。但是在widget_setting我们设置的那个时间间隔,是不起作用的,所以我们需要通过服务来达到计时,到时间,然后更新界面的操作,这样一直循环。
我们这个类里面,还设置了界面中Button的监听事件,通过发送广播并且设置Action然后在onReceive中接受广播,判断Action的方法来设置监听。

 RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);
        Intent intent = new Intent();
        intent.setClass(context, TestWedigt.class);
        intent.setAction(WIDGET_BTN_ACTION);//设置广播Action为BuutonAction
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
        remoteViews.setOnClickPendingIntent(R.id.btn, pendingIntent);//设置按钮的点击监听
 public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        String action = intent.getAction();//获取到广播的Action
        if(intent!=null&& TextUtils.equals(intent.getAction(),WIDGET_BTN_ACTION))//广播的Action为按钮按下
        {
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//注意:需要【重新】构造一个RemoteViewstime++;
            remoteViews.setTextViewText(R.id.text_view,"Hello Andoird"+time);
            remoteViews.setTextColor(R.id.text_view, Color.GRAY);
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);// 单例模式
            ComponentName componentName = new ComponentName(context,TestWedigt.class);
            appWidgetManager.updateAppWidget(componentName, remoteViews);//setText之后,记得更新一下,传入自定义界面
        }

下面看看服务类

WeidgetService.java

public class WedigetService extends Service {

    static int time=0;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
/*
*    每次重复启动服务后,后会调用这个方法。
* */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        time++;
        buildUpdate();
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(this,WedigetService.class);
        long cuutime = SystemClock.elapsedRealtime()+1000;//时间间隔
        PendingIntent pi = PendingIntent.getService(this,0,i,0);
        alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,cuutime,pi);//设置Alarm然后到时间再次启动服务,达成循环目的。
        return super.onStartCommand(intent, flags, startId);
    }
    /*
    * 更新控件的数据
    * */
    private void buildUpdate() {
        RemoteViews view = new RemoteViews(getPackageName(), R.layout.layout_widget);
        RemoteViews remoteViews = new RemoteViews(getApplicationContext().getPackageName(), R.layout.layout_widget);
        remoteViews.setTextViewText(R.id.text_view,""+time);
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getBaseContext());
        appWidgetManager.updateAppWidget(new ComponentName(getBaseContext(), TestWedigt.class), remoteViews);
    }
}

这里面没什么东西,主要就是在多次启动服务的时候会重复调用onStartCommand方法,
所以我们在onStartCommand里,设置了Alarm,然后设定时间间隔,每次到达时间后就进行更新界面操作和服务自启动操作,这样就可以让服务一直运行并且自己到达时间后更新界面的目的。

4.添加注册。
我们需要注册服务和我们刚才写的TestWidget.

    <receiver android:name=".TestWedigt">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@layout/widget_setting"
                ></meta-data>
        </receiver>
        <service android:name=".WedigetService">
        </service>
<meta-data
                android:name="android.appwidget.provider"
                android:resource="@layout/widget_setting"
                ></meta-data>

要注意这里的写法哦。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
创建 Android 应用程序中的 App Widget,需要以下步骤: 1. 创建 App Widget Provider 类 ```java public class MyWidgetProvider extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // 更新 App Widget RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); views.setTextViewText(R.id.tv_widget, "Hello World!"); appWidgetManager.updateAppWidget(appWidgetIds, views); } } ``` 2. 声明 App Widget Provider 在 AndroidManifest.xml 文件中声明 App Widget Provider,如下所示: ```xml <receiver android:name=".MyWidgetProvider" android:label="@string/app_name"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/my_widget_info" /> </receiver> ``` 其中,MyWidgetProvider 是你的 App Widget Provider 类名,@string/app_name 是你应用的名称,@xml/my_widget_info 是你的 App Widget Provider 的相关信息,需要在 res/xml 目录下创建一个名为 my_widget_info.xml 的文件,并在该文件中指定你的 App Widget 的布局和其他属性。 3. 定义 App Widget 的布局 在 res/layout 目录下创建一个名为 widget_layout.xml 的文件,定义 App Widget 的布局,如下所示: ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"> <TextView android:id="@+id/tv_widget" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:textColor="#000000" /> </RelativeLayout> ``` 4. 更新 App Widget 在 onUpdate() 方法中,更新 App Widget 的 UI。可以使用 RemoteViews 对象更新 App Widget 的 UI,如下所示: ```java @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // 更新 App Widget RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); views.setTextViewText(R.id.tv_widget, "Hello World!"); appWidgetManager.updateAppWidget(appWidgetIds, views); } ``` 5. 安装 App Widget 在应用的首次安装时,需要向用户请求授权,以便创建 App Widget。可以使用以下代码向用户请求授权: ```java // 请求授权 Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, new ComponentName(context, MyWidgetProvider.class)); int REQUEST_PICK_APPWIDGET = 1; ((Activity) context).startActivityForResult(intent, REQUEST_PICK_APPWIDGET); ``` 6. 添加 App Widget桌面 可以使用以下代码将 App Widget 添加到桌面: ```java // 添加 App Widget Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); context.sendBroadcast(intent); ``` 其中,appWidgetIds 是 App Widget 的 ID 数组,可以在 onUpdate() 方法中获取。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值