桌面小部件基础篇: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中,判断是否播放,停止。

 

 

 

更多相关文章

  1. Android小项目之五 splash动画效果
  2. Android(安卓)UI开源组件库BottomView ,第三方自定义UI控件
  3. [Android]Fragment自定义动画、动画监听以及兼容性包使用
  4. Android简易的仿微信聊天的语音播放控件
  5. 如何实现Siri中的波纹动画
  6. 手把手教你绘制Android粘性果冻动画组件
  7. 一对一视频直播系统Android补间动画-雷达扫描效果
  8. Android(安卓)的属性动画的实现和使用详解
  9. androidのXlist框架上拉下拉刷新案例

随机推荐

  1. 手把手的教你成为Android高手(视频+源码+
  2. Android(安卓)UI开发(一)初识安卓
  3. c++11 + SDL2 + ffmpeg +OpenAL + java =
  4. Android高手进阶教程(四)之----Android(
  5. Android(安卓)高工面试必考题(二):Android的
  6. Android中的消息机制
  7. 解析底层原理!月薪20k+的Android面试都问
  8. 一文帮你搞懂 Android(安卓)文件描述符
  9. 月薪20k+的Android面试都问些什么?深夜思
  10. Android应用程序的内存泄漏问题