Skip to content

PangHaHa12138/MusicPlayer2.0

Repository files navigation

MusicPlayerdemo

a MusicPlayer for Android

仿网易云音乐 可扫描本地音乐播放

核心播放页 唱盘的实现

1:首先是背景高斯迷糊,先切割图片一部分,然后缩小图片,利用FastBlur高斯模糊 最后加上灰色遮罩

 private Drawable getForegroundDrawable(int musicPicRes) {
        /*得到屏幕的宽高比,以便按比例切割图片一部分*/
        final float widthHeightSize = (float) (DisplayUtil.getScreenWidth(MusicPlayActivity.this)
                * 1.0 / DisplayUtil.getScreenHeight(this) * 1.0);

        Bitmap bitmap = getForegroundBitmap(musicPicRes);
        int cropBitmapWidth = (int) (widthHeightSize * bitmap.getHeight());
        int cropBitmapWidthX = (int) ((bitmap.getWidth() - cropBitmapWidth) / 2.0);

        /*切割部分图片*/
        Bitmap cropBitmap = Bitmap.createBitmap(bitmap, cropBitmapWidthX, 0, cropBitmapWidth,
                bitmap.getHeight());
        /*缩小图片*/
        Bitmap scaleBitmap = Bitmap.createScaledBitmap(cropBitmap, bitmap.getWidth() / 50, bitmap
                .getHeight() / 50, false);
        /*模糊化*/
        final Bitmap blurBitmap = FastBlurUtil.doBlur(scaleBitmap, 8, true);

        final Drawable foregroundDrawable = new BitmapDrawable(blurBitmap);
        /*加入灰色遮罩层,避免图片过亮影响其他控件*/
        foregroundDrawable.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
        return foregroundDrawable;
    }

    private Bitmap getForegroundBitmap(int musicPicRes) {
        int screenWidth = DisplayUtil.getScreenWidth(this);
        int screenHeight = DisplayUtil.getScreenHeight(this);

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        BitmapFactory.decodeResource(getResources(), musicPicRes, options);
        int imageWidth = options.outWidth;
        int imageHeight = options.outHeight;

        if (imageWidth < screenWidth && imageHeight < screenHeight) {
            return BitmapFactory.decodeResource(getResources(), musicPicRes);
        }

        int sample = 2;
        int sampleX = imageWidth / DisplayUtil.getScreenWidth(this);
        int sampleY = imageHeight / DisplayUtil.getScreenHeight(this);

        if (sampleX > sampleY && sampleY > 1) {
            sample = sampleX;
        } else if (sampleY > sampleX && sampleX > 1) {
            sample = sampleY;
        }

        options.inJustDecodeBounds = false;
        options.inSampleSize = sample;
        options.inPreferredConfig = Bitmap.Config.RGB_565;

        return BitmapFactory.decodeResource(getResources(), musicPicRes, options);
    }

2:合成唱盘 首先设置一个透明的圆背景 RoundedBitmapDrawable 然后拿到封面,生成圆形Drawable,还有黑胶部分,之后利用LayerDrawable(它类似ps的图层,可以将一个数组里的drawable合成一个drawable 索引最大盖在最上面) 把封面和黑胶合成唱片,这里还对图片进行了压缩避免oom

/*得到唱盘背后半透明的圆形背景*/
   private Drawable getDiscBlackgroundDrawable() {
       int discSize = (int) (mScreenWidth * DisplayUtil.SCALE_DISC_SIZE);
       Bitmap bitmapDisc = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),
               R.drawable.ic_disc_blackground), discSize, discSize, false);
       RoundedBitmapDrawable roundDiscDrawable = RoundedBitmapDrawableFactory.create
               (getResources(), bitmapDisc);
       return roundDiscDrawable;
   }

   /**
    * 得到唱盘图片
    * 唱盘图片由空心圆盘及音乐专辑图片“合成”得到
    */
   private Drawable getDiscDrawable(int musicPicRes) {
       int discSize = (int) (mScreenWidth * DisplayUtil.SCALE_DISC_SIZE);
       int musicPicSize = (int) (mScreenWidth * DisplayUtil.SCALE_MUSIC_PIC_SIZE);

       Bitmap bitmapDisc = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),
               R.drawable.ic_disc), discSize, discSize, false);
       Bitmap bitmapMusicPic = getMusicPicBitmap(musicPicSize, musicPicRes);
       BitmapDrawable discDrawable = new BitmapDrawable(bitmapDisc);
       RoundedBitmapDrawable roundMusicDrawable = RoundedBitmapDrawableFactory.create
               (getResources(), bitmapMusicPic);

       //抗锯齿
       discDrawable.setAntiAlias(true);
       roundMusicDrawable.setAntiAlias(true);

       Drawable[] drawables = new Drawable[2];
       drawables[0] = roundMusicDrawable;
       drawables[1] = discDrawable;

       LayerDrawable layerDrawable = new LayerDrawable(drawables);
       int musicPicMargin = (int) ((DisplayUtil.SCALE_DISC_SIZE - DisplayUtil
               .SCALE_MUSIC_PIC_SIZE) * mScreenWidth / 2);
       //调整专辑图片的四周边距,让其显示在正中
       layerDrawable.setLayerInset(0, musicPicMargin, musicPicMargin, musicPicMargin,
               musicPicMargin);

       return layerDrawable;
   }

   private Bitmap getMusicPicBitmap(int musicPicSize, int musicPicRes) {
       BitmapFactory.Options options = new BitmapFactory.Options();
       options.inJustDecodeBounds = true;

       BitmapFactory.decodeResource(getResources(), musicPicRes, options);
       int imageWidth = options.outWidth;

       int sample = imageWidth / musicPicSize;
       int dstSample = 1;
       if (sample > dstSample) {
           dstSample = sample;
       }
       options.inJustDecodeBounds = false;
       //设置图片采样率
       options.inSampleSize = dstSample;
       //设置图片解码格式
       options.inPreferredConfig = Bitmap.Config.RGB_565;

       return Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),
               musicPicRes, options), musicPicSize, musicPicSize, true);
   }

3:唱盘指针 其实是一张图片,设置它的旋转起始坐标点,监听viewPager的滑动利用ObjectAnimator旋转指针

 private void initNeedle() {
       mIvNeedle = (ImageView) findViewById(R.id.ivNeedle);

       int needleWidth = (int) (DisplayUtil.SCALE_NEEDLE_WIDTH * mScreenWidth);
       int needleHeight = (int) (DisplayUtil.SCALE_NEEDLE_HEIGHT * mScreenHeight);

       /*设置手柄的外边距为负数,让其隐藏一部分*/
       int marginTop = (int) (DisplayUtil.SCALE_NEEDLE_MARGIN_TOP * mScreenHeight) * -1;
       int marginLeft = (int) (DisplayUtil.SCALE_NEEDLE_MARGIN_LEFT * mScreenWidth);

       Bitmap originBitmap = BitmapFactory.decodeResource(getResources(), R.drawable
               .ic_needle);
       Bitmap bitmap = Bitmap.createScaledBitmap(originBitmap, needleWidth, needleHeight, false);

       LayoutParams layoutParams = (LayoutParams) mIvNeedle.getLayoutParams();
       layoutParams.setMargins(marginLeft, marginTop, 0, 0);

       int pivotX = (int) (DisplayUtil.SCALE_NEEDLE_PIVOT_X * mScreenWidth);
       int pivotY = (int) (DisplayUtil.SCALE_NEEDLE_PIVOT_Y * mScreenWidth);

       mIvNeedle.setPivotX(pivotX);
       mIvNeedle.setPivotY(pivotY);
       mIvNeedle.setRotation(DisplayUtil.ROTATION_INIT_NEEDLE);
       mIvNeedle.setImageBitmap(bitmap);
       mIvNeedle.setLayoutParams(layoutParams);
   }

   private void initObjectAnimator() {
       mNeedleAnimator = ObjectAnimator.ofFloat(mIvNeedle, View.ROTATION, DisplayUtil
               .ROTATION_INIT_NEEDLE, 0);
       mNeedleAnimator.setDuration(DURATION_NEEDLE_ANIAMTOR);
       mNeedleAnimator.setInterpolator(new AccelerateInterpolator());
       mNeedleAnimator.addListener(new Animator.AnimatorListener() {
           @Override
           public void onAnimationStart(Animator animator) {
               /**
                * 根据动画开始前NeedleAnimatorStatus的状态,
                * 即可得出动画进行时NeedleAnimatorStatus的状态
                * */
               if (needleAnimatorStatus == NeedleAnimatorStatus.IN_FAR_END) {
                   needleAnimatorStatus = NeedleAnimatorStatus.TO_NEAR_END;
               } else if (needleAnimatorStatus == NeedleAnimatorStatus.IN_NEAR_END) {
                   needleAnimatorStatus = NeedleAnimatorStatus.TO_FAR_END;
               }
           }

           @Override
           public void onAnimationEnd(Animator animator) {

               if (needleAnimatorStatus == NeedleAnimatorStatus.TO_NEAR_END) {
                   needleAnimatorStatus = NeedleAnimatorStatus.IN_NEAR_END;
                   int index = mVpContain.getCurrentItem();
                   playDiscAnimator(index);
                   musicStatus = MusicStatus.PLAY;
               } else if (needleAnimatorStatus == NeedleAnimatorStatus.TO_FAR_END) {
                   needleAnimatorStatus = NeedleAnimatorStatus.IN_FAR_END;
                   if (musicStatus == MusicStatus.STOP) {
                       mIsNeed2StartPlayAnimator = true;
                   }
               }

               if (mIsNeed2StartPlayAnimator) {
                   mIsNeed2StartPlayAnimator = false;
                   /**
                    * 只有在ViewPager不处于偏移状态时,才开始唱盘旋转动画
                    * */
                   if (!mViewPagerIsOffset) {
                       /*延时500ms*/
                       DiscView.this.postDelayed(new Runnable() {
                           @Override
                           public void run() {
                               playAnimator();
                           }
                       }, 50);
                   }
               }
           }

           @Override
           public void onAnimationCancel(Animator animator) {

           }

           @Override
           public void onAnimationRepeat(Animator animator) {

           }
       });
   }

利用媒体库查询语句扫描本地音乐并返回集合

// 媒体库查询语句(写一个工具类MusicUtils)
        try {
            Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                    null, null, null, MediaStore.Audio.AudioColumns.IS_MUSIC);
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    Song song = new Song();
                    song.song = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME));
                    song.singer = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
                    song.path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
                    song.duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
                    song.size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
                    song.image = pan[new Random().nextInt(pan.length)];
//                    song.image = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
                    if (song.size > 1000 * 800) {
                        // 注释部分是切割标题,分离出歌曲名和歌手 (本地媒体库读取的歌曲信息不规范)
                        if (song.song.contains("-")) {
                            String[] str = song.song.split("-");
                            song.singer = str[0];
                            song.song = str[1];
                        }
                        list.add(song);
                    }
                }
                // 释放资源
                cursor.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

About

a beautiful MusicPlayer for Android

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published