diff --git a/app/build.gradle b/app/build.gradle index 42e1b7b..6f63a4d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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' } diff --git a/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java b/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java index fcb1375..e99a5e5 100644 --- a/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java +++ b/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java @@ -10,6 +10,7 @@ public interface IPlayContract { } interface View{ String getSingerName(); //得到歌手的姓名 + void getSingerAndLrc();//按钮点击事件,获取封面和歌词 void setSingerImg(String ImgUrl); //将图片设置成背景 void setImgFail(String errorMessage); } diff --git a/app/src/main/java/com/example/musicplayer/util/DisplayUtil.java b/app/src/main/java/com/example/musicplayer/util/DisplayUtil.java new file mode 100644 index 0000000..9db8e66 --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/util/DisplayUtil.java @@ -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; + } +} diff --git a/app/src/main/java/com/example/musicplayer/util/FastBlurUtil.java b/app/src/main/java/com/example/musicplayer/util/FastBlurUtil.java new file mode 100644 index 0000000..3ee1927 --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/util/FastBlurUtil.java @@ -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); + } + +} diff --git a/app/src/main/java/com/example/musicplayer/util/MediaUtil.java b/app/src/main/java/com/example/musicplayer/util/MediaUtil.java index 4bfa119..704eb23 100644 --- a/app/src/main/java/com/example/musicplayer/util/MediaUtil.java +++ b/app/src/main/java/com/example/musicplayer/util/MediaUtil.java @@ -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); + } } diff --git a/app/src/main/java/com/example/musicplayer/view/PlayActivity.java b/app/src/main/java/com/example/musicplayer/view/PlayActivity.java index 0d5eff8..e0d982d 100644 --- a/app/src/main/java/com/example/musicplayer/view/PlayActivity.java +++ b/app/src/main/java/com/example/musicplayer/view/PlayActivity.java @@ -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 simpleTarget = new SimpleTarget() { + SimpleTarget target = new SimpleTarget(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) { @Override - public void onResourceReady(Drawable resource, Transition transition) { - mPlayRelative.setBackground(resource); + public void onResourceReady(@Nullable Drawable resource, Transition 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); + } + } diff --git a/app/src/main/java/com/example/musicplayer/widget/BackgroundAnimationRelativeLayout.java b/app/src/main/java/com/example/musicplayer/widget/BackgroundAnimationRelativeLayout.java new file mode 100644 index 0000000..6074cc9 --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/widget/BackgroundAnimationRelativeLayout.java @@ -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(); + } + + +} diff --git a/app/src/main/java/com/example/musicplayer/widget/DiscView.java b/app/src/main/java/com/example/musicplayer/widget/DiscView.java new file mode 100644 index 0000000..707486f --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/widget/DiscView.java @@ -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(); + /** + * 若动画在没结束时执行reverse方法,则不会执行监听器的onStart方法,此时需要手动设置 + * */ + 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(); + } + } +} diff --git a/app/src/main/res/drawable-xxhdpi/activity_play_last.png b/app/src/main/res/drawable-xxhdpi/activity_play_last.png index d839772..3d2f3fc 100644 Binary files a/app/src/main/res/drawable-xxhdpi/activity_play_last.png and b/app/src/main/res/drawable-xxhdpi/activity_play_last.png differ diff --git a/app/src/main/res/drawable-xxhdpi/activity_play_next.png b/app/src/main/res/drawable-xxhdpi/activity_play_next.png index 2a5932d..05a9d52 100644 Binary files a/app/src/main/res/drawable-xxhdpi/activity_play_next.png and b/app/src/main/res/drawable-xxhdpi/activity_play_next.png differ diff --git a/app/src/main/res/drawable-xxhdpi/activity_play_start.png b/app/src/main/res/drawable-xxhdpi/activity_play_start.png index c89ae73..5939097 100644 Binary files a/app/src/main/res/drawable-xxhdpi/activity_play_start.png and b/app/src/main/res/drawable-xxhdpi/activity_play_start.png differ diff --git a/app/src/main/res/drawable-xxhdpi/activity_play_stop.png b/app/src/main/res/drawable-xxhdpi/activity_play_stop.png index 96f14b4..d52151a 100644 Binary files a/app/src/main/res/drawable-xxhdpi/activity_play_stop.png and b/app/src/main/res/drawable-xxhdpi/activity_play_stop.png differ diff --git a/app/src/main/res/drawable-xxhdpi/default_disc.png b/app/src/main/res/drawable-xxhdpi/default_disc.png new file mode 100644 index 0000000..bbd7a7e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/default_disc.png differ diff --git a/app/src/main/res/drawable-xxhdpi/default_disc1.png b/app/src/main/res/drawable-xxhdpi/default_disc1.png new file mode 100644 index 0000000..52679e0 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/default_disc1.png differ diff --git a/app/src/main/res/drawable-xxhdpi/disc.png b/app/src/main/res/drawable-xxhdpi/disc.png new file mode 100644 index 0000000..dca93cb Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/disc.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_blackground.png b/app/src/main/res/drawable-xxhdpi/ic_blackground.png new file mode 100644 index 0000000..d56dd07 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_blackground.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_disc.png b/app/src/main/res/drawable-xxhdpi/ic_disc.png new file mode 100644 index 0000000..dca93cb Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_disc.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_last.png b/app/src/main/res/drawable-xxhdpi/ic_last.png new file mode 100644 index 0000000..3d2f3fc Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_last.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher_background.xml b/app/src/main/res/drawable-xxhdpi/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xxhdpi/ic_needle.png b/app/src/main/res/drawable-xxhdpi/ic_needle.png new file mode 100644 index 0000000..e22f785 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_needle.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_next.png b/app/src/main/res/drawable-xxhdpi/ic_next.png new file mode 100644 index 0000000..05a9d52 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_next.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_pause.png b/app/src/main/res/drawable-xxhdpi/ic_pause.png new file mode 100644 index 0000000..d52151a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_pause.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_play.png b/app/src/main/res/drawable-xxhdpi/ic_play.png new file mode 100644 index 0000000..5939097 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_play.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_seekbar_thumb.png b/app/src/main/res/drawable-xxhdpi/ic_seekbar_thumb.png new file mode 100644 index 0000000..365c467 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_seekbar_thumb.png differ diff --git a/app/src/main/res/drawable-xxhdpi/needle.png b/app/src/main/res/drawable-xxhdpi/needle.png new file mode 100644 index 0000000..e22f785 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/needle.png differ diff --git a/app/src/main/res/drawable-xxhdpi/selector_player.xml b/app/src/main/res/drawable-xxhdpi/selector_player.xml new file mode 100644 index 0000000..a99f71c --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/selector_player.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_bg.xml b/app/src/main/res/drawable/button_bg.xml new file mode 100644 index 0000000..300750b --- /dev/null +++ b/app/src/main/res/drawable/button_bg.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_play.xml b/app/src/main/res/layout/activity_play.xml index bdc3554..01b80fc 100644 --- a/app/src/main/res/layout/activity_play.xml +++ b/app/src/main/res/layout/activity_play.xml @@ -1,56 +1,79 @@ - + android:layout_height="wrap_content"> - + android:orientation="vertical" + android:layout_marginBottom="5dp" + android:layout_marginTop="5dp" + android:layout_marginStart="10dp"> + + + + + - + android:background="#33ffffff" /> - - - - /> +