Android 桌面小组件 AppWidgetProvider(2)

Android 桌面小组件 AppWidgetProvider(2)

1.生命周期

2.怎么处理点击事件

3.怎么创建集合

4.怎么处理动画效果

1.生命周期

1.1 添加小组件的生命周期

onEnabled:
onReceive:
onUpdate:
onReceive:
onAppWidgetOptionsChanged:
onReceive:

1.2 移除小组件的生命周期

onDeleted:
onReceive:
onDisabled:
onReceive:

2.怎么处理点击事件

这个问题解决方案的关键是 设置广播action

<receiver android:name=".listWidget.ListWidget">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        <action android:name="com.zg.todesk.CLICK" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/listwidget" />
</receiver>

这里添加的是

<action android:name="com.zg.todesk.CLICK" />

然后再组件中,发送广播,就能在onReceive中收到消息,然后做相应的处理就好

	val pendingIntent = PendingIntent.getBroadcast(
        context,
        0,
        Intent(context, MuyuAppWidget::class.java).apply {
            action = "com.zg.todesk.CLICK"
        },
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
    views.setOnClickPendingIntent(R.id.rl_muyu, pendingIntent)//这里选择最大的控件

然后onReceive处理消息

override fun onReceive(context: Context?, intent: Intent?) {
    super.onReceive(context, intent)
    Log.e("zxd", "onReceive: ${intent!!.action}")
    if (intent!!.action == "com.zg.zanglidemo.ANIM") {
        ...
    }
}

3.怎么创建集合

这里简单的举一个例子。

1.声明AppWidgetProviderInfo XML

<?xml version="1.0" encoding="UTF-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/list_widget_layout"
    android:minWidth="280dp"
    android:minHeight="280dp"
    android:updatePeriodMillis="0">
    <!-- sdk1.5之后updatePeriodMillis已失效,置为0,循环执行自行在代码中实现 -->
</appwidget-provider>

2.使用 AppWidgetProvider 类处理 widget 广播

<!--    list widget    -->
<receiver android:name=".listWidget.ListWidget">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        <action android:name="com.zg.todesk.CLICK" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/listwidget" />
</receiver>

3.实现 AppWidgetProvider 类

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;

import com.zg.todesk.MainActivity;
import com.zg.todesk.R;

import java.util.ArrayList;
import java.util.List;

/***
 * @Author: zxd
 * @CreateDate: 2024/5/11 8:25:03
 * @Description:
 */
public class ListWidget extends AppWidgetProvider {

    private static List<String> sList;

    static {
        sList = new ArrayList<>();
        sList.add("第一条新闻");
        sList.add("第二条新闻");
        sList.add("第三条新闻");
        sList.add("第四条新闻");
        sList.add("第五条新闻");
        sList.add("第六条新闻");
    }

    private ComponentName thisWidget;
    private RemoteViews remoteViews;

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        thisWidget = new ComponentName(context, ListWidget.class);
        remoteViews = new RemoteViews(context.getPackageName(), R.layout.list_widget_layout);

        Intent intent = new Intent(context, UpdateService.class);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[0]);
        //设置适配器
        remoteViews.setRemoteAdapter(R.id.widget_list, intent);

        Intent intent2 = new Intent(context, MainActivity.class);

        //TODO
        //intent2.setComponent(new ComponentName("包名", "类名"));
        PendingIntent pendingIntentTemplate = PendingIntent.getActivity(context, 1, intent2, PendingIntent.FLAG_UPDATE_CURRENT);

        //拼接PendingIntent
        remoteViews.setPendingIntentTemplate(R.id.widget_list, pendingIntentTemplate);

        //更新RemoteViews
        appWidgetManager.updateAppWidget(thisWidget, remoteViews);

        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        manager.notifyAppWidgetViewDataChanged(appWidgetIds[0], R.id.widget_list);
    }

    @Override
    public void onDisabled(Context context) {
        super.onDisabled(context);
    }


    public static List<String> getList() {
        return sList;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        //在这里可以添加
        if (intent.getAction().equals("com.zg.todesk.CLICK")) {
            Log.i("zxd", "onReceive: " + intent.getStringExtra("val"));
        }
    }
}

4. widget 布局

<?xml version="1.0" encoding="UTF-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000">

    <ListView
        android:id="@+id/widget_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="4dp"
        android:layout_marginBottom="4dp"
        android:cacheColorHint="#00000000"
        android:scrollbars="none" />
    <!--        android:divider="@drawable/widget_list_divider"
            android:listSelector="@drawable/list_bg_selector"-->
</FrameLayout>

5.UpdateService中的处理**

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.Looper;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;

import com.zg.todesk.MainActivity;
import com.zg.todesk.R;

import java.util.List;

public class UpdateService extends RemoteViewsService {

    @Override
    public void onStart(Intent intent, int startId) {
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return super.onBind(intent);
    }

    @Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return new ListRemoteViewsFactory(this.getApplicationContext(), intent);
    }

    class ListRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {

        private final Context mContext;
        private final List<String> mList;

        public ListRemoteViewsFactory(Context context, Intent intent) {
            mContext = context;
            mList = ListWidget.getList();

            if (Looper.myLooper() == null) {
                Looper.prepare();
            }
        }

        @Override
        public void onCreate() {
        }

        @Override
        public void onDataSetChanged() {
        }

        @Override
        public void onDestroy() {
            mList.clear();
        }

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public RemoteViews getViewAt(int position) {
            if (position < 0 || position >= mList.size())
                return null;
            String content = mList.get(position);
            final RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_list_item);

            Intent intent = new Intent();
            //TODO
            intent.putExtra("val", content);
            //与CustomWidget中remoteViews.setPendingIntentTemplate配对使用
            rv.setOnClickFillInIntent(R.id.widget_list_item_layout, intent);

            rv.setTextViewText(R.id.widget_list_item_tv, content);

            return rv;
        }

        @Override
        public RemoteViews getLoadingView() {
            return null;
        }

        @Override
        public int getViewTypeCount() {
            return 1;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }
    }
}

6.AndroidManifest.xml中添加service

<service
    android:name=".listWidget.UpdateService"
    android:exported="false"
    android:permission="android.permission.BIND_REMOTEVIEWS" />

4.怎么处理动画效果

要想小组件有动画效果,就需要点击配合layoutAnimation才能实现动画效果

小组件布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/Widget.ZangliDemo.AppWidget.Container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_raidus"
    android:id="@+id/rl_muyu"
    android:theme="@style/AppTheme.AppWidgetContainer">

    <LinearLayout
        android:id="@+id/ll_muyu"
        android:layout_width="140dp"
        android:layout_height="140dp"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <TextView
            android:id="@+id/appwidget_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:contentDescription="测试桌面木鱼"
            android:text="已敲0次"
            android:textColor="@color/gray_8f"
            android:textSize="18sp"
            android:textStyle="bold" />

        <RelativeLayout
            android:id="@+id/muyu_rl"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/widget_muyu_iv"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_centerHorizontal="true"
                android:layout_margin="15dp"
                android:src="@mipmap/muyu" />

        </RelativeLayout>
    </LinearLayout>
</RelativeLayout>

实现效果

private fun doAnimation(context: Context?, remoteViews: RemoteViews?) {
    remoteViews?.removeAllViews(R.id.muyu_rl)
    val remoteViews2 = RemoteViews(context?.packageName, R.layout.anim_layout)
    remoteViews2.setImageViewResource(R.id.widget_muyu_iv, R.mipmap.muyu)
    remoteViews?.addView(R.id.muyu_rl, remoteViews2)
    clickNum++
    Log.e("zxd", "doAnimation: $clickNum")
    remoteViews?.setTextViewText(R.id.appwidget_text, "已敲${clickNum}次")
}

动画效果(anim_layout)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layoutAnimation="@anim/muyu_anim">

    <ImageView
        android:id="@+id/widget_muyu_iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/muyu" />
</RelativeLayout>

muyu_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/scale_anim" />

scale_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="100"
    android:fromXScale="0.9"
    android:fromYScale="0.9"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="1"
    android:toYScale="1" />

5.参考链接

Android-桌面小组件RemoteViews播放动画

RemoteViews嵌入ListView复杂布局

android AppWidget 支持ListView

在widget实现复杂布局(Listview,GirdView)以及RemoteViewsService、RemoteViewsFactory的用法

官网

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值