开发步骤

【开发步骤】
点击 CircleImageView 时,弹出完整的播放界面
1、给 CircleImageView 添加 onClick 监听
2、编写 RelativeLayoutPlayMusic 界面
3、完成弹出动画操作
4、点击返回键,弹出 RelativeLayoutPlayMusic

我们按照步骤开发,修改 actviity_test 布局为 RelativeLayout 同时增加要弹出的界面布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/tv_title_bar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#2894FF"
android:gravity="center"
android:text="音乐播放器"
android:textColor="#fff" />

<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_below="@+id/tv_title_bar"
android:orientation="horizontal">

<RadioButton
android:id="@+id/radioButtonNew"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:button="@null"
android:checked="true"
android:gravity="center"
android:text="新歌榜"
android:textColor="@drawable/selector_tab"
android:textSize="18sp" />

<RadioButton
android:id="@+id/radioButtonHot"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:text="热歌榜"
android:textColor="@drawable/selector_tab"
android:textSize="18sp" />

</RadioGroup>

<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_above="@+id/ll_bottom"
android:layout_below="@+id/radioGroup"
android:layout_weight="1"
android:background="#ffffff" />

<LinearLayout
android:id="@+id/ll_bottom"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="#2894FF"
android:gravity="center_vertical"
android:paddingLeft="10dp"
android:paddingRight="10dp">

<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/img_music_thumb"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="10dp"
android:src="@mipmap/ic_launcher" />

<TextView
android:id="@+id/tv_music_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="歌名"
android:textColor="@android:color/white" />

</LinearLayout>

<RelativeLayout
android:id="@+id/rlPlayMusic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg_music"
android:visibility="invisible">

<ImageView
android:id="@+id/img_play_music_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />

<TextView
android:id="@+id/tv_play_music_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="hehe"
android:textColor="@android:color/white"
android:textSize="22dp" />

<TextView
android:id="@+id/tv_play_music_singer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_play_music_title"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="hehe"
android:textColor="@android:color/white"
android:textSize="18dp" />

<ImageView
android:id="@+id/img_play_music_thumb"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_below="@+id/tv_play_music_singer"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher" />

<TextView
android:id="@+id/img_play_music_lrc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/img_play_music_thumb"
android:layout_alignLeft="@+id/img_play_music_thumb"
android:layout_alignRight="@+id/img_play_music_thumb"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="歌词歌词歌词"
android:textColor="@android:color/white" />

<SeekBar
android:id="@+id/sk_play_music_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/img_play_music_lrc"
android:layout_margin="5dp" />

<TextView
android:id="@+id/tv_play_music_current_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/sk_play_music_progress"
android:layout_alignLeft="@+id/sk_play_music_progress"
android:text="00:00"
android:textColor="@android:color/white" />

<TextView
android:id="@+id/tv_play_music_total_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/sk_play_music_progress"
android:layout_alignRight="@+id/sk_play_music_progress"
android:text="3:50"
android:textColor="@android:color/white" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp">

<ImageView
android:id="@+id/img_pre_music"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_media_previous" />

<ImageView
android:id="@+id/img_pause_music"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_media_pause" />

<ImageView
android:id="@+id/img_next_music"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_media_next" />
</LinearLayout>
</RelativeLayout>

</RelativeLayout>

在 Activity 中给界面控件初始化,然后给转动的底部图片增加点击事件,让刚才增加的 RelativeLayout 弹出,然后点击返回,再弹回

public class TestActivity extends AppCompatActivity implements View.OnClickListener {
......
private RelativeLayout rlPlayMusic;
private ImageView img_play_music_background;
private ImageView img_play_music_thumb;
.....

private void setViews() {
.....
tvMusicTitle = findViewById(R.id.tv_music_title);
rlPlayMusic = findViewById(R.id.rlPlayMusic);
img_play_music_background = findViewById(R.id.img_play_music_background);
img_play_music_thumb = findViewById(R.id.img_play_music_thumb);
}
......
private void setListeners() {
......
imgMusicThumb.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.img_music_thumb:
//显示出RelativeLayout
rlPlayMusic.setVisibility(View.VISIBLE);
//弹出
TranslateAnimation animation = new TranslateAnimation(0, 0, rlPlayMusic.getHeight(), 0);
animation.setDuration(500);
rlPlayMusic.setAnimation(animation);
break;
}
}

@Override
public void onBackPressed() {
if (rlPlayMusic.getVisibility() == View.VISIBLE) {
rlPlayMusic.setVisibility(View.INVISIBLE);
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, rlPlayMusic.getHeight());
animation.setDuration(500);
rlPlayMusic.setAnimation(animation);
} else {
super.onBackPressed();
}
}
......
}

其中添加动画时,是从底部弹出,到原来的位置(RelativeLayout 本来覆盖在屏幕全屏的),所以 X 坐标变化是0->0,Y 坐标变化是 RelativeLayout 的高度->0(Y左边原点0,越往下坐标值越大,越往上坐标值越小)
【达内课程】音乐播放器4.0(播放详情页上)_背景图
【开发步骤】
显示播放界面中的:背景图片与专辑图片
当音乐开始播放后,获取该音乐的两个图片路径
异步发送 http 请求,获取图片 bitmap,设置到相应的 ImageView 中

根据开放步骤修改 Activity

class MusicInfoBroadCastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Globalconsts.ACTION_MUSIC_STARTED)) {
......
tvMusicTitle.setText(title);

//更新专辑图片
String thumb = music.albumPic;
BitmapUtils.loadBitmap(thumb, new BitmapCallback() {
@Override
public void onBitmapLoaded(Bitmap bitmap) {
if (bitmap != null) {
img_play_music_thumb.setImageBitmap(bitmap);
} else {
img_play_music_thumb.setImageResource(R.mipmap.ic_launcher);
}
}
});

//更新背景图
final String background = music.albumPic;
BitmapUtils.loadBitmap(background, new BitmapCallback() {
@Override
public void onBitmapLoaded(Bitmap bitmap) {
if (bitmap != null) {
//模糊化处理
BitmapUtils.loadBlurBitmap(bitmap, new BitmapCallback() {
@Override
public void onBitmapLoaded(Bitmap bitmap) {
img_play_music_background.setImageBitmap(bitmap);
}
});
} else {
img_play_music_background.setImageResource(R.mipmap.ic_launcher);
}
}
});
}
}
}

BitmapUtils 增加以下方法

/**
* 异步加载模糊图片
*
* @param bitmap 源图片
* @param callback
*/
public static void loadBlurBitmap(final Bitmap bitmap, final BitmapCallback callback) {
//只要有耗时的操作就不能在主线程执行
AsyncTask<String, String, Bitmap> task = new AsyncTask<String, String, Bitmap>() {
@Override
protected Bitmap doInBackground(String... strings) {
Bitmap b = createBlurBitmap(bitmap, 10);
return b;
}

@Override
protected void onPostExecute(Bitmap bitmap) {
callback.onBitmapLoaded(bitmap);
}
};
task.execute();
}

其中 createBlurBitmap 方法是一个模糊 bitmap 的方法,可以参考:​​模糊化处理Bitmap的一个方法​

查看效果图

【达内课程】音乐播放器4.0(播放详情页上)_背景图_02

BitmapUtils 中新增一个可以展示压缩过后 bitmap 的方法

/**
* @param path 资源路径
* @param scale 压缩比例
* @param bitmapCallback
*/
public static void loadBitmap(final String path, final int scale, final BitmapCallback bitmapCallback) {
AsyncTask<String, String, Bitmap> task = new AsyncTask<String, String, Bitmap>() {
@Override
protected Bitmap doInBackground(String... strings) {
try {
//先从内存缓存中读
//再从文件中读
String filename = path.substring(path.lastIndexOf("/") + 1);
File file = new File(MusicApplication.getApp().getCacheDir(), "images/" + filename);
Bitmap b = bitmap(file, scale);
if (b != null) {
return b;
}
InputStream is = HttpUtils.getInputStream(path);
//下载图片并且不压缩
b = BitmapFactory.decodeStream(is);
//下载下来的原始尺寸图片,存入缓存中
save(b, file);
//从文件中读取bitmap,按照scale压缩
b = bitmap(file, scale);
return b;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

//主线程中执行回调方法
@Override
protected void onPostExecute(Bitmap bitmap) {
bitmapCallback.onBitmapLoaded(bitmap);
}
};
task.execute();
}

同时修改bitmap方法,同时修改调用该方法的地方,传入第二个参数0

public static Bitmap bitmap(File file, int scale) {
if (!file.exists()) {
return null;
}
if (scale == 0) {
Bitmap b = BitmapFactory.decodeFile(file.getAbsolutePath());
return b;
} else {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = scale;
Bitmap b = BitmapFactory.decodeFile(file.getAbsolutePath(), opts);
return b;
}
}

MainActivity 中更新背景图处的方法修改为

//更新背景图
final String background = music.albumPic;
BitmapUtils.loadBitmap(background, 10,new BitmapCallback() {
@Override
public void onBitmapLoaded(Bitmap bitmap) {
if (bitmap != null) {
//模糊化处理
BitmapUtils.loadBlurBitmap(bitmap, new BitmapCallback() {
@Override
public void onBitmapLoaded(Bitmap bitmap) {
img_play_music_background.setImageBitmap(bitmap);
}
});
} else {
img_play_music_background.setImageResource(R.mipmap.ic_launcher);
}
}
});