今天掐指一算,学习Android长达近两个月了,今天开始,对过去一段时间的学习收获以及遇到的疑难杂症做一些总结。

简单音乐播放器是我自己完成的第一个功能较为完整的APP,可以说是我的Android学习之路上的一个小小里程碑,给我增加了很多信心(~~真容易获得满足~~)。从下面开始,我将详细介绍MusicPlayer的设计过程。

首先,先看一下这个项目的工程目录和运行效果:

    

从上面的图片看到,整个工程的布局文件有两个:activity_main.xml和musiclist.xml,其中,musiclist.xml中放置了两个TextView,分别对应歌曲名称和演唱者,结合activity_main.xml中的ListView,完成一张音乐文件列表。播放页面的其他组件的布局则由activity_main.xml完成。具体如下:

activity_main.xml:

 <RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_weight="2"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="本地音乐文件"
android:id="@+id/textView"
android:textSize="25dp" /> <ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@android:id/list"
android:scrollbars="vertical"
android:divider="@android:color/holo_blue_light"
android:dividerHeight="2dp"
android:drawSelectorOnTop="false"
android:choiceMode="singleChoice"/>
</LinearLayout> <LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="3"> <tina.musicplayer.AlwaysMarqueeTextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:id="@+id/nameDisplay"
android:layout_gravity="center_horizontal"
android:textSize="28dp"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:focusable="true"
android:singleLine="true"
android:layout_margin="5dp"/> <RelativeLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:id="@+id/currTime"
android:layout_alignParentStart="true"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:id="@+id/totalTime"
android:layout_alignParentEnd="true"/>
</RelativeLayout> <SeekBar
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/seekBar"
android:layout_gravity="center_horizontal"
android:layout_margin="10dp"/> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="20dp"> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/previous"
android:layout_gravity="center_horizontal"
android:layout_marginStart="40dp"
android:src="@drawable/player_previous"
android:onClick="onPreviousClick"
android:background="@android:color/transparent"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/stop"
android:src="@drawable/player_stop"
android:layout_gravity="center_horizontal"
android:onClick="onStopClick"
android:background="@android:color/transparent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_toRightOf="@+id/previous"
android:layout_marginStart="30dp"/> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/play"
android:layout_gravity="center_horizontal"
android:src="@drawable/player_play"
android:onClick="onPlayClick"
android:background="@android:color/transparent"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/stop"
android:layout_marginStart="30dp"/> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:id="@+id/next"
android:src="@drawable/player_next"
android:onClick="onNextClick"
android:background="@android:color/transparent"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/play"
android:layout_marginStart="30dp" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

musiclist.xml:

 <?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="horizontal"
android:background="@drawable/selector"> <TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="New Text"
android:id="@+id/songName"
android:textSize="25dp"
android:textColor="@android:color/holo_purple"
android:layout_weight="2"/> <TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="New Text"
android:id="@+id/artistName"
android:textSize="25dp"
android:gravity="right"
android:textColor="@android:color/holo_purple"
/>
</LinearLayout>

预览效果:

     

在播放页面实现的过程中,主要有以下几个重要的点:

1、自动水平滚动的TextView

为了增加音乐播放器的趣味性,我放置了一个可以水平滚动的TextView,用来显示当前选中的歌曲名称,这也就是常常说的走马灯的文字效果。那么如何实现呢?

首先,新建一个TextView的子类(AlwaysMarqueeTextView),重写isFocusd()方法,使得该类对象始终获得焦点。

 package tina.musicplayer;

 import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView; /**
* Created by CW3479 on 2015/4/2.
*/
public class AlwaysMarqueeTextView extends TextView {
public AlwaysMarqueeTextView(Context context) {
super(context);
} public AlwaysMarqueeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
} public AlwaysMarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} @Override
public boolean isFocused() {
return true;
}
}

然后,在布局文件中,放置AlwaysMarqueeTextView,设置属性:

  android:ellipsize="marquee"     
  android:marqueeRepeatLimit="marquee_forever"
  android:focusable="true"
  android:singleLine="true"

以上,可以实现程序运行时,选中歌曲,歌曲名就能自动从右往左重复滚动。需要注意的是,只有当AlwaysMarqueeTextView中的文字超过其能够显示的长度时,文字才能开始滚动。所以android:layout_width="100dp"属性需要设置为合适的值。

关于跑马灯效果,还可以参考一下网络上的这篇文章。http://www.cnblogs.com/Gaojiecai/archive/2013/06/18/3142783.html

2、音乐文件列表

为了完成音乐文件列表的呈现,我用到了ListActivity,在布局文件activity_main.xml中,放置的ListView,设置属性:

    android:id="@android:id/list"    这里的id一定要设置成"@android:id/list",才能使其绑定到ListActivity
    android:scrollbars="vertical"     使list长度超过ListView的显示高度时,ListView能够垂直滚动
    android:divider="@android:color/holo_blue_light"  list中每一行之间的分割线
   android:dividerHeight="2dp"
    android:choiceMode="singleChoice" 设置选择模式为单选
    android:drawSelectorOnTop="false" 使选中某一项时,选中背景不覆盖当前文字使用

现在,我们已经有了ListView和musiclist.xml中的两个TextView,具体如何使用到程序中呢?

(1)定义全局变量

     private ListView musicListView;
private SimpleAdapter listAdapter;
private List<HashMap<String,String>> list=new ArrayList<HashMap<String,String>>();

(2)MainActivity继承ListActivity,设置ListAdapter。

 musicListView=(ListView)findViewById(android.R.id.list);
listAdapter=new SimpleAdapter(MainActivity.this,list,R.layout.musiclist,new String[]{"name","artist"}, new int[]{R.id.songName,R.id.artistName});
MainActivity.this.setListAdapter(listAdapter);

至此,完成一个音乐播放列表的基本框架。下面,再增加一点小功能。

在点击列表时,我希望能区别出选中的项,即:选中一首歌曲时,该项的背景变成另一种颜色。如何实现这种功能?

(1)在res/drawable文件夹中新建一个selector.xml文件,在里面定义TextView的不同状态下的背景。

(2)在musiclist.xml中,设置LinearLayout的属性android:background="@drawable/selector"

selector.xml:

 <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--被选中时的布局-->
<item
android:state_activated="true">
<shape>
<gradient
android:angle="270"
android:endColor="#99BD4C"
android:startColor="#C1C125"
/>
<corners
android:radius="8dp"
/>
</shape>
</item>
<!--默认的布局-->
<item>
<shape>
<gradient
android:angle="270"
android:endColor="#A8C3B0"
android:startColor="#C0CFCE"
/>
<corners
android:radius="8dp"
/>
</shape>
</item> </selector>

需要注意的是,区分列表项是否选中的属性是:"android:state_activated",当这个属性的值为true时,表明选项被选中。

  以上,基本完成了音乐播放器的页面设计。在下一篇文章Android 实现简单音乐播放器(二)中,我将介绍音乐播放器的功能实现。

Android 实现简单音乐播放器(一)的更多相关文章

  1. Android 实现简单音乐播放器(二)

    在Android 实现简单音乐播放器(一)中,我介绍了MusicPlayer的页面设计. 现在,我简单总结一些功能实现过程中的要点和有趣的细节,结合MainActivity.java代码进行说明(写出 ...

  2. Android实现简单音乐播放器(MediaPlayer)

    Android实现简单音乐播放器(MediaPlayer) 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 工程内容 实现一个简单的音乐播放器,要求功能 ...

  3. Android实现简单音乐播放器(startService和bindService后台运行程序)

    Android实现简单音乐播放器(MediaPlayer) 开发工具:Andorid Studio 1.3运行环境:Android 4.4 KitKat 工程内容 实现一个简单的音乐播放器,要求功能有 ...

  4. Android——简单音乐播放器

    使用MediaPlayer做的简单音乐播放器,更多内容请到百度经验查看   http://jingyan.baidu.com/article/60ccbceb63452364cab197f1.html ...

  5. html5 简单音乐播放器

    html5 简单音乐播放器 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> < ...

  6. iOS之基于FreeStreamer的简单音乐播放器(模仿QQ音乐)

    代码地址如下:http://www.demodashi.com/demo/11944.html 天道酬勤 前言 作为一名iOS开发者,每当使用APP的时候,总难免会情不自禁的去想想,这个怎么做的?该怎 ...

  7. Android开发6:Service的使用(简单音乐播放器的实现)

    前言 啦啦啦~各位好久不见啦~博主最近比较忙,而且最近一次实验也是刚刚结束~ 好了不废话了,直接进入我们这次的内容~ 在这篇博文里我们将学习Service(服务)的相关知识,学会使用 Service ...

  8. Android开发学习之路--MediaPlayer之简单音乐播放器初体验

    很多时候我们都会用手机来播放音乐,播放视频,那么具体地要怎么实现呢,其实主要是MediaPlayer类来完成的.下面通过简单的例子来实现一首歌曲的播放吧.新建工程MediaPlayerStudy,这里 ...

  9. Android开发实战之简单音乐播放器

    最近开始学习音频相关.所以,很想自己做一个音乐播放器,于是,花了一天学习,将播放器的基本功能实现了出来.我觉得学习知识点还是蛮多的,所以写篇博客总结一下关于一个音乐播放器实现的逻辑.希望这篇博文对你的 ...

随机推荐

  1. Debian8 从本地源安装软件

    假如你从Debian官网下载了三个DVD镜像,那么就可以设置从本地源来安装软件,例如这里我从官网下载了 debian-8.6.0-amd64-DVD-1.iso,debian-8.6.0-amd64- ...

  2. bootstrap搜索框样式代码及效果

    <div class="container"> <div class="input-group"> <input type=&qu ...

  3. 【POJ】2187 Beauty Contest(旋转卡壳)

    http://poj.org/problem?id=2187 显然直径在凸包上(黑书上有证明).(然后这题让我发现我之前好几次凸包的排序都错了QAQ只排序了x轴.....没有排序y轴.. 然后本题数据 ...

  4. Win8 安装Oracle 10g 提示“程序异常终止”的解决方案

    这段时间在做DRP,需要安装Oracle 10g的数据库,我的系统是win8企业版,安装Oracle 10g的时候,选择“高级安装”,提示“程序异常终止”,下面是几个解决方案,跟大家分享一下. 错误提 ...

  5. 你必须知道的session与cookie

    Session本质 提到Session我们能联想到的就是用户登录功能,而本身我们使用Session的基础是通过url进行访问的,也就是使用http协议进行访问的,而http协议本身是无状态的,那么问题 ...

  6. 【Java】几道让你拿offer的知识点

    前言 只有光头才能变强 之前在刷博客的时候,发现一些写得比较好的博客都会默默收藏起来.最近在查阅补漏,有的知识点比较重要的,但是在之前的博客中还没有写到,于是趁着闲整理一下. 文本的知识点: Inte ...

  7. SpringMvc的Controller singleton synchronized

    SpringMvc的controller是singleton的(非线程安全的) - lvyuanj的专栏 - CSDN博客 https://blog.csdn.net/lvyuanj/article/ ...

  8. [U3D Demo] 手机FPS射击游戏

    游戏截图 使用插件 DOTween Easy Touch UGUI 游戏介绍 游戏使用C#开发,是在<Unity3D手机游戏开发>一书第3章游戏的基础上优化和修改的. 机枪镭射光线和枪口特 ...

  9. 手工编程:hello world

    全部用命令行工具和Notepad编辑器,用手工创建并编译一个C的命令行程序:hello world. public class Hello{         public static void ma ...

  10. python生成Excel图表(通过xlsxwriter)

    前面介绍了pandas的简单用法,pandas的数据可以通过matlab第三方包将数据生成报表,但是我想将报表生成在Excel中,这时候就可以借助xlsxwriter第三方包来生成图标   缺点:xl ...