优化了播放界面,界面主要仿网易云,并增加了播放歌碟旋转的动画效果

pull/1/head
jsyjst 7 years ago
parent 06c7b3ea1f
commit 34b212b353

@ -41,10 +41,5 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
//glide
api('com.github.bumptech.glide:glide:4.7.1') {
exclude group: 'com.android.support'
}
api('jp.wasabeef:glide-transformations:3.3.0') {
exclude group: 'com.android.support'
}
implementation 'com.github.bumptech.glide:glide:4.8.0'
}

@ -10,6 +10,7 @@ public interface IPlayContract {
}
interface View{
String getSingerName(); //得到歌手的姓名
void getSingerAndLrc();//按钮点击事件,获取封面和歌词
void setSingerImg(String ImgUrl); //将图片设置成背景
void setImgFail(String errorMessage);
}

@ -0,0 +1,42 @@
package com.example.musicplayer.util;
import android.content.Context;
/**
* Created by on 2018/10/27.
*/
public class DisplayUtil {
/*手柄起始角度*/
public static final float ROTATION_INIT_NEEDLE = -30;
/*截图屏幕宽高*/
private static final float BASE_SCREEN_WIDTH = (float) 1080.0;
private static final float BASE_SCREEN_HEIGHT = (float) 1920.0;
/*唱针宽高、距离等比例*/
public static final float SCALE_NEEDLE_WIDTH = (float) (276.0 / BASE_SCREEN_WIDTH);
public static final float SCALE_NEEDLE_MARGIN_LEFT = (float) (500.0 / BASE_SCREEN_WIDTH);
public static final float SCALE_NEEDLE_PIVOT_X = (float) (43.0 / BASE_SCREEN_WIDTH);
public static final float SCALE_NEEDLE_PIVOT_Y = (float) (43.0 / BASE_SCREEN_WIDTH);
public static final float SCALE_NEEDLE_HEIGHT = (float) (413.0 / BASE_SCREEN_HEIGHT);
public static final float SCALE_NEEDLE_MARGIN_TOP = (float) (43.0 / BASE_SCREEN_HEIGHT);
/*唱盘比例*/
public static final float SCALE_DISC_SIZE = (float) (813.0 / BASE_SCREEN_WIDTH);
public static final float SCALE_DISC_MARGIN_TOP = (float) (190 / BASE_SCREEN_HEIGHT);
/*专辑图片比例*/
public static final float SCALE_MUSIC_PIC_SIZE = (float) (533.0 / BASE_SCREEN_WIDTH);
/*设备屏幕宽度*/
public static int getScreenWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
/*设备屏幕高度*/
public static int getScreenHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
}

@ -0,0 +1,217 @@
package com.example.musicplayer.util;
import android.graphics.Bitmap;
/**
* Created by on 18/10/27
*/
public class FastBlurUtil {
public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {
Bitmap bitmap;
if (canReuseInBitmap) {
bitmap = sentBitmap;
} else {
bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
}
if (radius < 1) {
return (null);
}
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
int wm = w - 1;
int hm = h - 1;
int wh = w * h;
int div = radius + radius + 1;
int r[] = new int[wh];
int g[] = new int[wh];
int b[] = new int[wh];
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
int vmin[] = new int[Math.max(w, h)];
int divsum = (div + 1) >> 1;
divsum *= divsum;
int dv[] = new int[256 * divsum];
for (i = 0; i < 256 * divsum; i++) {
dv[i] = (i / divsum);
}
yw = yi = 0;
int[][] stack = new int[div][3];
int stackpointer;
int stackstart;
int[] sir;
int rbs;
int r1 = radius + 1;
int routsum, goutsum, boutsum;
int rinsum, ginsum, binsum;
for (y = 0; y < h; y++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
for (i = -radius; i <= radius; i++) {
p = pix[yi + Math.min(wm, Math.max(i, 0))];
sir = stack[i + radius];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rbs = r1 - Math.abs(i);
rsum += sir[0] * rbs;
gsum += sir[1] * rbs;
bsum += sir[2] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
}
stackpointer = radius;
for (x = 0; x < w; x++) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (y == 0) {
vmin[x] = Math.min(x + radius + 1, wm);
}
p = pix[yw + vmin[x]];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[(stackpointer) % div];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi++;
}
yw += w;
}
for (x = 0; x < w; x++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
yp = -radius * w;
for (i = -radius; i <= radius; i++) {
yi = Math.max(0, yp) + x;
sir = stack[i + radius];
sir[0] = r[yi];
sir[1] = g[yi];
sir[2] = b[yi];
rbs = r1 - Math.abs(i);
rsum += r[yi] * rbs;
gsum += g[yi] * rbs;
bsum += b[yi] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
if (i < hm) {
yp += w;
}
}
yi = x;
stackpointer = radius;
for (y = 0; y < h; y++) {
// Preserve alpha channel: ( 0xff000000 & pix[yi] )
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (x == 0) {
vmin[y] = Math.min(y + r1, hm) * w;
}
p = x + vmin[y];
sir[0] = r[p];
sir[1] = g[p];
sir[2] = b[p];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[stackpointer];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi += w;
}
}
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
return (bitmap);
}
}

@ -29,7 +29,7 @@ import java.util.List;
public class MediaUtil {
//获取专辑封面的Uri
private static final String TAG="MediaUtil";
private static final String TAG = "MediaUtil";
private static final Uri albumArtUri = Uri.parse("content://media/external/audio/albumart");
@ -127,150 +127,26 @@ public class MediaUtil {
return Bitmap.createScaledBitmap(bm, 150, 150, true);
}
// public static Bitmap getDefaultArtwork(Context context, boolean small) {
//
// return (Bitmap) BitmapFactory.decodeResource(context.getResources(), R.drawable.background);
// }
//
// /**
// * 从文件当中获取专辑封面位图
// * * @param context
// * * @param songid
// * * @param albumid
// * * @return
// */
// private static Bitmap getArtworkFromFile(Context context, long songid, long albumid) {
// Bitmap bm = null;
// if (albumid < 0) {
// throw new IllegalArgumentException("Must specify an album or a song id");
// }
// try {
// BitmapFactory.Options options = new BitmapFactory.Options();
// FileDescriptor fd = null;
// if (albumid < 0) {
// Uri uri = Uri.parse("content://media/external/audio/media/" + songid + "/albumart");
// ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
// if (pfd != null) {
// fd = pfd.getFileDescriptor();
// }
// } else {
// Uri uri = ContentUris.withAppendedId(albumArtUri, albumid);
// ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
// if (pfd != null) {
// fd = pfd.getFileDescriptor();
// }
// }
// options.inSampleSize = 1; // 只进行大小判断
// options.inJustDecodeBounds = true;
// // 调用此方法得到options得到图片大小
// BitmapFactory.decodeFileDescriptor(fd, null, options);
// //我们的目标是在800pixel的画面上显示
// // 所以需要调用computeSampleSize得到图片缩放的比例
// options.inSampleSize = 100;
// //我们得到了缩放的比例现在开始正式读入Bitmap数据
// options.inJustDecodeBounds = false;
// options.inDither = false;
// options.inPreferredConfig = Bitmap.Config.ARGB_8888; //根据options参数减少所需要的内存
// bm = BitmapFactory.decodeFileDescriptor(fd, null, options);
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
// return bm;
// }
//
// /**
// * 获取专辑封面位图对象 * @param context * @param song_id * @param album_id * @param allowdefalut * @return
// */
// public static Bitmap getArtwork(Context context, long song_id, long album_id, boolean allowdefalut, boolean small) {
// if (album_id < 0) {
// if (song_id < 0) {
// Bitmap bm = getArtworkFromFile(context, song_id, -1);
// if (bm != null) {
// return bm;
// }
// }
// if (allowdefalut) {
// return getDefaultArtwork(context, small);
// }
// return null;
// }
// ContentResolver res = context.getContentResolver();
// Uri uri = ContentUris.withAppendedId(albumArtUri, album_id);
// if (uri != null) {
// InputStream in = null;
// try {
// in = res.openInputStream(uri);
// BitmapFactory.Options options = new BitmapFactory.Options();
// //先制定原始大小
// options.inSampleSize = 1;
// //只进行大小判断
// options.inJustDecodeBounds = true;
// //调用此方法得到options得到图片的大小
// BitmapFactory.decodeStream(in, null, options);
// /** 我们的目标是在你N pixel的画面上显示。 所以需要调用computeSampleSize得到图片缩放的比例 **/
// /** 这里的target为800是根据默认专辑图片大小决定的800只是测试数字但是试验后发现完美的结合 **/
// if (small) {
// options.inSampleSize = computeSampleSize(options, 40);
// } else {
// options.inSampleSize = computeSampleSize(options, 600);
// }
// // 我们得到了缩放比例现在开始正式读入Bitmap数据
// options.inJustDecodeBounds = false;
// options.inDither = false;
// options.inPreferredConfig = Bitmap.Config.ARGB_8888;
// in = res.openInputStream(uri);
// return BitmapFactory.decodeStream(in, null, options);
// } catch (FileNotFoundException e) {
// Bitmap bm = getArtworkFromFile(context, song_id, album_id);
// if (bm != null) {
// if (bm.getConfig() == null) {
// bm = bm.copy(Bitmap.Config.RGB_565, false);
// if (bm == null && allowdefalut) {
// return getDefaultArtwork(context, small);
// }
// }
// } else if (allowdefalut) {
// bm = getDefaultArtwork(context, small);
// }
// return bm;
// } finally {
// try {
// if (in != null) {
// in.close();
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// }
// return null;
// }
//
// /**
// * 对图片进行合适的缩放 * @param options * @param target * @return
// */
// public static int computeSampleSize(BitmapFactory.Options options, int target) {
// int w = options.outWidth;
// int h = options.outHeight;
// int candidateW = w / target;
// int candidateH = h / target;
// int candidate = Math.max(candidateW, candidateH);
// if (candidate == 0) {
// return 1;
// }
// if (candidate > 1) {
// if ((w > target) && (w / candidate) < target) {
// candidate -= 1;
// }
// }
// if (candidate > 1) {
// if ((h > target) && (h / candidate) < target) {
// candidate -= 1;
// }
// }
// return candidate;
// }
public static String formatTime(long time) {
String min = time / (1000 * 60) + "";
String sec = time % (1000 * 60) + "";
if (min.length() < 2) {
min = "0" + time / (1000 * 60) + "";
} else {
min = time / (1000 * 60) + "";
}
if (sec.length() == 4) {
sec = "0" + (time % (1000 * 60)) + "";
} else if (sec.length() == 3) {
sec = "00" + (time % (1000 * 60)) + "";
} else if (sec.length() == 2) {
sec = "000" + (time % (1000 * 60)) + "";
} else if (sec.length() == 1) {
sec = "0000" + (time % (1000 * 60)) + "";
}
return min + ":" + sec.trim().substring(0, 2);
}
}

@ -1,40 +1,111 @@
package com.example.musicplayer.view;
import android.animation.ObjectAnimator;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;
import android.transition.Slide;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.example.musicplayer.R;
import com.example.musicplayer.base.BaseActivity;
import com.example.musicplayer.contract.IPlayContract;
import com.example.musicplayer.entiy.Song;
import com.example.musicplayer.presenter.PlayPresenter;
import com.example.musicplayer.service.PlayerService;
import com.example.musicplayer.util.CommonUtil;
import com.example.musicplayer.util.DisplayUtil;
import com.example.musicplayer.util.FastBlurUtil;
import com.example.musicplayer.util.FileHelper;
import com.example.musicplayer.util.MediaUtil;
import com.example.musicplayer.widget.BackgroundAnimationRelativeLayout;
import com.example.musicplayer.widget.DiscView;
/**
*
*/
public class PlayActivity extends BaseActivity implements IPlayContract.View {
public class PlayActivity extends BaseActivity implements IPlayContract.View, DiscView.IPlayInfo {
private String TAG = "PlayActivity";
private boolean isChange; //拖动进度条
private boolean isSeek;//标记是否在暂停的时候拖动进度条
private boolean flag; //用做暂停的标记
private int time; //记录暂停的时间
private boolean isPlaying;
private Song mSong;
private MediaPlayer mMediaPlayer;
private TextView mSongTv; //
private TextView mSingerTv;
private Button mPlayBtn;
private Button mLastBtn;
private Button mNextBtn;
private RelativeLayout mPlayRelative;
private PlayPresenter mPresenter;
private boolean isPlaying;
private SeekBar mSeekBar;
private TextView mCurrentTimeTv;
private TextView mDurationTimeTv;
private DiscView mDisc; //唱碟
private ImageView mDiscImg; //唱碟中的歌手头像
private Bitmap mImgBmp;
private Button mGetImgAndLrcBtn;//获取封面和歌词
private BackgroundAnimationRelativeLayout mRootLayout;
//服务
private Thread mSeekBarThread;
private IntentFilter mIntentFilter;
private SongChangeReceiver songChangeReceiver;
private PlayerService.PlayStatusBinder mPlayStatusBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mPlayStatusBinder = (PlayerService.PlayStatusBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private Handler mMusicHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mSeekBar.setProgress((int) mPlayStatusBinder.getCurrentTime());
mCurrentTimeTv.setText(MediaUtil.formatTime(mSeekBar.getProgress()));
startUpdateSeekBarProgress();
}
};
@Override
@ -49,15 +120,87 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View {
//与Presenter建立关系
mPresenter = new PlayPresenter();
mPresenter.attachView(this);
mPresenter.getSingerImg(getSingerName());
//
mPlayRelative = findViewById(R.id.relative_play);
//注册广播
mIntentFilter = new IntentFilter();
mIntentFilter.addAction("android.song.change");
songChangeReceiver = new SongChangeReceiver();
registerReceiver(songChangeReceiver, mIntentFilter);
mRootLayout = findViewById(R.id.relative_root);
mSongTv = findViewById(R.id.tv_song);
mSingerTv = findViewById(R.id.tv_singer);
mPlayBtn = findViewById(R.id.btn_player);
mLastBtn = findViewById(R.id.btn_last);
mNextBtn = findViewById(R.id.next);
mGetImgAndLrcBtn = findViewById(R.id.btn_get_img_lrc);
mSeekBar=findViewById(R.id.seek);
mDurationTimeTv=findViewById(R.id.tv_duration_time);
mCurrentTimeTv=findViewById(R.id.tv_current_time);
mDisc = findViewById(R.id.disc_view);
mDisc.setPlayInfoListener(this);
mDiscImg = findViewById(R.id.iv_disc_background);
//绑定服务
Intent playIntent = new Intent(PlayActivity.this, PlayerService.class);
bindService(playIntent, connection, Context.BIND_AUTO_CREATE);
mSong=FileHelper.getSong();
mSingerTv.setText(mSong.getArtist());
mSongTv.setText(mSong.getTitle());
mCurrentTimeTv.setText(MediaUtil.formatTime(0));
mDurationTimeTv.setText(MediaUtil.formatTime(mSong.getDuration()));
mSeekBar.setMax((int)mSong.getDuration());
mSeekBar.setProgress((int) mSong.getCurrentTime());
}
private void try2UpdateMusicPicBackground(final Bitmap bitmap) {
new Thread(new Runnable() {
@Override
public void run() {
final Drawable drawable = getForegroundDrawable(bitmap);
runOnUiThread(new Runnable() {
@Override
public void run() {
mRootLayout.setForeground(drawable);
mRootLayout.beginAnimation();
}
});
}
}).start();
}
private Drawable getForegroundDrawable(Bitmap bitmap) {
/*得到屏幕的宽高比,以便按比例切割图片一部分*/
final float widthHeightSize = (float) (DisplayUtil.getScreenWidth(PlayActivity.this)
* 1.0 / DisplayUtil.getScreenHeight(this) * 1.0);
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;
}
@Override
protected void onClick() {
mPlayBtn.setOnClickListener(new View.OnClickListener() {
@ -67,35 +210,202 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View {
mPlayBtn.setSelected(isPlaying);
}
});
mGetImgAndLrcBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getSingerAndLrc();
}
});
//进度条的监听事件
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
//防止在拖动进度条进行进度设置时与Thread更新播放进度条冲突
isChange = true;
isSeek = true;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (mPlayStatusBinder.isPlaying()) {
mMediaPlayer.seekTo(seekBar.getProgress());
} else {
time = seekBar.getProgress();
}
isChange = false;
startUpdateSeekBarProgress();
}
});
//
mPlayBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mMediaPlayer = mPlayStatusBinder.getMediaPlayer();
if (mPlayStatusBinder.isPlaying()) {
time = mMediaPlayer.getCurrentPosition();
mPlayStatusBinder.pause();
flag = true;
mPlayBtn.setSelected(false);
mDisc.pause();
} else if (flag) {
mPlayStatusBinder.resume();
flag = false;
if (isSeek) {
mMediaPlayer.seekTo(time);
} else {
isSeek = false;
}
mDisc.play();
mPlayBtn.setSelected(true);
startUpdateSeekBarProgress();
} else {
mPlayStatusBinder.play(0);
mMediaPlayer.seekTo((int) mSong.getCurrentTime());
mDisc.play();
mPlayBtn.setSelected(true);
startUpdateSeekBarProgress();
}
}
});
mNextBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPlayStatusBinder.next();
if (mPlayStatusBinder.isPlaying()) {
mPlayBtn.setSelected(true);
} else {
mPlayBtn.setSelected(false);
}
}
});
}
@Override
public String getSingerName() {
Song song = FileHelper.getSong();
Log.d(TAG, "getSingerName: " + "-" + song.getArtist().toString() + "-");
return song.getArtist().toString().trim();
if(song.getArtist().contains("/")){
String[] s=song.getArtist().split("/");
return s[0].trim();
}else{
return song.getArtist().trim();
}
}
@Override
public void getSingerAndLrc() {
mGetImgAndLrcBtn.setText("正在获取...");
mPresenter.getSingerImg(getSingerName());
}
@Override
public void setSingerImg(String ImgUrl) {
Log.d(TAG, "setSingerImg: success");
SimpleTarget<Drawable> simpleTarget = new SimpleTarget<Drawable>() {
SimpleTarget target = new SimpleTarget<Drawable>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
@Override
public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
mPlayRelative.setBackground(resource);
public void onResourceReady(@Nullable Drawable resource, Transition<? super Drawable> transition) {
Bitmap bitmap = ((BitmapDrawable) resource).getBitmap();
mImgBmp = bitmap;
try2UpdateMusicPicBackground(mImgBmp);
setDiscImg(mImgBmp);
CommonUtil.showToast(PlayActivity.this,"获取封面歌词成功");
mGetImgAndLrcBtn.setVisibility(View.GONE);
}
};
Glide.with(this)
.load(ImgUrl)
.apply(RequestOptions.placeholderOf(R.drawable.background))
.apply(RequestOptions.errorOf(R.drawable.background))
.into(simpleTarget);
.into(target);
}
@Override
public void setImgFail(String errorMessage) {
CommonUtil.showToast(this, errorMessage);
}
@Override
public void onMusicChanged(DiscView.MusicChangedStatus musicChangedStatus) {
switch (musicChangedStatus) {
case PLAY: {
//play();
break;
}
case PAUSE: {
// pause();
break;
}
case NEXT: {
// next();
break;
}
case LAST: {
// last();
break;
}
case STOP: {
// stop();
break;
}
}
}
//设置唱碟中歌手头像
private void setDiscImg(Bitmap bitmap) {
mDiscImg.setImageDrawable(mDisc.getDiscDrawable(bitmap));
int marginTop = (int) (DisplayUtil.SCALE_DISC_MARGIN_TOP * CommonUtil.getScreenHeight(PlayActivity.this));
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mDiscImg
.getLayoutParams();
layoutParams.setMargins(0, marginTop, 0, 0);
mDiscImg.setLayoutParams(layoutParams);
}
private class SongChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Song mSong = FileHelper.getSong();
mSongTv.setText(mSong.getTitle());
mSingerTv.setText(mSong.getArtist());
mPlayBtn.setSelected(true);
mSeekBar.setMax((int) mSong.getDuration());
startUpdateSeekBarProgress();
}
}
private class SeekBarThread implements Runnable {
@Override
public void run() {
while (!isChange && mPlayStatusBinder.isPlaying()) {
mSeekBar.setProgress((int) mPlayStatusBinder.getCurrentTime());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void startUpdateSeekBarProgress() {
/*避免重复发送Message*/
stopUpdateSeekBarProgress();
mMusicHandler.sendEmptyMessageDelayed(0,1000);
}
private void stopUpdateSeekBarProgress() {
mMusicHandler.removeMessages(0);
}
}

@ -0,0 +1,108 @@
package com.example.musicplayer.widget;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.view.animation.AccelerateInterpolator;
import android.widget.RelativeLayout;
import com.example.musicplayer.R;
/**
* Created by AchillesL on 2016/11/18.
*/
/**
* RelativeLayout
* */
public class BackgroundAnimationRelativeLayout extends RelativeLayout {
private final int DURATION_ANIMATION = 500;
private final int INDEX_BACKGROUND = 0;
private final int INDEX_FOREGROUND = 1;
/**
* LayerDrawable[0]: background drawable
* LayerDrawable[1]: foreground drawable
*/
private LayerDrawable layerDrawable;
private ObjectAnimator objectAnimator;
public BackgroundAnimationRelativeLayout(Context context) {
this(context, null);
}
public BackgroundAnimationRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BackgroundAnimationRelativeLayout(Context context, AttributeSet attrs, int
defStyleAttr) {
super(context, attrs, defStyleAttr);
initLayerDrawable();
initObjectAnimator();
}
private void initLayerDrawable() {
Drawable backgroundDrawable = getContext().getDrawable(R.drawable.ic_blackground);
Drawable[] drawables = new Drawable[2];
/*初始化时先将前景与背景颜色设为一致*/
drawables[INDEX_BACKGROUND] = backgroundDrawable;
drawables[INDEX_FOREGROUND] = backgroundDrawable;
layerDrawable = new LayerDrawable(drawables);
}
private void initObjectAnimator() {
objectAnimator = ObjectAnimator.ofFloat(this, "number", 0f, 1.0f);
objectAnimator.setDuration(DURATION_ANIMATION);
objectAnimator.setInterpolator(new AccelerateInterpolator());
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int foregroundAlpha = (int) ((float) animation.getAnimatedValue() * 255);
/*动态设置Drawable的透明度让前景图逐渐显示*/
layerDrawable.getDrawable(INDEX_FOREGROUND).setAlpha(foregroundAlpha);
BackgroundAnimationRelativeLayout.this.setBackground(layerDrawable);
}
});
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
/*动画结束后,记得将原来的背景图及时更新*/
layerDrawable.setDrawable(INDEX_BACKGROUND, layerDrawable.getDrawable(
INDEX_FOREGROUND));
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
public void setForeground(Drawable drawable) {
layerDrawable.setDrawable(INDEX_FOREGROUND, drawable);
}
//对外提供方法,用于开始渐变动画
public void beginAnimation() {
objectAnimator.start();
}
}

@ -0,0 +1,370 @@
package com.example.musicplayer.widget;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.example.musicplayer.R;
import com.example.musicplayer.util.CommonUtil;
import com.example.musicplayer.util.DisplayUtil;
/**
* Created by on 2018/10/27.
*/
public class DiscView extends RelativeLayout {
private ImageView mIvNeedle;
private ObjectAnimator mNeedleAnimator;
private ObjectAnimator mObjectAnimator;
/*标记ViewPager是否处于偏移的状态*/
private boolean mViewPagerIsOffset = false;
/*标记唱针复位后,是否需要重新偏移到唱片处*/
private boolean mIsNeed2StartPlayAnimator = false;
private MusicStatus musicStatus = MusicStatus.STOP;
public static final int DURATION_NEEDLE_ANIAMTOR = 500;
private NeedleAnimatorStatus needleAnimatorStatus = NeedleAnimatorStatus.IN_FAR_END;
private IPlayInfo mIPlayInfo;
private int mScreenWidth, mScreenHeight;
/*唱针当前所处的状态*/
private enum NeedleAnimatorStatus {
/*移动时:从唱盘往远处移动*/
TO_FAR_END,
/*移动时:从远处往唱盘移动*/
TO_NEAR_END,
/*静止时:离开唱盘*/
IN_FAR_END,
/*静止时:贴近唱盘*/
IN_NEAR_END
}
/*音乐当前的状态:只有播放、暂停、停止三种*/
public enum MusicStatus {
PLAY, PAUSE, STOP
}
/*DiscView需要触发的音乐切换状态播放、暂停、上/下一首、停止*/
public enum MusicChangedStatus {
PLAY, PAUSE, NEXT, LAST, STOP
}
public interface IPlayInfo {
/*用于更新音乐播放状态*/
void onMusicChanged(MusicChangedStatus musicChangedStatus);
}
public DiscView(Context context) {
this(context, null);
}
public DiscView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DiscView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScreenWidth = CommonUtil.getScreenWidth(context);
mScreenHeight = CommonUtil.getScreenHeight(context);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
initDiscImg();
initNeedle();
initObjectAnimator();
}
private void initDiscImg() {
ImageView mDiscBackground = findViewById(R.id.iv_disc_background);
mObjectAnimator=getDiscObjectAnimator(mDiscBackground);
mDiscBackground.setImageDrawable(getDiscDrawable(
BitmapFactory.decodeResource(getResources(),R.drawable.default_disc)
));
int marginTop = (int) (DisplayUtil.SCALE_DISC_MARGIN_TOP * mScreenHeight);
LayoutParams layoutParams = (LayoutParams) mDiscBackground
.getLayoutParams();
layoutParams.setMargins(0, marginTop, 0, 0);
mDiscBackground.setLayoutParams(layoutParams);
}
private void initNeedle() {
mIvNeedle = findViewById(R.id.iv_needle);
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;
playDiscAnimator();
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) {
}
});
}
public void setPlayInfoListener(IPlayInfo listener) {
this.mIPlayInfo = listener;
}
/**
*
*
*/
public Drawable getDiscDrawable(Bitmap bitmap) {
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 = Bitmap.createScaledBitmap(bitmap, musicPicSize, musicPicSize, true);
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;
}
public ObjectAnimator getDiscObjectAnimator(ImageView disc) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(disc, View.ROTATION, 0, 360);
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
objectAnimator.setDuration(20 * 1000);
objectAnimator.setInterpolator(new LinearInterpolator());
return objectAnimator;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
/*播放动画*/
private void playAnimator() {
/*唱针处于远端时,直接播放动画*/
if (needleAnimatorStatus == NeedleAnimatorStatus.IN_FAR_END) {
mNeedleAnimator.start();
}
/*唱针处于往远端移动时,设置标记,等动画结束后再播放动画*/
else if (needleAnimatorStatus == NeedleAnimatorStatus.TO_FAR_END) {
mIsNeed2StartPlayAnimator = true;
}
}
/*暂停动画*/
private void pauseAnimator() {
/*播放时暂停动画*/
if (needleAnimatorStatus == NeedleAnimatorStatus.IN_NEAR_END) {
pauseDiscAnimatior();
}
/*唱针往唱盘移动时暂停动画*/
else if (needleAnimatorStatus == NeedleAnimatorStatus.TO_NEAR_END) {
mNeedleAnimator.reverse();
/**
* reverseonStart
* */
needleAnimatorStatus = NeedleAnimatorStatus.TO_FAR_END;
}
/**
* /
* */
if (musicStatus == MusicStatus.STOP) {
notifyMusicStatusChanged(MusicChangedStatus.STOP);
}else if (musicStatus == MusicStatus.PAUSE) {
notifyMusicStatusChanged(MusicChangedStatus.PAUSE);
}
}
/*播放唱盘动画*/
private void playDiscAnimator() {
if (mObjectAnimator.isPaused()) {
mObjectAnimator.resume();
} else {
mObjectAnimator.start();
}
/**
*
* */
if (musicStatus != MusicStatus.PLAY) {
notifyMusicStatusChanged(MusicChangedStatus.PLAY);
}
}
/*暂停唱盘动画*/
private void pauseDiscAnimatior() {
mObjectAnimator.pause();
mNeedleAnimator.reverse();
}
public void notifyMusicStatusChanged(MusicChangedStatus musicChangedStatus) {
if (mIPlayInfo != null) {
mIPlayInfo.onMusicChanged(musicChangedStatus);
}
}
public void play() {
playAnimator();
}
public void pause() {
musicStatus = MusicStatus.PAUSE;
pauseAnimator();
}
public void stop() {
musicStatus = MusicStatus.STOP;
pauseAnimator();
}
public void playOrPause() {
if (musicStatus == MusicStatus.PLAY) {
pause();
} else {
play();
}
}
public void next() {
selectMusicWithButton();
}
public void last() {
selectMusicWithButton();
}
public boolean isPlaying() {
return musicStatus == MusicStatus.PLAY;
}
private void selectMusicWithButton() {
if (musicStatus == MusicStatus.PLAY) {
mIsNeed2StartPlayAnimator = true;
pauseAnimator();
} else if (musicStatus == MusicStatus.PAUSE) {
play();
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/song_start"/>
<item android:drawable="@drawable/song_stop"/>
</selector>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="45"
android:startColor="@color/gray_deep"
android:endColor="@color/gray"/>
<padding
android:bottom="7dp"
android:right="7dp"
android:left="7dp"
android:top="7dp"/>
<corners android:radius="5dp"/>
</shape>

@ -1,56 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relative_play"
<com.example.musicplayer.widget.BackgroundAnimationRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relative_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
android:background="@drawable/welcome"
android:fitsSystemWindows="true"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/relative_song"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize">
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_back"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="10dp"
android:layout_centerVertical="true"
android:src="@drawable/back" />
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/iv_back"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginStart="5dp"
android:text="青茫"
android:textColor="@color/white"
android:textSize="18sp" />
android:orientation="vertical"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_marginStart="10dp">
<TextView
android:id="@+id/tv_song"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="青茫"
android:textColor="@color/white"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_singer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="白敬亭、李宏毅、丁冠森、赵文龙"
android:textColor="@color/white_easy" />
</LinearLayout>
</RelativeLayout>
<TextView
android:id="@+id/tv_artist"
<View
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="0.5dp"
android:layout_below="@+id/relative_song"
android:gravity="center"
android:text="白敬亭、李宏毅、丁冠森、赵文龙"
android:textColor="@color/white" />
android:background="#33ffffff" />
<LinearLayout
android:id="@+id/linear"
<include
android:id="@+id/disc_view"
layout="@layout/layout_discview"
android:layout_width="match_parent"
android:layout_height="350dp"
android:layout_below="@+id/tv_artist">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/rlMusicTime"
android:layout_below="@+id/relative_song" />
/>
<Button
android:id="@+id/btn_get_img_lrc"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_below="@+id/disc_view"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:textColor="@color/white"
android:background="@drawable/button_bg"
android:text="获取封面歌词"/>
</LinearLayout>
<RelativeLayout
android:id="@+id/relative_music_time"
@ -72,17 +95,16 @@
android:textColor="@color/white" />
<SeekBar
android:id="@+id/musicSeekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/seek"
style="@style/neteasa_music_time_seek_bar_sytle"
android:layout_centerInParent="true"
android:layout_toEndOf="@id/tv_current_time"
android:layout_toStartOf="@+id/tvTotalTime"
android:layout_toStartOf="@+id/tv_duration_time"
android:paddingEnd="15dp"
android:paddingStart="15dp" />
<TextView
android:id="@+id/tvTotalTime"
android:id="@+id/tv_duration_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
@ -96,13 +118,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="40dp">
android:layout_marginBottom="10dp">
<Button
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/playstatus_order"
android:layout_centerVertical="true"
android:layout_marginStart="20dp"/>
android:layout_marginStart="20dp"
android:background="@drawable/playstatus_order" />
<LinearLayout
@ -116,24 +139,24 @@
<Button
android:id="@+id/btn_last"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/activity_play_last" />
<Button
android:id="@+id/btn_player"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_marginEnd="20dp"
android:layout_marginStart="20dp"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:background="@drawable/selector_activity_play" />
<Button
android:id="@+id/next"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/activity_play_next" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</com.example.musicplayer.widget.BackgroundAnimationRelativeLayout>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_disc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<com.example.musicplayer.widget.DiscView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--底盘-->
<ImageView
android:id="@+id/iv_disc_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
/>
<!--唱针-->
<ImageView
android:id="@+id/iv_needle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_needle"/>
</com.example.musicplayer.widget.DiscView>

@ -8,6 +8,8 @@
<color name="white">#ffffff</color>
<color name="short_white">#cecdcd</color>
<color name="gray">#80c9c9c9</color>
<color name="gray_deep">#898888</color>
<color name="seekColor">#80FFFFFF</color>
<color name="translucent">#80010738</color>
<color name="actionBarColor">#050e41</color>

@ -14,4 +14,22 @@
<item name="colorAccent">@color/musicStyle</item>
</style>
<style name="neteasa_music_time_text_sytle">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#ccc</item>
<item name="android:textSize">9sp</item>
</style>
<style name="neteasa_music_time_seek_bar_sytle"
parent="Widget.AppCompat.SeekBar">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:thumb">@drawable/ic_seekbar_thumb</item>
</style>
</resources>

Loading…
Cancel
Save