飞道的博客

Android Studio如何实现音乐播放器(简单易上手)

412人阅读  评论(0)

我们大家平时长时间打代码的时候肯定会感到疲惫和乏味,这个时候一边播放自己喜欢的音乐,一边继续打代码,心情自然也愉快很多。音乐带给人的听觉享受是无可比拟的,动听的音乐可以愉悦人的身心,让人更加积极地去热爱生活。大家平常应该会用QQ音乐、网易云音乐或者酷狗音乐等音乐APP来听歌,想不想拥有属于自己的音乐播放器。那么接下来就教大家如何用Android Studio自己制作一个音乐播放器APP。



一、工程概述

这次音乐播放器工程,可以让大家熟练掌握Android程序开发的基本技术,涉及Android 基础知识、UI界面、数据存储、四大组件、网络编程、高级编程等。综合运用UI界面设计、数据存储、Activity(活动)、Service(服务)、MusicPlayer、ListView等知识,设计开发一款具有音乐列表的音乐播放器。

整个工程包含五个类和五个布局文件,其中frag1、frag2为java文件,Music_Activity为Activity文件,MusicService为Service文件,MainActivity为主文件。

在res文件夹下创建了raw文件夹,放了三首音乐曲目,在drawable文件夹中粘贴了音乐封面图片和背景图片,还有背景选择器的xml文件,如图:

二、准备工具

1、Android Studio及开发环境。
2、选择几首自己下载好的音乐文件,命名为music0、music1、music2等。
3、选择每首歌对应的歌手图片,剪成圆形并且保存好,命名为music0、music1、music2等。
如果不太清楚图片如何剪成圆形,可以看这篇博客:如何将图片剪成圆形
4、准备一张音乐播放器的背景图片,命名为music_bg,再找一张图片用作专辑图片,命名为bg。

三、详细设计

准备工作做好了,接下来开始进行详细设计了。

1、首先打开Android Studio,并新建一个工程,工程名称叫做Music_List。
包名自己选择,这里博主用的是zj.dzh;工程文件的保存路径要修改一下,不要放在C盘,我这里选择的是放在E盘的一个Projects文件夹中;最后选择API 14:Android 4.0,因为这样它就拥有了100%的跨平台性,可以运行其他各种设备上。点击Finish完成创建。


MainActivity类是整个工程的主类,包含了两个菜单文件:frag1(歌曲菜单)和frag2(专辑封面),默认情况下展示frag1,点击切换显示frag2。代码如下:

package zj.dzh.music_list;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private FrameLayout content;
    private TextView tv1,tv2;
    private FragmentManager fm;
    private FragmentTransaction ft;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            content=(FrameLayout)findViewById(R.id.content);

            tv1=(TextView)findViewById(R.id.menu1);
            tv2=(TextView)findViewById(R.id.menu2);

            tv1.setOnClickListener(this);
            tv2.setOnClickListener(this);

            fm=getSupportFragmentManager();//若是继承FragmentActivity,fm=getFragmentManger();
            ft=fm.beginTransaction();
        ft.replace(R.id.content,new frag1());//默认情况下Fragment1
        ft.commit();
    }
    @Override
    public void onClick(View v){
        ft=fm.beginTransaction();
        switch (v.getId()){
            case R.id.menu1:
                ft.replace(R.id.content,new frag1());
                break;
            case R.id.menu2:
                ft.replace(R.id.content,new frag2());
                break;
            default:
                break;
        }
        ft.commit();
    }
}

activity_main主要实现界面菜单,显示歌曲和专辑TextView控件,效果如图:

代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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=".MainActivity"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="我喜欢"
            android:textSize="35dp"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
    <TextView
        android:id="@+id/menu1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:text="歌曲"
        android:textSize="25dp"/>
    <TextView
        android:id="@+id/menu2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:text="专辑"
        android:textSize="25dp"/>
    </LinearLayout>
    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="9">
    </FrameLayout>

</LinearLayout>

2、创建MusicService文件,右击包名New——>Service——>Service,如图:

命名为MusicService,然后Finish。然后拷贝一下代码。
MusicService代码:

package zj.dzh.music_list;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;

import java.util.Timer;
import java.util.TimerTask;

public class MusicService extends Service {
    private MediaPlayer player;
    private Timer timer;
    public MusicService() {}
    @Override
    public  IBinder onBind(Intent intent){
        return new MusicControl();
    }
    @Override
    public void onCreate(){
        super.onCreate();
        player=new MediaPlayer();//创建音乐播放器对象
    }
    public void addTimer(){ //添加计时器用于设置音乐播放器中的播放进度条
        if(timer==null){
            timer=new Timer();//创建计时器对象
            TimerTask task=new TimerTask() {
                @Override
                public void run() {
                    if (player==null) return;
                    int duration=player.getDuration();//获取歌曲总时长
                    int currentPosition=player.getCurrentPosition();//获取播放进度
                    Message msg=Music_Activity.handler.obtainMessage();//创建消息对象
                    //将音乐的总时长和播放进度封装至消息对象中
                    Bundle bundle=new Bundle();
                    bundle.putInt("duration",duration);
                    bundle.putInt("currentPosition",currentPosition);
                    msg.setData(bundle);
                    //将消息发送到主线程的消息队列
                    Music_Activity.handler.sendMessage(msg);
                }
            };
            //开始计时任务后的5毫秒,第一次执行task任务,以后每500毫秒执行一次
            timer.schedule(task,5,500);
        }
    }
    class MusicControl extends Binder{//Binder是一种跨进程的通信方式
        public void play(int i){//String path
                Uri uri=Uri.parse("android.resource://"+getPackageName()+"/raw/"+"music"+i);
                try{
                    player.reset();//重置音乐播放器
                    //加载多媒体文件
                    player=MediaPlayer.create(getApplicationContext(),uri);
                    player.start();//播放音乐
                    addTimer();//添加计时器
                }catch(Exception e){
                e.printStackTrace();
            }
        }
        public void pausePlay(){
            player.pause();//暂停播放音乐
        }
        public void continuePlay(){
            player.start();//继续播放音乐
        }
        public void seekTo(int progress){
            player.seekTo(progress);//设置音乐的播放位置
        }
    }
    @Override
    public void onDestroy(){
        super.onDestroy();
        if(player==null) return;
        if(player.isPlaying()) player.stop();//停止播放音乐
        player.release();//释放占用的资源
        player=null;//将player置为空
    }
}

3、右击包名,新建一个Activity,命名为Music_Activity,点击Finish,它会生成一个activity_music文件,用来显示音乐播放器界面。


(1)Music_Activity类:该类通过onClick方法控制着音乐的播放、暂停、继续播放和退出功能。它和MusicService进行绑定连接。在音乐播放时显示歌曲总时长,还有歌曲当前播放时长,控制滑动条的移动。代码如下:

package zj.dzh.music_list;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.animation.ObjectAnimator;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;

import static java.lang.Integer.parseInt;

public class Music_Activity extends AppCompatActivity implements View.OnClickListener{
    private static SeekBar sb;
    private static TextView tv_progress,tv_total,name_song;
    private ObjectAnimator animator;
    private MusicService.MusicControl musicControl;
    String name;
    Intent intent1,intent2;
    MyServiceConn conn;
    private boolean isUnbind =false;//记录服务是否被解绑
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_music);
        intent1=getIntent();
        init();
    }
    private void init(){
        tv_progress=(TextView)findViewById(R.id.tv_progress);
        tv_total=(TextView)findViewById(R.id.tv_total);
        sb=(SeekBar)findViewById(R.id.sb);
        name_song=(TextView)findViewById(R.id.song_name);

        findViewById(R.id.btn_play).setOnClickListener(this);
        findViewById(R.id.btn_pause).setOnClickListener(this);
        findViewById(R.id.btn_continue_play).setOnClickListener(this);
        findViewById(R.id.btn_exit).setOnClickListener(this);

        name=intent1.getStringExtra("name");
        name_song.setText(name);
        intent2=new Intent(this,MusicService.class);//创建意图对象
        conn=new MyServiceConn();//创建服务连接对象
        bindService(intent2,conn,BIND_AUTO_CREATE);//绑定服务
        //为滑动条添加事件监听
        sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @RequiresApi(api = Build.VERSION_CODES.KITKAT)
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                //进度条改变时,会调用此方法
                if (progress==seekBar.getMax()){//当滑动条到末端时,结束动画
                    animator.pause();//停止播放动画
                }
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {//滑动条开始滑动时调用
            }
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {//滑动条停止滑动时调用
                //根据拖动的进度改变音乐播放进度
                int progress=seekBar.getProgress();//获取seekBar的进度
                musicControl.seekTo(progress);//改变播放进度
            }
        });
        ImageView iv_music=(ImageView)findViewById(R.id.iv_music);
        String position= intent1.getStringExtra("position");
        int i=parseInt(position);
        iv_music.setImageResource(frag1.icons[i]);


        animator=ObjectAnimator.ofFloat(iv_music,"rotation",0f,360.0f);
        animator.setDuration(10000);//动画旋转一周的时间为10秒
        animator.setInterpolator(new LinearInterpolator());//匀速
        animator.setRepeatCount(-1);//-1表示设置动画无限循环
    }


    public static Handler handler=new Handler(){//创建消息处理器对象
        //在主线程中处理从子线程发送过来的消息
        @Override
        public void handleMessage(Message msg){
            Bundle bundle=msg.getData();//获取从子线程发送过来的音乐播放进度
            int duration=bundle.getInt("duration");
            int currentPosition=bundle.getInt("currentPosition");
            sb.setMax(duration);
            sb.setProgress(currentPosition);
            //歌曲总时长
            int minute=duration/1000/60;
            int second=duration/1000%60;
            String strMinute=null;
            String strSecond=null;
            if(minute<10){//如果歌曲的时间中的分钟小于10
                strMinute="0"+minute;//在分钟的前面加一个0
            }else{
                strMinute=minute+"";
            }
            if (second<10){//如果歌曲中的秒钟小于10
                strSecond="0"+second;//在秒钟前面加一个0
            }else{
                strSecond=second+"";
            }
            tv_total.setText(strMinute+":"+strSecond);
            //歌曲当前播放时长
            minute=currentPosition/1000/60;
            second=currentPosition/1000%60;
            if(minute<10){//如果歌曲的时间中的分钟小于10
                strMinute="0"+minute;//在分钟的前面加一个0
            }else{
                strMinute=minute+" ";
            }
            if (second<10){//如果歌曲中的秒钟小于10
                strSecond="0"+second;//在秒钟前面加一个0
            }else{
                strSecond=second+" ";
            }
            tv_progress.setText(strMinute+":"+strSecond);
        }
    };
    class MyServiceConn implements ServiceConnection{//用于实现连接服务
        @Override
        public void onServiceConnected(ComponentName name, IBinder service){
            musicControl=(MusicService.MusicControl) service;
        }
        @Override
        public void onServiceDisconnected(ComponentName name){

        }
    }
    private void unbind(boolean isUnbind){
        if(!isUnbind){//判断服务是否被解绑
            musicControl.pausePlay();//暂停播放音乐
            unbindService(conn);//解绑服务
        }
    }
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_play://播放按钮点击事件
                String position=intent1.getStringExtra("position");
                int i=parseInt(position);
                musicControl.play(i);
                animator.start();
                break;
            case R.id.btn_pause://暂停按钮点击事件
                musicControl.pausePlay();
                animator.pause();
                break;
            case R.id.btn_continue_play://继续播放按钮点击事件
                musicControl.continuePlay();
                animator.start();
                break;
            case R.id.btn_exit://退出按钮点击事件
                unbind(isUnbind);
                isUnbind=true;
                finish();
                break;
        }
    }
    @Override
    protected void onDestroy(){
        super.onDestroy();
        unbind(isUnbind);//解绑服务
    }
}

(2)activity_music:显示音乐播放器界面,包括图片转动,歌曲名传值,还有播放、暂停播放、继续播放和退出四个控制按钮。效果如图:

activity_music代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/music_bg"
    tools:context=".Music_Activity"
    android:gravity="center"
    android:orientation="vertical">
    <ImageView
        android:id="@+id/iv_music"
        android:layout_width="240dp"
        android:layout_height="240dp"
        android:layout_gravity="center_horizontal"
        android:layout_margin="15dp"
        android:src="@drawable/music0"/>
    <TextView
        android:id="@+id/song_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="歌曲名"
        android:textSize="20sp"/>
    <SeekBar
        android:id="@+id/sb"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="8dp"
        android:paddingRight="8dp">
        <TextView
            android:id="@+id/tv_progress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="00:00"/>
        <TextView
            android:id="@+id/tv_total"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="00:00"/>
    </RelativeLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btn_play"
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_margin="8dp"
            android:layout_weight="1"
            android:background="@drawable/btn_bg_selector"
            android:text="播放音乐"/>
        <Button
            android:id="@+id/btn_pause"
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_margin="8dp"
            android:layout_weight="1"
            android:background="@drawable/btn_bg_selector"
            android:text="暂停播放"/>
        <Button
            android:id="@+id/btn_continue_play"
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_margin="8dp"
            android:layout_weight="1"
            android:background="@drawable/btn_bg_selector"
            android:text="继续播放"/>
        <Button
            android:id="@+id/btn_exit"
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_margin="8dp"
            android:layout_weight="1"
            android:background="@drawable/btn_bg_selector"
            android:text="退出"/>
    </LinearLayout>

</LinearLayout>

(3)右击drawable文件夹,New——>Drawable Resource File,命名为btn_bg_selector,如图:

该文件为按钮颜色选择器,是当按钮按下的时候变成灰色,未按下显示白色。代码如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <corners android:radius="3dp"/>
            <solid android:color="#d4d4d4"/>
        </shape>
    </item>
    <item android:state_pressed="false">
        <shape android:shape="rectangle">
            <corners android:radius="3dp"/>
            <solid android:color="#ffffff"/>
        </shape>
    </item>
</selector>

4、右击包名,New——>Java Class,命名为frag1,点击OK。如图:

(1)frag1类:显示歌曲菜单,手机模拟器运行出来的默认界面,代码如下:

package zj.dzh.music_list;

import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import androidx.fragment.app.Fragment;

public class frag1 extends Fragment {
    private View view;
    public String[] name={"邓紫棋——光年之外","蔡健雅——红色高跟鞋","Taylor Swift——Love Story"};
    public static int[] icons={R.drawable.music0,R.drawable.music1,R.drawable.music2};
    @Override
    public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        view=inflater.inflate(R.layout.music_list,null);
        ListView listView=view.findViewById(R.id.lv);
        MyBaseAdapter adapter=new MyBaseAdapter();
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent=new Intent(frag1.this.getContext(),Music_Activity.class);//创建Intent对象,启动check
                //将数据存入Intent对象
                intent.putExtra("name",name[position]);
                intent.putExtra("position",String.valueOf(position));
                startActivity(intent);
            }
        });
        return view;
    }
    class MyBaseAdapter extends BaseAdapter{
        @Override
        public int getCount(){return  name.length;}
        @Override
        public Object getItem(int i){return name[i];}
        @Override
        public long getItemId(int i){return i;}

        @Override
        public View getView(int i ,View convertView, ViewGroup parent) {
            View view=View.inflate(frag1.this.getContext(),R.layout.item_layout,null);
            TextView tv_name=view.findViewById(R.id.item_name);
            ImageView iv=view.findViewById(R.id.iv);

            tv_name.setText(name[i]);
            iv.setImageResource(icons[i]);
            return view;
        }
    }


}

(2)右击layout文件夹,New———>Layout Resource File,新建两个layout文件,分别命名为music_list和item_layout,这两个菜单布局文件和frag1对应,显示歌曲列表。如图所示:

music_list:歌曲列表布局文件,和QQ好友列表功能相同,垂直显示多条记录。效果如图:

music_list代码如下:

<?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="match_parent"
    android:orientation="vertical">
    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

item_layout: 和上面的music_list一起使用组成音乐列表界面,布局效果如图:
item_layout代码如下:

<?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:padding="16dp">
    <ImageView
        android:id="@+id/iv"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_centerVertical="true"/>
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@+id/iv"
        android:layout_centerVertical="true">
        <TextView
            android:id="@+id/item_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="歌曲"
            android:textSize="15sp"
            android:textColor="#000000"/>
    </RelativeLayout>
</RelativeLayout>

5、右击包名,New——>Java Class,命名为frag2,点击OK。如图:
(1)frag2类:展示的封面专辑图片,在主界面点击专辑按钮跳转到此界面。代码如下:

package zj.dzh.music_list;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import androidx.fragment.app.Fragment;

public class frag2 extends Fragment {
    private View zj;

    public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        zj = inflater.inflate(R.layout.frag2_layout, null);
        ImageView listView = zj.findViewById(R.id.lv);
        return zj;

    }
}

(2)再新建一个layout文件,命名为frag2_layout,如图:

frag2_layout用来设置一个ImageView,显示专辑图片,代码如下:

<?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="match_parent">
    <ImageView
        android:id="@+id/zj"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/bg"/>

</LinearLayout>

6、将准备的音频文件和图片导入。
在drawable文件夹下新建一个raw文件夹,将刚刚准备好的视频文件复制到raw文件夹中。对应的封面圆形图片、背景图片和专辑图片都复制到drawable中,这里我只选择了三首歌曲和三张封面圆形图片,数量由大家自己设置,没有限制。

至此,完整的音乐播放器项目创建完成。

四、运行效果

选择自己的模拟器运行,如果没有模拟器可以点击AVD,选择新建模拟器:

选择API 24下载即可,如图:

(1)打开手机模拟器,显示主界面:

(2)点击专辑选项卡:

(3)再打开歌曲选项卡,选择第一首歌《光年之外》并打开,跳转到播放页面,歌手的封面图片显示在正中间,发现《光年之外》的歌名也传递过来了:


(4)点击播放音乐按钮,音乐开始播放,进度条开始滑动,图片开始旋转:

(5)点击暂停播放按钮,音乐停止播放,而且进度条停止滑动,图片也停止旋转:

(6)点击继续播放按钮,音乐继续播放,歌手图片也继续旋转:

(7)点击退出按钮,会退回到主界面:

(8)选择第二首歌《红色高跟鞋》并播放,这里进度条可以自由拖动,歌曲也会随之播放到对应位置:

(9)选择第三首歌《Love Story》并播放:

运行效果和功能很完整,至此完成了音乐播放器的实现,喜欢的朋友们可以自己动手做一下,放上自己喜欢的偶像照片,还有喜欢的歌,体验感真的不要太好!

工程文件的链接我发在下面,大家也可以下载下来运行一波。
Music_List 工程文件下载

其实,人的潜能不是在不知不觉中被发现的,而是我们某个时候把一件事做到了极致。努力了,奋斗了,就没有遗憾。


转载:https://blog.csdn.net/qq_42257666/article/details/105555550
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场