手把手教你做音乐播放器(六)存储多首音乐

第6节 存储多首音乐

我们已经能够存储单首音乐了,接下来我们开始添加一次存储多首音乐的界面设计。

当用户长按某首音乐项的时候,将进入ListView的多选modal状态,我们叫它模式框。

6.1 ListView的选择模式

在理解这个模式框之前,我们要先进一步了解一下ListView

ListView本身带有单选和多选功能,也就是说在单选模式下,它能够记住当前选中的唯一的列表项;在多选模式下,它能够记住目前选取的所有的列表项。

这种选择模式共有4种CHOICE_MODE_NONE CHOICE_MODE_SINGLE CHOICE_MODE_MULTIPLE CHOICE_MODE_MULTIPLE_MODAL

使用setChoiceMode()函数,就可以设置ListView的选择模式。

ListView lv = (ListView) findViewById(R.id.list_view);
lv.setChoiceMode(ListView.CHOICE_MODE_NONE);

6.1.1 CHOICE_MODE_NONE

这是ListView默认的选择模式,当使用者点击列表项后,不会将任何点击的列表项当成被选择上的列表项。

6.1.2 CHOICE_MODE_SINGLE

使用这个选项模式,当使用者点击列表项后,会将最后一次点击的列表项当成被选择上的列表项。

ArrayAdapter adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_single_choice , datalist);
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lv.setAdapter(adapter);

每次点击列表项,可以在它的监听函数中得知哪个列表项被点击了,

lv.setOnItemClickListener(new ListView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        //添加需要响应的操作
    }
}

以后就可以通过ListViewgetCheckedItemPositions()获取被选中的数据项的位置列表,

SparseBooleanArray checkedItems = lv.getCheckedItemPositions();

例如,当列表项按照序号为3->2->1-7的顺序被点击后,7将被记录下来,作为当前被选中的数据项。调用getCheckedItemPositions()后,将得到一个键值对,里面只会记录,

key=7, value=true

这里为了看到被选中的效果,采用了Android SDK提供的android.R.layout.simple_list_item_single_choice布局,作为列表项的布局。

6.1.3 CHOICE_MODE_MULTIPLE

使用这个选项模式,当使用者点击列表项后,会将所有点击的列表项当成被选择上的列表项。

ArrayAdapter adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_multiple_choice, datalist);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lv.setAdapter(adapter);

每次点击列表项,可以在它的监听函数中得知哪个列表项被点击了,

lv.setOnItemClickListener(new ListView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        //添加需要响应的操作
    }
}

通过ListViewgetCheckedItemPositions()获取被选中的数据项的位置列表,

SparseBooleanArray checkedItems = lv.getCheckedItemPositions();

例如,当列表项按照序号为3->2->1->7的顺序被点击后,3 2 1 7将被记录下来,作为当前被选中的数据项。调用getCheckedItemPositions()后,将得到一个个键值对,里面会记录,

key=1, value=true
key=2, value=true
key=3, value=true
key=7, value=true

这些记录,将按照列表项的位置从小到大排列。

如果用户在已经被选上的数据项上,又再次点击,这将取消对它的选择。例如,当列表项按照序号为3->2->1->7->2->1的顺序被点击后,就变成了,

key=1, value=false
key=2, value=false
key=3, value=true
key=7, value=true

对于被取消了选择的列表项,并不会从记录中移除,而是改变它的值成false

这里为了看到被选中的效果,采用了Android SDK提供的android.R.layout.simple_list_item_multiple_choice布局,作为列表项的布局。

6.1.4 CHOICE_MODE_MULTIPLE_MODAL

CHOICE_MODE_MULTIPLE_MODAL模式中,用户必须通过长按任意一个列表项,进入多选模式,否则不能进行多选。

这个模式的使用与CHOICE_MODE_MULTIPLE类似,不过它需要设置一个ActionMode,这样才能在长按列表项后,改变ActionBar的菜单栏,打开多选的菜单。

  1. 实现ListViewMultiChoiceModeListener接口,

    private class MyMultiChoiceModeListener implements ListView.MultiChoiceModeListener {
    
        @Override
        public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
    
            //添加列表项被点击后的响应
        }
    
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            //这里返回true
            return true;
        }
    
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            //这里返回true
            return true;
        }
    
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            //这里返回true
            return true;
        }
    
        @Override
        public void onDestroyActionMode(ActionMode mode) {
    
        }
    }
  2. 使用创建的接口,传递给ListView
    ArrayAdapter adapter = new ArrayAdapter<String>(this,
                    android.R.layout.simple_list_item_multiple_choice, datalist);
    lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
    
    ListView.MultiChoiceModeListener callback = new MyMultiChoiceModeListener();
    lv.setMultiChoiceModeListener(callback);
    lv.setAdapter(adapter);

CHOICE_MODE_MULTIPLE_MODAL模式下,对列表项的点击,是在ListView.MultiChoiceModeListeneronItemCheckedStateChanged()函数中响应的。

这里为了看到被选中的效果,采用了Android SDK提供的android.R.layout.simple_list_item_multiple_choice布局,作为列表项的布局。

6.1.5 关于单选和多选的状态背景

前面的演示中,分别对不同的选择模式,使用了不同的数据项布局,

CHOICE_MODE_SINGLE         --> android.R.layout.simple_list_item_single_choice
CHOICE_MODE_MULTIPLE       --> android.R.layout.simple_list_item_multiple_choice
CHOICE_MODE_MULTIPLE_MODAL --> android.R.layout.simple_list_item_multiple_choice

我们也可以选择自己的布局来实现。但是不管使用什么布局,我们都希望被选上的列表项有特别的效果,和其他没有被选上的数据项区别开。这里有两种方案,

  1. 使用实现了Clickable接口的控件或者布局,作为数据项的布局。例如前面我们使用的android.R.layout.simple_list_item_multiple_choice android.R.layout.simple_list_item_single_choice等,它们本身就是CheckedTextView。当点击它们的时候,它们就自带了勾选框,可以看到效果。

    所以,可以选择CheckBox Switch这类同样实现了Clickable接口的布局来表现;也可以自定义一个实现了Clickable接口的布局。这里用android.R.layout.simple_list_item_multiple_choice的实现来举个例子,

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeightSmall"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:checkMark="?android:attr/listChoiceIndicatorMultiple"
        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
  2. 给数据项的布局使用一个Selector,告诉这个布局,当它被activated以后要怎么显示。比如,定义一个布局custom_item_layout.xml,
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="48dp" --> 为了布局好看设置一个最小高度
        android:gravity="center_vertical"
        android:padding="5dp"
        android:background="@drawable/selector">
    
    </TextView>

    给这个布局设计一个selector,增加对android:activated属性的设置,

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_activated="true" android:drawable="@color/yellow"/>
    </selector>

    使用这个这个布局,

    ArrayAdapter adapter = new ArrayAdapter<String>(this,
                    R.layout.custom_item_layout, datalist);
    lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    lv.setAdapter(adapter);

    当我们多选的时候,那些选中项,就变成黄色,看到如下的界面,

6.2 选择多首音乐

接下来,我们将上面学到的方法应用到我们当前的项目中。

  1. 创建music_choice_actionbar.xml菜单项,

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
        <item
            android:title="@string/play"
            android:id="@+id/menu_play"/>
    </menu>
  2. 定义一个MultiChoiceModeListener,将菜单项和菜单项被点击后的响应添加进去,
    private ListView.MultiChoiceModeListener mMultiChoiceListener = new AbsListView.MultiChoiceModeListener() {
    
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    
            //增加进入modal模式后的菜单栏菜单项
            getMenuInflater().inflate(R.menu.music_choice_actionbar, menu);
            return true;
        }
    
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return true;
        }
    
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch(item.getItemId()) {
                case R.id.menu_play: {
                    //这里添加点击添加到播放列表后的响应
                }
                break;
            }
            return true;
        }
    
        @Override
        public void onDestroyActionMode(ActionMode mode) {
    
        }
    
        @Override
        public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
    
        }
    };
  3. 将音乐列表设置成多选modal模式,
    public class MusicListActivity extends AppCompatActivity {
    
        ......
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_music_list);
    
            mMusicList = new ArrayList<MusicItem>();
            mMusicListView = (ListView) findViewById(R.id.music_list);
            MusicItemAdapter adapter = new MusicItemAdapter(this, R.layout.music_item, mMusicList);
            mMusicListView.setAdapter(adapter);
            mMusicListView.setOnItemClickListener(mOnMusicItemClickListener);
    
            //设置多选modal模式
            mMusicListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL);
            //设置多选模式变化的监听器
            mMusicListView.setMultiChoiceModeListener(mMultiChoiceListener);
        }
    
        ......
    }
  4. 为了便于观察哪些音乐处于多选状态,我们让被选择的数据项处于高亮状态,
    1. res\drawable目录下,定义一个高亮的selector-menu_item_selector

      <selector xmlns:android="http://schemas.android.com/apk/res/android">
          <item android:state_activated="true" android:drawable="@color/colorHighlight"/>
      </selector>
    2. 给音乐项的布局文件music_item.xml设置上高亮的selector
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="horizontal"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="@drawable/menu_item_selector">
      
          <ImageView>
              ......
          </ImageView>
      
          <LinearLayout>
              ......
          </LinearLayout>
      
      </LinearLayout>
  5. 增加添加到播放列表的功能,
    private ListView.MultiChoiceModeListener mMultiChoiceListener = new AbsListView.MultiChoiceModeListener() {
    
        ......
    
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch(item.getItemId()) {
                case R.id.menu_play: {
                    //获取被选中的音乐项
                    List musicList = new ArrayList<MusicItem>();
                    SparseBooleanArray checkedResult = mMusicListView.getCheckedItemPositions();
                    for (int i = 0; i < checkedResult.size(); i++) {
                        if(checkedResult.valueAt(i)) {
                            int pos = checkedResult.keyAt(i);
                            MusicItem music = mMusicList.get(pos);
                            musicList.add(music);
                        }
                    }
    
                    //调用MusicService提供的接口,把播放列表保存起来
                    mMusicService.addPlayList(musicList);
    
                    //退出ListView的modal状态
                    mode.finish();
                }
                break;
            }
            return true;
        }
    
        ......
    };


    现在长按数据项,点击看看,已经能够成功的把选上的音乐添加到播放列表了。



/*******************************************************************/

* 版权声明

* 本教程只在CSDN安豆网发布,其他网站出现本教程均属侵权。

*另外,我们还推出了Arduino智能硬件相关的教程,您可以在我们的网店安豆的杂货铺中购买相关硬件。同时也感谢大家对我们这些码农的支持。

*最后再次感谢各位读者对安豆的支持,谢谢:)

/*******************************************************************/

时间: 2024-07-31 08:01:33

手把手教你做音乐播放器(六)存储多首音乐的相关文章

委托实现音乐播放器 | 委托实现音乐播放器的缺点 | 事件实现音乐播放器

1,使用委托实现一个音乐播放器的功能呢.(模拟事件) using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace 模拟事件 { /// <summary> /// 音乐播放器类 /// </summary> public class MusicP

Android开发本地及网络Mp3音乐播放器(六)实现独立音乐播放界面

实现功能: 功能1:点击MyMusicListFragment(本地音乐)底部UI中的专辑封面图片打开的PlayActivity(独立音乐播放界面) PlayActivity中,显示正在播放的歌名 PlayActivity中,显示专辑封面图片(大图) PlayActivity中,显示上一首按钮,实现对应功能 PlayActivity中,显示暂停播放按钮,实现对应功能 PlayActivity中,显示下一首,实现对应功能 功能2:实现同步MyMusicListFragment(本地音乐界面)和Pl

android 在音乐播放器中设置一首歌曲为来电铃声,设置不起作用

AudioProfile,情景模式,多卡设置铃声 系统开启Multi_ringtone_support.进入菜单--音乐--歌曲列表--长按一首歌曲选择设为手机铃声,提示已成功设置,但是进入设置中情景模式查看,仍然是默认铃声.打电话后铃声还为默认铃声. 修改: AudioProfileService.java mRingtoneObserver = new ContentObserver(new Handler())函数里面的 case GENERAL: case OUTDOOR: if (mE

MediaPlayer音乐播放器、上一首、下一首、播放、停止、自动下一首、进度条

本文介绍MediaPlayer的使用.MediaPlayer可以播放音频和视频,另外也可以通过VideoView来播放视频,虽然VideoView比MediaPlayer简单易用,但定制性不如用MediaPlayer,要视情况选择了.MediaPlayer播放音频比较简单,但是要播放视频就需要SurfaceView.SurfaceView比普通的自定义View更有绘图上的优势,它支持完全的OpenGL ES库. 先贴出本文程序运行结果的截图,下面是上一首.下一首.播放.停止.自动下一首.可用Se

使用ivx制作音乐播放器的经验总结

今天我们要使用ivx制作一个音乐播放器,功能包括控制音乐的播放.暂停,能够通过点击或者拖拽调节音乐的播放进度,下面说一下具体的实现方法.一.demo布局首先看一下demo的结构,横幅下两个文本组件用于展示音乐信息,其余内容放置在画布中,布局上可以分为一个播放/暂停模块和一个进度条模块,分别放置在两个对象组中,另外还有一些变量.动作组和触发器.二.音乐组件既然是音乐播放器,自然就需要添加一个音乐组件啦.在素材资源地址里上传我们的音乐素材,这里注意一下如果音频素材比较大的话不建议开启预加载模式.三.

Simple2D-14(音乐播放器)简介

接下来文章中,会介绍一个简单的程序--音乐播放器.通过编写一个音乐播放器在 Simple2D 中加入两个库:音频库 bass 和界面库 ImGui. 下面是音乐播放器的预览图: 播放器的功能比较简单,音频播放使用了 bass 库,界面则是使用 ImGui 库.

简易音乐播放器制作

制作简易音乐播放器: 1.功能:音乐列表,播放,暂停,上一曲,下一曲,进度条(显示进度时间,控制进度),随机播放,单曲循环,顺序播放,歌词显示等 2.使用框架:AVFoundation 3.知识点:AVPlayer 使用,pch 文件使用,封装思想,MVC模式,storyBoard的使用,消息发送机制,观察者,block回调,nstimer,nsrunloop,空间约束,第三方使用等 详细过程: 一.布局 :使用 storyBoard 布局 1.歌曲列表界面:使用 TableViewContro

Android(java)学习笔记234: 服务(service)之音乐播放器

1.我们播放音乐,希望在后台长期运行,不希望因为内存不足等等原因,从而导致被gc回收,音乐播放终止,所以我们这里使用服务Service创建一个音乐播放器. 2.创建一个音乐播放器项目(使用服务) (1)首先新建一个Android项目,命名为"Mp3音乐播放器",如下: (2)创建服务MusicService,如下: 1 package com.himi.Mp3player; 2 3 import android.app.Service; 4 import android.content

Ubuntu 14.04 用户如何安装深度音乐播放器和百度音乐插件

播放本地音乐或者收听国外的音乐电台,Ubuntu 14.04 自带的音乐播放器 Rhythmbox 完全能够满足,但是如果你想有像酷狗那样的国内播放器就需要折腾一下,还好有深度音乐播放器,这是一款完全为中国人开发的音乐播放器,深度音乐播放器(Dmusic)+ 百度音乐插件=酷狗,但是如果是deepin系统用户就完全不需要折腾了.先截图一下: 安装方法 (注释:我的系统是Ubuntu 14.04 其他系统没有实验,所以不保证是否成功) 先安装深度音乐播放器,安装很方便,有PPA可用,不过安装之前需