Android displays animation in widgets - ViewFlipper nested ImageView

Preliminary preparation:

Add widget Android Studio =>New=>AppWidget 

Configuration details:

widget_info.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/app_widget_description"
    android:initialKeyguardLayout="@layout/quote_widget_small"    
    android:initialLayout="@layout/quote_widget_small"// 初始化的layout布局
    android:minWidth="110dp"// 宽度对应格子2
    android:minHeight="40dp"//高度对应格子1
    android:previewImage="@drawable/example_appwidget_preview"//预览外观
    android:previewLayout="@layout/quote_widget_small"//预览布局仅用于 API 级别 31 及更高版本
    android:resizeMode="horizontal|vertical"//指示是否以及如何调整此小部件的大小
    android:targetCellWidth="2"//设置宽度格子数仅用于 API 级别 31 及更高版本
    android:targetCellHeight="1"//设置高度格子数仅用于 API 级别 31 及更高版本
    android:updatePeriodMillis="86400000"//设置自动刷新间隔毫秒数,最小为30分钟
    android:widgetCategory="home_screen" />//设置桌面小组件

Implementation ideas:

The widget is Remoteviews and the layout is restricted.

RemoteViewsSupport is limited to the following layouts:

 Implementation: RemoteViews do not support direct use of animation, so try to use ViewFlipper to nest ImageView to implement animation.

 <ViewFlipper
        android:id="@+id/flipper"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="end|center_vertical"
        android:autoStart="true"
        android:flipInterval="90">

        <ImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:src="@drawable/blue"
            android:scaleType="fitXY"
            android:contentDescription="蓝色" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:src="@drawable/green"
            android:scaleType="fitXY"
            android:contentDescription="绿色" />
    </ViewFlipper>

The test results found that animation effects can be achieved.

Problem : It’s hard-coded now, and it’s very troublesome to set up the image again. Moreover, each frame of picture needs to be uploaded to drawable, and then each frame of picture needs to be set, which is very unscientific.

Extension: If the resource file uploads a GIF, then split each frame of the GIF into BitMap, then set the BitMap to ImageView, and then use it as a sub-control of ViewFlipper.

Implementation process:

first step:

Upload the GIF to the Drawable folder.

To split a GIF into frames, use android-gif-drawable. (If it is just a simple display and loading of animation, you can use Glide)

    implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.27'

Step two:

Get the GifDrawable object and get each frame of the GIF.

 try {
            GifDrawable gifDrawable = new GifDrawable(context.getResources(), drawableIds[new Random().nextInt(drawableIds.length)]);
            int frameCount = gifDrawable.getNumberOfFrames();
            Log.e(TAG, "Number of frames: " + frameCount);
            for (int i = 0; i < frameCount; i++) {
                // 获取当前帧的 Bitmap
                Bitmap frameBitmap = gifDrawable.seekToFrameAndGet(i);
              
            }
            // Instruct the widget manager to update the widget
            appWidgetManager.updateAppWidget(appWidgetId, views);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

third step:

Prepare an ImageView xml file in advance

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/Widget.Android.AppWidget.Container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="0dp"
    android:theme="@style/Theme.Android.AppWidgetContainer">

    <ImageView
        android:id="@+id/custom"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY" />
</RelativeLayout>

Convert each frame of BitMap object obtained into RemoteViews.

RemoteViews views2 = new RemoteViews(context.getPackageName(), R.layout.custom_image);
                views2.setImageViewBitmap(R.id.custom, frameBitmap);

the fourth step:

Add the RemoteViews generated by each frame of picture to the ViewFlipper in the RemoteViews of the widget.

views.addView(R.id.flipper, views2);

Complete code

 private static final String TAG = "eWidgetTall";
//    static int[] drawableIds = {R.drawable.ceshi, R.drawable.ceshi2, R.drawable.ceshi3, R.drawable.ceshi4,R.drawable.ceshi6};
    static int[] drawableIds = {R.drawable.ceshi8, R.drawable.ceshi};

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId) {

        CharSequence widgetText = context.getString(R.string.appwidget_text);
        // Construct the RemoteViews object
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.quote_widget_tall);
//        views.setTextViewText(R.id.appwidget_text, widgetText);
        views.removeAllViews(R.id.flipper);
//点击切换Gif图
        Intent intent = new Intent(context, QuoteWidgetTall.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        int[] arr = {appWidgetId};
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,arr);
        PendingIntent pendingIntent = PendingIntent
                .getBroadcast(context, appWidgetId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        views.setOnClickPendingIntent(R.id.widget_tall, pendingIntent);

        try {
            GifDrawable gifDrawable = new GifDrawable(context.getResources(), drawableIds[new Random().nextInt(drawableIds.length)]);
            int frameCount = gifDrawable.getNumberOfFrames();
            Log.e(TAG, "Number of frames: " + frameCount);
            for (int i = 0; i < frameCount; i++) {
                // 获取当前帧的 Bitmap
                Bitmap frameBitmap = gifDrawable.seekToFrameAndGet(i);
                Log.e(TAG, i + " frameBitmap: " + frameBitmap);
                // 在此处对获取到的 Bitmap 进行操作,例如保存到文件、显示在 ImageView 等
                RemoteViews views2 = new RemoteViews(context.getPackageName(), R.layout.custom_image);
                views2.setImageViewBitmap(R.id.custom, frameBitmap);
                views.addView(R.id.flipper, views2);
            }
            // Instruct the widget manager to update the widget
            appWidgetManager.updateAppWidget(appWidgetId, views);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

Guess you like

Origin blog.csdn.net/renxi0/article/details/131997542