Android AppWidget(桌面小部件-音乐播放动画)

版权声明:转载请标明出处 https://blog.csdn.net/Android_man_me/article/details/82835110

桌面小部件基础篇:Android AppWidget (桌面小部件)

音乐播放 (动画实现)

   

一个音乐播放的柱状图(不会上传动图,自行脑补)

思路方案:

1,自定义View,widget 仅支持部分控件,自定义没用,我把自定义弄完了,才想起来。所以这个方案pass

2,帧动画,直接使用ImageView,也不行,无法获取子控件属性,帧动画运行不了

3,LayoutAnimation,这个我还没试怎么实现复杂动画,不过应该可以实现简单的 缩放,透明度,等属性动画(自己测试吧)

4,线程实现帧动画

5,handler 实现帧动画(比较好控制)

自定义View(记录,不是最终选择方案)

package cn.sh.changxing.onlineradio.view;

import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.RemoteViews;

import java.util.Random;

/**
 * 仿柱形频谱 动画播放
 */
public class PlayerView extends View {

    private static final String TAG = "PlayerView2";

    /**
     * 画笔
     */
    private Paint paint;

    /**
     * 整个控件宽,高,最终取值
     */
    private int width, height, min;

    /**
     * 小矩形边长
     */
    private float border;

    /**
     * 间隔
     */
    private float interval;

    /**
     * 柱状图 X*X(默认 7*7)
     */
    private int line = 7;

    private ValueAnimator valueAnimator;
    private int current = -1;
    private int random = 0;

    public PlayerView(Context context) {
        this(context, null);
    }

    public PlayerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PlayerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化
     */
    private void init() {

        Log.e(TAG, "init: ");

        paint = new Paint();
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setColor(Color.WHITE);

        initAnimation();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (width == 0 || height == 0) {
            width = getMeasuredWidth();
            height = getMeasuredHeight();

            min = Math.min(width, height);
            interval = (float) (min * 0.025);
            border = (min - (line + 1) * interval) / line;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //绘制 多列
        for (int i = 0; i < line; i++) {
            drawColumnRect(canvas, (i + 1) * interval + i * border, random);
        }

    }


    /**
     * 绘制一列
     *
     * @param canvas
     * @param startX X轴的起始位置
     * @param random 为了动画效果,设置额外增加的随机数个数(每列生成个数 = 随机生成的个数+额外统一增加个数) 达到上下抖动效果
     */
    private void drawColumnRect(Canvas canvas, float startX, int random) {

        //随机生成个数
        //根据 间隔,小方块边长,个数,确定要绘制的小方块区域

        int size = new Random().nextInt(4);//0-3

        for (int i = 0; i < random + size; i++) {
            RectF rectF = new RectF();
            rectF.left = startX;
            rectF.top = min - (i + 1) * (border + interval);
            rectF.right = startX + border;
            rectF.bottom = min - (i + 1) * interval - i * border;

            //透明度变化
            paint.setAlpha(50 + i * 30);
            canvas.drawRect(rectF, paint);
        }
    }


    /**
     * 开始播放
     */
    public void startPlay() {

        if (null != valueAnimator && !valueAnimator.isRunning()) {
            valueAnimator.start();
        } else {
            initAnimation();
            startPlay();
        }
    }

    /**
     * 停止播放
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public void stop() {
        if (null != valueAnimator && valueAnimator.isRunning()) {
            valueAnimator.pause();
        }
    }

    /**
     * 销毁 回收
     */
    public void destroy() {

    }

    /**
     * 初始化动画 (暂时写死)
     */
    private void initAnimation() {

        valueAnimator = ValueAnimator.ofInt(0, 5);
        valueAnimator.setDuration(850);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int progress = (int) animation.getAnimatedValue();
                if (progress != current) {
                    postInvalidate();
                    random = new Random().nextInt(5);//额外增加个数 0-4
                    current = progress;
                }
            }
        });
    }

}

一个随机生成小方块,也能做到类似音频播放时的效果,部分直接写死的参数,记录一下,并不能用在 Widget上。

Handler实现

package cn.sh.changxing.onlineradio.widget;

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.content.ServiceConnection;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;

import com.ximalaya.ting.android.opensdk.player.XmPlayerManager;

import cn.sh.changxing.applib.constant.SysBroadcastConstant;
import cn.sh.changxing.onlineradio.OnlineRadioApplication;
import cn.sh.changxing.onlineradio.R;
import cn.sh.changxing.onlineradio.activity.MainActivity;
import cn.sh.changxing.onlineradio.service.aidl.IMediaPlayerService;

import static cn.sh.changxing.applib.constant.SysBroadcastConstant.ACTION_NOTIFY_MPLAYER_STATE_CHANGED;
import static cn.sh.changxing.applib.constant.SysBroadcastConstant.EXTRA_VALUE_NOTIFY_MPLAYER_PLAYING;

public class RadioWidgetProvider2 extends AppWidgetProvider {

    private static final String TAG = "RadioWidgetProvider2";
    public static int REQUEST_GO_ACTIVITY_CODE = 112;
    private static final int START_ANIMATION = 0;
    private static final int END_ANIMATION = 1;

    private static Context mContext;
    private static RemoteViews remoteViews;

    private IMediaPlayerService mediaPlayerService;

    private int[] bitmapId = new int[]{R.drawable.radio_play_gif_2, R.drawable.radio_play_gif_3, R.drawable.radio_play_gif_4, R.drawable.radio_play_gif_5,
            R.drawable.radio_play_gif_6, R.drawable.radio_play_gif_8, R.drawable.radio_play_gif_9, R.drawable.radio_play_gif_10, R.drawable.radio_play_gif_11,
            R.drawable.radio_play_gif_12, R.drawable.radio_play_gif_13, R.drawable.radio_play_gif_14, R.drawable.radio_play_gif_13, R.drawable.radio_play_gif_12,
            R.drawable.radio_play_gif_11, R.drawable.radio_play_gif_10, R.drawable.radio_play_gif_9, R.drawable.radio_play_gif_8, R.drawable.radio_play_gif_6,
            R.drawable.radio_play_gif_5, R.drawable.radio_play_gif_4, R.drawable.radio_play_gif_3};

    //图片资源
//    private int[] bitmapId = new int[]{R.drawable.radio_play_gif_2, R.drawable.radio_play_gif_4, R.drawable.radio_play_gif_6, R.drawable.radio_play_gif_8,
//            R.drawable.radio_play_gif_10, R.drawable.radio_play_gif_12, R.drawable.radio_play_gif_14};

    //动画间隔时间/ms
    private long sleep = 100;

    private static boolean isRun = false;

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

        if (null == mContext) {
            mContext = context;
        }
        //设置默认初始显示图片
        remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_radio);
        remoteViews.setImageViewResource(R.id.onlineRadio_widget, bitmapId[0]);
        //点击进入应用
        startRadio();
        //多个Widget的情况 刷新
        for (int i = 0; i < appWidgetIds.length; i++) {
            Log.e(TAG, "onUpdate: ");
            appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews);
        }
        //初始播放状态
        initStatus();

    }

    /**
     * 获取 播放器状态
     */
    private void initStatus(){
        OnlineRadioApplication application = OnlineRadioApplication.getInstance();
        XmPlayerManager manager = XmPlayerManager.getInstance(application);

        if(manager.isPlaying()){
            if(!isRun){
                Log.e(TAG, "initStatus: isPlaying");
                isRun = true;
                Message msg = mHandler.obtainMessage(START_ANIMATION);
                msg.arg1 = 0;
                mHandler.sendMessage(msg);
            }
        }
    }


    /**
     * 播放器状态发生变化 接收广播
     * @param context
     * @param intent
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        Message msg = mHandler.obtainMessage(START_ANIMATION);
        msg.arg1 = 0;
        String action = intent.getAction();
        if (action.equals(ACTION_NOTIFY_MPLAYER_STATE_CHANGED)) {
            String appPackName = intent.getStringExtra(SysBroadcastConstant.EXTRA_NAME_APP_PACKAGE);
            if (appPackName.equals(OnlineRadioApplication.getInstance().getPackageName())) {
                int state = intent.getIntExtra(SysBroadcastConstant.EXTRA_NAME_NOTIFY_MPLAYER_STATE, 1);
                switch (state) {
                    case EXTRA_VALUE_NOTIFY_MPLAYER_PLAYING:
                        if(!isRun){
                            isRun = true;
                            mHandler.sendMessage(msg);
                            Log.e(TAG, "onReceive: 播放");
                        }
                        break;
                    default:
                        if(isRun){
                            isRun = false;
                            mHandler.sendEmptyMessage(END_ANIMATION);
                            Log.e(TAG, "onReceive: 暂停");
                        }
                        break;
                }
            } else {
                int state = intent.getIntExtra(SysBroadcastConstant.EXTRA_NAME_NOTIFY_MPLAYER_STATE, 1);
                if (state == EXTRA_VALUE_NOTIFY_MPLAYER_PLAYING) {
                    if(!isRun){
                        isRun = true;
                        mHandler.sendMessage(msg);
                        Log.e(TAG, "onReceive: 播放");
                    }
                }
            }
        }
    }


    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            AppWidgetManager appWidgetManger = AppWidgetManager.getInstance(mContext);
            int[] appIds = appWidgetManger.getAppWidgetIds(new ComponentName(mContext, RadioWidgetProvider2.class));

            if (msg.what == START_ANIMATION) {
                if (!isRun) {
                    return;
                }
                if (null != remoteViews) {
                    remoteViews.setImageViewResource(R.id.onlineRadio_widget, bitmapId[msg.arg1]);
                    appWidgetManger.updateAppWidget(appIds, remoteViews);

                    //循环切换
                    Message message = mHandler.obtainMessage(START_ANIMATION);
                    message.arg1 = (msg.arg1 + 1) % bitmapId.length;
                    mHandler.sendMessageDelayed(message, sleep);
                }

            } else if (msg.what == END_ANIMATION) {
                //停止时显示默认图片
                remoteViews.setImageViewResource(R.id.onlineRadio_widget, bitmapId[0]);
                appWidgetManger.updateAppWidget(appIds, remoteViews);
            }
        }
    };


    /***
     *
     * 点击背景 进入radio
     *
     */
    private void startRadio() {
        Intent intent = new Intent(mContext, MainActivity.class);
        intent.setAction("cn.sh.changxing.action.redio");
        intent.addCategory("android.intent.category.DEFAULT");
        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, REQUEST_GO_ACTIVITY_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        remoteViews.setOnClickPendingIntent(R.id.widget_layout, pendingIntent);
    }

    /***
     * 检测电台服务是否开启 没有开启的话自动开启
     * @param context
     */
    public void startRadioService(final Context context) {
        mediaPlayerService = OnlineRadioApplication.getInstance().getMediaPlayerService();
        if (mediaPlayerService == null) {
            Intent intent = new Intent();
            intent.setAction("cn.sh.changxing.onlineradio.service.MediaPlayerServiceCTL");
            context.bindService(intent, new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.d(TAG, "服务开启成功" + name);
                    mediaPlayerService = IMediaPlayerService.Stub.asInterface(service);
                }

                @Override
                public void onServiceDisconnected(ComponentName name) {
                    Log.d(TAG, "服务关闭" + name);
                    context.unbindService(this);
                }
            }, Context.BIND_NOT_FOREGROUND);
        }
    }

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

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

代码注释清晰,准备好图片数组,首先判断播放器状态,看是否启动动画。所有处理在handlerMessage中,判断是否播放,停止。

猜你喜欢

转载自blog.csdn.net/Android_man_me/article/details/82835110