AppWidget 添加动画效果

最近的UI给的效果图要求在widget上显示动画效果,怕我看不明白特意做了一个视频,因为软件还未发布,视频就不贴出来了。这里把实现过程记录一下,以及自己写的demo,有相关需求的小伙伴们可以少走点弯路了。

demo的效果如图:

2020-09-15 16.39.08.gif

效果图只截取了widget的部分,其它的没有截取。图片只用到了箭头,可以自己从网上随便下载一个,命名为rotate_img

废话不多说,直接上代码。

先创建动画文件,如下文件放在anim文件夹中。

rotate_up.xml



        

rotate_down.xml



        

layout_rotate_up.xml






layout_rotate_down.xml






接着创建布局文件,以下文件放到layout文件夹中。

rotate_app_widget.xml



    

        

    

    

layout_rotate_default.xml




    



layout_rotate_down.xml




    



layout_rotate_up.xml




    



res目录如下:

res目录截图.png

RotateAppWidget.kt

package com.tom.rotatewidgetdemo

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.widget.RemoteViews

/**
 * Implementation of App Widget functionality.
 */
class RotateAppWidget : AppWidgetProvider() {

    companion object {
        internal const val ACTION_UP = "com.tom.rotate.ACTION_UP"
        internal const val ACTION_DOWN = "com.tom.rotate.ACTION_DOWN"
        internal const val ACTION_DEFAULT = "com.tom.rotate.ACTION_DEFAULT"
    }

    override fun onReceive(context: Context, intent: Intent) {
        super.onReceive(context, intent)
        val action = intent.action
        val views = RemoteViews(context.packageName, R.layout.rotate_app_widget)
        var replaceView: RemoteViews? = null

        when (action) {
            ACTION_UP -> replaceView = RemoteViews(context.packageName, R.layout.layout_rotate_up)

            ACTION_DOWN -> replaceView =
                RemoteViews(context.packageName, R.layout.layout_rotate_down)

            ACTION_DEFAULT -> replaceView =
                RemoteViews(context.packageName, R.layout.layout_rotate_default)
            else -> {

            }

        }


        if (replaceView != null) {
            views.removeAllViews(R.id.replace)
            views.addView(R.id.replace, replaceView)
            val manager = AppWidgetManager.getInstance(context)
            manager.updateAppWidget(ComponentName(context, RotateAppWidget::class.java), views)
        }
    }

    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray
    ) {
        for (appWidgetId in appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId)
        }
    }

    override fun onEnabled(context: Context) {
    }

    override fun onDisabled(context: Context) {
    }


}

internal fun updateAppWidget(
    context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int
) {

    val downIntent = Intent(RotateAppWidget.ACTION_DOWN)
        .let {
            PendingIntent.getBroadcast(
                context, 0, it, PendingIntent.FLAG_UPDATE_CURRENT
            )
        }


    val upIntent = Intent(RotateAppWidget.ACTION_UP)
        .let {
            PendingIntent.getBroadcast(
                context, 0, it, PendingIntent.FLAG_UPDATE_CURRENT
            )
        }


    val defaultIntent = Intent(RotateAppWidget.ACTION_DEFAULT)
        .let {
            PendingIntent.getBroadcast(
                context, 0, it, PendingIntent.FLAG_UPDATE_CURRENT
            )
        }


    val views =
        RemoteViews(context.packageName, R.layout.rotate_app_widget)
            .apply {
                setOnClickPendingIntent(R.id.down, downIntent)
                setOnClickPendingIntent(R.id.up, upIntent)
                setOnClickPendingIntent(R.id.default_state, defaultIntent)
            }

    appWidgetManager.updateAppWidget(appWidgetId, views)
}

AndroidManifest.xml





    
        
            
                
                
                
                
            

            
        
    


代码完事,run一下,很可能发现没有效果?为什么呢?

  1. 确定运行的设备的安卓版本,如果是安卓8及以上设备,确实不好使,原因后面说。
  2. 如果运行的是安卓8以下的设备,那么确定一下onReceive方法里,是不是有super.onReceive(context, intent),必须要有这一句,否则不起作用。

解释一下安卓8以上不好使的原因——静态广播,解决方法,使用service,用动态广播去实现就可以了,我已经在安卓10的版本上实现了。

说一下要注意的地方,widget实现动画效果主要是依靠LayoutAnimation,用它来控制子view显示时的动画效果,所以需要在使用动画的地方,将原有的View删掉,然后将带有动画的布局添加进来,从而适用动画效果。掌握了这个方法,widget中使用动画就不再是难题了,基本可以满足设计人员的要求,至于更加炫酷的,还是使用替换图片,

你可能感兴趣的:(AppWidget 添加动画效果)