PS: 今天偶然听到消息, 我也是惊了! 网易云音乐暂时下架了, 内心就是五味陈杂.
由于最近自己在做一个音乐 App, 在播放音乐时, 想实现网易云那种带光盘和指针的界面, 所以在查找了许多的学习教程, 对网易云音乐的消息也特别的关注.
同时也希望有知情的大佬评论一下, 网易云音乐到底怎么了?
以下是我的学习制作过程, 先放出网易云播放界面
1. 隐藏 statusBar
- // 隐藏 statusBar, 第一个参数是新窗口的标志位, 第二个参数时要修改的标志位
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
2. 布局文件(暂时添加返回按钮, 背景, 歌名和作者)
- <?xml version="1.0" encoding="utf-8"?>
- <FrameLayout xmlns:Android="http://schemas.android.com/apk/res/android"
- xmlns:App="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- Android:layout_width="match_parent"
- Android:layout_height="match_parent"
- tools:context=".activities.PlayMusicActivity">
- <ImageView
- Android:id="@+id/iv_bg"
- Android:layout_width="match_parent"
- Android:layout_height="match_parent"
- Android:scaleType="centerCrop"
- Android:src="@mipmap/album1"
- />
- <ImageView
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:src="@mipmap/no_bar_back"
- Android:layout_margin="@dimen/marginSize"
- Android:onClick="onBackClick"/>
- <LinearLayout
- Android:layout_width="match_parent"
- Android:layout_height="wrap_content"
- Android:orientation="vertical"
- Android:gravity="center_horizontal"
- Android:layout_marginTop="480dp">
- <TextView
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:text="音乐名称"
- Android:textColor="@android:color/white"
- Android:textSize="@dimen/textSize"
- Android:textStyle="bold"/>
- <TextView
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:layout_marginTop="@dimen/marginSize"
- Android:textSize="@dimen/infoSize"
- Android:text="作者"
- Android:textColor="@android:color/white"/>
- </LinearLayout>
- </FrameLayout>
3. 设置背景模糊
使用 GlideTransTransformations 包
(1) 引入包(App/build.gradle)
- // 如果没有引入 Glide 的包也要记得引入, 因为两者是配合使用的
- implementation 'com.github.bumptech.glide:glide:4.9.0'
- //glide-transformation
- implementation 'jp.wasabeef:glide-transformations:4.0.1'
(2) 加载图片, 这里设置效果为模糊, 具体的其他效果可以参考 GitHub 中该包的详细说明, 地址是 https://github.com/wasabeef/glide-transformations
(3) 操作代码, load 中的可以是网络图片 url, 也可以是模块中的文件
- iv_bg = this.findViewById(R.id.iv_bg);
- //glide-transformation
- Glide.with(this)
- .load(R.mipmap.album1)
- .apply(RequestOptions.bitmapTransform(new BlurTransformation(25,10)))
- .into(iv_bg);
(4) 效果
4. 自定义带指针光盘的 View
(1) 指针
(2) 光盘
- <?xml version="1.0" encoding="utf-8"?>
- <FrameLayout xmlns:Android="http://schemas.android.com/apk/res/android"
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- xmlns:App="http://schemas.android.com/apk/res-auto">
- <!-- 光盘 -->
- <FrameLayout
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:layout_marginTop="@dimen/discTopSize">
- <ImageView
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:src="@mipmap/disc" />
- <!--CircleImageView-->
- <de.hdodenhof.circleimageview.CircleImageView
- Android:id="@+id/cv_icon"
- Android:layout_width="@dimen/playMusicIconSize"
- Android:layout_height="@dimen/playMusicIconSize"
- Android:layout_gravity="center"
- App:civ_border_width="2dp"
- App:civ_border_color="@android:color/black"/>
- <!-- 播放按钮 -->
- <ImageView
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:src="@mipmap/play_music"
- Android:layout_gravity="center"
- Android:visibility="gone"/>
- </FrameLayout>
- <!-- 指针 -->
- <ImageView
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:src="@mipmap/needle"
- Android:layout_gravity="center_horizontal"
- Android:layout_marginLeft="@dimen/needleMarginSize"/>
- </FrameLayout>
上面的 xml, 是这个自定义 view 的一个布局, 具体的自定义 view 的代码如下
- package com.musicplaer.eminemmusic.views;
- import Android.content.Context;
- import Android.os.Build;
- import Android.support.annotation.NonNull;
- import Android.support.annotation.Nullable;
- import Android.support.annotation.RequiresApi;
- import Android.util.AttributeSet;
- import Android.view.LayoutInflater;
- import Android.view.View;
- import Android.widget.FrameLayout;
- import com.bumptech.glide.Glide;
- import com.musicplaer.eminemmusic.R;
- import de.hdodenhof.circleimageview.CircleImageView;
- public class PlayMusicView extends FrameLayout {
- private Context mContext;
- private View mView;
- private CircleImageView cv_icon;
- public PlayMusicView(@NonNull Context context) {
- super(context);
- init(context);
- }
- public PlayMusicView(@NonNull Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- init(context);
- }
- public PlayMusicView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context);
- }
- @RequiresApi(API = Build.VERSION_CODES.LOLLIPOP)
- public PlayMusicView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init(context);
- }
- private void init(Context context){
- this.mContext = context;
- mView = LayoutInflater.from(mContext).inflate(R.layout.play_music,this,false);
- cv_icon = mView.findViewById(R.id.cv_icon);
- addView(mView);
- }
- /**
- * 设置光盘中显示的音乐封面图片
- */
- public void setMusicIcon(String icon){
- Glide.with(mContext)
- .load(icon)
- .into(cv_icon);
- }
- public void setMusicIcon(int album1) {
- cv_icon.setImageResource(album1);
- }
- }
然后将该自定义的 view 添加到原先的布局文件中, 在 Activity 中调用 setMusicIcon 来设置图片, 效果如下:
5. 设置动画(@integers/xxxx 是在 App/src/main/res/values/integers.xml 中自定义的变量)
(1) 光盘转动动画
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:Android="http://schemas.android.com/apk/res/android"
- Android:interpolator="@android:anim/linear_interpolator">
- <!-- 转动效果 -->
- <rotate
- Android:fromDegrees="0"
- Android:toDegrees="360"
- Android:pivotX="50%"
- Android:pivotY="50%"
- Android:duration="@integer/play_music_anim_duration"
- Android:repeatCount="infinite"/>
- </set>
(2) 指针指向光盘动画
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:Android="http://schemas.android.com/apk/res/android"
- Android:interpolator="@android:anim/linear_interpolator">
- <!-- 指针旋转动画 -->
- <rotate
- Android:fromDegrees="-20"
- Android:toDegrees="0"
- Android:pivotX="0"
- Android:pivotY="0"
- Android:duration="@integer/play_needle_anim_duration"
- />
- </set>
(3) 指针离开光盘动画
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:Android="http://schemas.android.com/apk/res/android"
- Android:interpolator="@android:anim/linear_interpolator"
- Android:fillAfter="true">
- <rotate
- Android:fromDegrees="0"
- Android:toDegrees="-20"
- Android:pivotY="0"
- Android:pivotX="0"
- Android:duration="@integer/play_needle_anim_duration"
- />
- </set>
(4) 在自定义 View 中设置动画, 且在播放 Activity 中还要调用 playMusic()的方法, 使得一开始就有动画效果
- package com.musicplaer.eminemmusic.views;
- import Android.content.Context;
- import Android.os.Build;
- import Android.support.annotation.NonNull;
- import Android.support.annotation.Nullable;
- import Android.support.annotation.RequiresApi;
- import Android.util.AttributeSet;
- import Android.view.LayoutInflater;
- import Android.view.View;
- import Android.view.animation.Animation;
- import Android.view.animation.AnimationUtils;
- import Android.widget.FrameLayout;
- import Android.widget.ImageView;
- import com.bumptech.glide.Glide;
- import com.musicplaer.eminemmusic.R;
- import de.hdodenhof.circleimageview.CircleImageView;
- public class PlayMusicView extends FrameLayout {
- private Context mContext;
- private View mView;
- private CircleImageView cv_icon;
- private Animation mPlayMusicAnim,mPlayNeedleAnim,mStopNeedleAnim;
- private FrameLayout fl_disc;
- private ImageView iv_needle,iv_play;
- private boolean isPlay;
- public PlayMusicView(@NonNull Context context) {
- super(context);
- init(context);
- }
- public PlayMusicView(@NonNull Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- init(context);
- }
- public PlayMusicView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context);
- }
- @RequiresApi(API = Build.VERSION_CODES.LOLLIPOP)
- public PlayMusicView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init(context);
- }
- private void init(Context context){
- this.mContext = context;
- mView = LayoutInflater.from(mContext).inflate(R.layout.play_music,this,false);
- cv_icon = mView.findViewById(R.id.cv_icon);
- iv_play = mView.findViewById(R.id.iv_play);
- fl_disc = mView.findViewById(R.id.fl_fisc);
- iv_needle = mView.findViewById(R.id.iv_needle);
- // 设置监听事件
- fl_disc.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- trigger();
- }
- });
- /**
- * 定义所需要执行的动画:
- * 1, 光盘转动的动画
- * 2. 指针指向光盘的动画
- * 3. 指针离开光盘的动画
- * 使用 startAnimation
- */
- // 初始化
- mPlayMusicAnim = AnimationUtils.loadAnimation(mContext,R.anim.play_music_animation);
- mPlayNeedleAnim = AnimationUtils.loadAnimation(mContext,R.anim.play_needle_anim);
- mStopNeedleAnim = AnimationUtils.loadAnimation(mContext,R.anim.stao_needle_anim);
- addView(mView);
- }
- /**
- * 设置光盘中显示的音乐封面图片
- */
- public void setMusicIcon(String icon){
- Glide.with(mContext)
- .load(icon)
- .into(cv_icon);
- }
- public void setMusicIcon(int album1) {
- cv_icon.setImageResource(album1);
- }
- /**
- * 播放音乐: 设置动画执行效果
- */
- public void playMusic(){
- isPlay = true;
- fl_disc.startAnimation(mPlayMusicAnim);
- iv_needle.startAnimation(mPlayNeedleAnim);
- }
- /**
- * 停止音乐: 设置动画执行效果
- */
- private void stopMusic(){
- isPlay = false;
- fl_disc.clearAnimation();
- iv_needle.startAnimation(mStopNeedleAnim);
- // 显示按钮
- iv_play.setVisibility(View.VISIBLE);
- }
- /**
- * 切换播放状态
- */
- private void trigger(){
- if(isPlay){
- stopMusic();
- }else {
- playMusic();
- }
- }
- }
最后
如果你看到了这里, 觉得文章写得不错就给个喜欢呗? 如果你觉得那里值得改进的, 请给我留言. 一定会认真查询, 修正不足. 谢谢.
来源: http://www.jianshu.com/p/349b9381b7ec