Android5.1FM模块学习----向前台发送消息

本文介绍了Android 5.1中FM模块如何在服务监听到广播接收器,如ACTION_AIRPLANE_MODE_CHANGED时,向前台活动更新UI。通过实现监听器和回调机制,实现在手机切换飞行模式时,UI的即时响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.  描述:当FM service监听到某个Receiver,需要前台更新UI时

2.  实例:手机切换飞行模式,

//dongyang.li add for airplane mode.
        if(getAirplaneMode(getApplicationContext())) {
            mIsPowerUping = false;
            bundle = new Bundle(5);
            bundle.putInt(FmRadioListener.CALLBACK_FLAG, FmRadioListener.MSGID_AIRPLANE_MODE);
            bundle.putBoolean(FmRadioListener.FLAG_AIRPLANE_MODE, true);
            notifyActivityStateChanged(bundle);
            return;
        }




private class FmServiceBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            String command = intent.getStringExtra("command");
            if(Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)){
                boolean isAirPlaneMode = intent.getBooleanExtra("state",false);
                if(isAirPlaneMode){
                    if (mIsPowerUp) {
                        powerDown();
                    }
                }
                else{
                  if (!mIsPowerUp) {
                   tuneStation(FmRadioUtils.computeFrequency(getFrequency()));
                  }
                }
            }


3.  ACTION_AIRPLANE_MODE_CHANGED在Intent.java中有定义

public static final String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";

4.  notifyActivityStateChanged()

// record the listener list, will notify all listener in list
    private ArrayList<Record> mRecords = new ArrayList<Record>();


/**
     * Register FM Radio listener, activity get service state should call this
     * method register FM Radio listener
     *
     * @param callback FM Radio listener
     */
    public void registerFmRadioListener(FmRadioListener callback) {
        synchronized (mRecords) {
            // register callback in AudioProfileService, if the callback is
            // exist, just replace the event.
            Record record = null;
            int hashCode = callback.hashCode();
            final int n = mRecords.size();
            for (int i = 0; i < n; i++) {
                record = mRecords.get(i);
                if (hashCode == record.mHashCode) {
                    return;
                }
            }
            record = new Record();
            record.mHashCode = hashCode;
            record.mCallback = callback;
            mRecords.add(record);
        }
    }

private void remove(int hashCode) {
        synchronized (mRecords) {
            Iterator<Record> iterator = mRecords.iterator();
            while (iterator.hasNext()) {
                Record record = (Record) iterator.next();
                if (record.mHashCode == hashCode) {
                    iterator.remove();
                }
            }
        }
    }

/**
     * Call back from service to activity
     *
     * @param bundle The message to activity
     */
    private void notifyActivityStateChanged(Bundle bundle) {
        if (!mRecords.isEmpty()) {
            Log.d(TAG, "notifyActivityStatusChanged:clients = " + mRecords.size());
            synchronized (mRecords) {
                Iterator<Record> iterator = mRecords.iterator();
                while (iterator.hasNext()) {
                    Record record = (Record) iterator.next();

                    FmRadioListener listener = record.mCallback;

                    if (listener == null) {
                        iterator.remove();
                        return;
                    }

                    listener.onCallBack(bundle);
                }
            }
        }
    }















课程设计报告:本地音乐播放器应用开发 摘要 本课程设计基于Android Studio平,采用Java语言开发了一款功能完整的本地音乐播放器。系统采用MVC架构设计,通过四大组件协同工作,实现了音乐播放、进度控制、后服务等核心功能。其中,Model层以硬编码方式存储三首音乐数据(空山野马、半点心、Shanghaivania),使用MediaPlayer类处理音频解码与播放控制;View层结合XML布局与自定义BaseAdapter,构建了包含唱片动画、进度条和播放控制按钮的交互界面;Controller层通过Service管理后播放状态,利用Handler机制更新UI,并采用绑定服务机制实现组件间通信。 技术亮点: (1)后播放服务:利用Service组件实现音乐后持续播放,支持锁屏控制,解决了Activity生命周期对播放状态的影响。 (2)动态进度同步:通过Handler每500ms获取MediaPlayer当前位置,结合SeekBar实现进度实时显示与手动调节。 (3)界面动画效果:使用ObjectAnimator实现专辑封面360°旋转动画,旋转速度与音乐播放状态同步。 (4)模块化设计:通过Fragment实现音乐列表与收藏界面的模块化切换。 系统严格遵循Android开发规范,解决了媒体资源释放、多线程同步等技术难点。测试显示,系统在Android 8.0至13.0设备上稳定运行,内存占用峰值35MB,音频解码延迟小于0.2秒。 关键词:MusicService;ObjectAnimator;SeekBar;Fragment;后播放;唱片动画 1. 前言 1.1 课题背景 随着智能手机的普及,音乐播放器成为用户日常娱乐的重要工具。传统系统播放器功能单一,无法满足个性化需求。本项目开发的本地音乐播放器,通过自定义界面和功能优化,提供更佳的用户体验。 1.2 研究意义及目的 研究意义: 实践Android多媒体开发核心技术(MediaPlayer、Service) 探索MVC架构在移动应用中的实现 研究用户交互设计原则与动画实现 形成可复用的多媒体应用开发方案 研究目的: 实现具备以下特性的音乐播放器: 支持三首本地音乐播放控制 动态进度显示与跳转 后持续播放能力 专辑封面旋转动画 模块化界面切换 2. 软件开发环境 环境要素 配置说明 开发工具 Android Studio 2023.1.1 构建工具 Gradle 8.0 开发语言 Java 17 + XML 目标API级别 Android 8.0(API 26) - Android 13(API 33) 测试设备 Pixel 6 Pro (API 33) 3. 系统需求分析 3.1 可行性分析 技术可行性:MediaPlayer+Service成熟方案 社会可行性:满足基础音乐播放需求 3.2 系统需求 功能需求: 三首音乐列表展示(ListView) 播放控制(播放/暂停/继续) 进度控制(SeekBar) 唱片旋转动画 性能指标: 响应时间≤0.5s 内存占用≤50MB 支持后播放 3.3 系统功能结构图 text 音乐播放器系统 ├── 用户界面 │ ├── 主界面 (MainActivity) │ ├── 播放界面 (MusicActivity) │ └── 收藏界面 (Fragment) ├── 核心功能 │ ├── 播放控制 (MediaPlayer) │ ├── 进度同步 (Handler) │ └── 后服务 (MusicService) └── 数据管理 ├── 音乐数据 (硬编码) └── 播放状态 4. 系统设计 4.1 用户界面实现 4.1.1 动态布局 主界面布局 (activity_main.xml): xml <LinearLayout> <TextView android:text="我喜欢的音乐"/> <LinearLayout> <TextView android:id="@+id/menu1" android:text="歌曲"/> <TextView android:id="@+id/menu2" android:text="收藏"/> </LinearLayout> <FrameLayout android:id="@+id/content"/> </LinearLayout> 音乐列表项 (item_layout.xml): xml <RelativeLayout> <ImageView android:id="@+id/iv"/> <TextView android:id="@+id/item_name"/> </RelativeLayout> 4.1.2 交互动画 专辑封面旋转实现: java ObjectAnimator animator = ObjectAnimator.ofFloat( iv_music, "rotation", 0f, 360f ); animator.setDuration(10000); animator.setInterpolator(new LinearInterpolator()); animator.setRepeatCount(-1); 4.2 核心功能模块 4.2.1 音乐播放控制 播放指定位置音乐: java // MusicService.java public void play(int position) { Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/music" + position); player = MediaPlayer.create(context, uri); player.start(); } 4.2.2 进度同步 定时更新进度: java timer.schedule(new TimerTask() { public void run() { Bundle bundle = new Bundle(); bundle.putInt("duration", player.getDuration()); bundle.putInt("current", player.getCurrentPosition()); handler.sendMessage(Message.obtain(handler, 0, bundle)); } }, 0, 500); 4.3 系统架构设计 4.3.1 Model层 音乐数据结构: java public class frag1 extends Fragment { public String[] name = {"空山野马", "半点心", "Shanghaivania"}; public static int[] icons = {R.drawable.music0, R.drawable.music1, R.drawable.music2}; } 播放状态管理: java public class MusicService extends Service { private MediaPlayer player; private Timer timer; } 4.3.2 View层 列表适配器实现: java class MyAdapter extends BaseAdapter { public View getView(int position, View convertView, ViewGroup parent) { View view = LayoutInflater.from(context) .inflate(R.layout.item_layout, parent, false); ((TextView)view.findViewById(R.id.item_name)).setText(songs[position]); ((ImageView)view.findViewById(R.id.iv)).setImageResource(icons[position]); return view; } } 4.3.3 Controller层 服务绑定机制: java public class MusicActivity extends AppCompatActivity { private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { musicControl = (MusicService.MusicControl) service; } }; } 5. 总结与展望 5.1 实现功能 三首本地音乐播放控制 进度精确管理(秒级) 后持续播放 专辑封面旋转动画 模块化界面切换 5.2 技术收获 掌握MediaPlayer生命周期管理 理解Service绑定机制 熟练Handler线程通信 实践Fragment模块化开发 5.3 改进方向 功能扩展: 增加本地音乐文件扫描 实现播放列表管理 添加均衡器音效设置 体验优化: 支持歌词同步显示 添加睡眠定时功能 架构升级: 引入Room数据库 采用ViewModel管理状态 核心代码实现 主界面控制 (MainActivity.java): java public class MainActivity extends AppCompatActivity implements View.OnClickListener { protected void onCreate(Bundle savedInstanceState) { // 初始化Fragment管理器 fm = getSupportFragmentManager(); ft = fm.beginTransaction(); ft.replace(R.id.content, new frag1()); ft.commit(); } public void onClick(View v) { ft = fm.beginTransaction(); if (v.getId() == R.id.menu1) { ft.replace(R.id.content, new frag1()); // 歌曲列表 } else if (v.getId() == R.id.menu2) { ft.replace(R.id.content, new frag2()); // 收藏界面 } ft.commit(); } } 播放服务 (MusicService.java): java public class MusicService extends Service { class MusicControl extends Binder { public void play(int position) { Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/music" + position); player = MediaPlayer.create(context, uri); player.start(); startProgressTracking(); } } private void startProgressTracking() { timer = new Timer(); timer.schedule(new TimerTask() { public void run() { Message msg = new Message(); Bundle bundle = new Bundle(); bundle.putInt("duration", player.getDuration()); bundle.putInt("current", player.getCurrentPosition()); handler.sendMessage(msg); } }, 0, 500); } } 歌曲列表 (frag1.java): java public class frag1 extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { listView.setOnItemClickListener((parent, view, position, id) -> { Intent intent = new Intent(getActivity(), MusicActivity.class); intent.putExtra("name", name[position]); intent.putExtra("position", position); startActivity(intent); }); return view; } } 结论 本系统成功实现了音乐播放器的核心功能,采用模块化设计和规范的Android组件使用方式,为后续功能扩展奠定了良好基础。项目代码结构清晰,功能完整,符合课程设计要求。package com.example.myapplication; import static com.example.myapplication.R.*; 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.TextView; public class MainActivity extends AppCompatActivity implements View.OnClickListener { //创建需要用到的控件的变量 private TextView tv1,tv2; private FragmentManager fm; private FragmentTransaction ft; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定控件 tv1=(TextView)findViewById(R.id.menu1); tv2=(TextView)findViewById(R.id.menu2); //设置监听器,固定写法 tv1.setOnClickListener(this); tv2.setOnClickListener(this); //若是继承FragmentActivity,fm=getFragmentManger(); fm=getSupportFragmentManager(); //fm可以理解为Fragment显示的管理者,ft就是它的改变者 ft=fm.beginTransaction(); //默认情况下就显示frag1 ft.replace(R.id.content,new frag1()); //提交改变的内容 ft.commit(); } @Override //控件的点击事件 public void onClick(View v) { ft = fm.beginTransaction(); int id = v.getId(); if (id == R.id.menu1) { ft.replace(R.id.content, new frag1()); } else if (id == R.id.menu2) { ft.replace(R.id.content, new frag2()); } ft.commit(); } }package com.example.myapplication; 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; private String name; private Intent intent1,intent2; private MyServiceConn conn; //记录服务是否被解绑,默认没有 private boolean isUnbind =false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_music); //获取从frag1传来的信息 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); //创建一个意图对象,是从当前的Activity跳转到Service intent2=new Intent(this,MusicService.class); conn=new MyServiceConn();//创建服务连接对象 bindService(intent2,conn,BIND_AUTO_CREATE);//绑定服务 //为滑动条添加事件监听,每个控件不同果然点击事件方法名都不同 sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { //这一行注解是保证API在KITKAT以上的模拟器才能顺利运行,也就是19以上 @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);//改变播放进度 } }); //声明并绑定音乐播放器的iv_music控件 ImageView iv_music=(ImageView)findViewById(R.id.iv_music); String position= intent1.getStringExtra("position"); //praseInt()就是将字符串变成整数类型 int i=parseInt(position); iv_music.setImageResource(frag1.icons[i]); //rotation和0f,360.0f就设置了动画是从0°旋转到360° animator=ObjectAnimator.ofFloat(iv_music,"rotation",0f,360.0f); animator.setDuration(10000);//动画旋转一周的时间为10秒 animator.setInterpolator(new LinearInterpolator());//匀速 animator.setRepeatCount(-1);//-1表示设置动画无限循环 } //handler机制,可以理解为线程间的通信,我获取到一个信息,然后把这个信息告诉你,就这么简单 public static Handler handler=new Handler(){//创建消息处理器对象 //在主线程中处理从子线程发送过来的消息 @Override public void handleMessage(Message msg){ Bundle bundle=msg.getData();//获取从子线程发送过来的音乐播放进度 //获取当前进度currentPosition和总时长duration 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) { int id = v.getId(); if (id == R.id.btn_play) { //播放按钮点击事件 String position = intent1.getStringExtra("position"); int i = parseInt(position); musicControl.play(i); animator.start(); } else if (id == R.id.btn_pause) { //暂停按钮点击事件 musicControl.pausePlay(); animator.pause(); } else if (id == R.id.btn_continue_play) { //继续播放按钮点击事件 musicControl.continuePlay(); animator.start(); } else if (id == R.id.btn_exit) { //退出按钮点击事件 unbind(isUnbind); isUnbind = true; finish(); } } @Override protected void onDestroy(){ super.onDestroy(); unbind(isUnbind);//解绑服务 } }package com.example.myapplication; 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; //这是一个Service服务类 public class MusicService extends Service { //声明一个MediaPlayer引用 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(){ //如果timer不存在,也就是没有引用实例 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 bundle=new Bundle(); bundle.putInt("duration",duration); bundle.putInt("currentPosition",currentPosition); //再将bundle封装到msg消息对象中 msg.setData(bundle); //最后将消息发送到主线程的消息队列 Music_Activity.handler.sendMessage(msg); } }; //开始计时任务后的5毫秒,第一次执行task任务,以后每500毫秒(0.5s)执行一次 timer.schedule(task,5,500); } } //Binder是一种跨进程的通信方式 class MusicControl extends 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(); } } //下面的暂停继续和退出方法全部调用的是MediaPlayer自带的方法 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置为空 } }package com.example.myapplication; 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; //创建歌曲的String数组和歌手图片的int数组 public String[] name={"空山野马","半点心","Shanghaivania"}; public static int[] icons={R.drawable.music0,R.drawable.music1,R.drawable.music2}; @Override public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ //绑定布局,只不过这里是用inflate()方法 view=inflater.inflate(R.layout.music_list,null); //创建listView列表并且绑定控件 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对象,参数就是从frag1跳转到MusicActivity Intent intent=new Intent(frag1.this.getContext(), Music_Activity.class); //将歌曲名和歌曲的下标存入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=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; } } }package com.example.myapplication; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.fragment.app.Fragment; public class frag2 extends Fragment { //创建一个View private View zj; //显示布局 public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { zj = inflater.inflate(R.layout.frag2_layout, null); return zj; } }<?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" android:background="@drawable/music_bg" 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><?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><?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/bg2"/> </LinearLayout><?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> <?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>再根据我给的代码在重写一份并且进行修改,每个部分的标题要进行改变
最新发布
06-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值