今天掐指一算,学习Android长达近两个月了,今天开始,对过去一段时间的学习收获以及遇到的疑难杂症做一些总结。
简单音乐播放器是我自己完成的第一个功能较为完整的APP,可以说是我的Android学习之路上的一个小小里程碑,给我增加了很多信心(~~真容易获得满足~~)。从下面开始,我将详细介绍MusicPlayer的设计过程。
首先,先看一下这个项目的工程目录和运行效果:
从上面的图片看到,整个工程的布局文件有两个:activity_main.xml和musiclist.xml,其中,musiclist.xml中放置了两个TextView,分别对应歌曲名称和演唱者,结合activity_main.xml中的ListView,完成一张音乐文件列表。播放页面的其他组件的布局则由activity_main.xml完成。具体如下:
activity_main.xml:
12 xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" 3 android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" 4 android:paddingRight="@dimen/activity_horizontal_margin" 5 android:paddingTop="@dimen/activity_vertical_margin" 6 android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> 7 <LinearLayout 8 android:orientation="vertical" 9 android:layout_width="fill_parent" 10 android:layout_height="fill_parent" 11 android:layout_alignParentBottom="true" 12 android:layout_alignParentStart="true"> 13 <LinearLayout 14 android:orientation="vertical" 15 android:layout_width="fill_parent" 16 android:layout_height="match_parent" 17 android:layout_alignParentTop="true" 18 android:layout_alignParentStart="true" 19 android:layout_weight="2"> 20 21 <TextView 22 android:layout_width="wrap_content" 23 android:layout_height="wrap_content" 24 android:text="本地音乐文件" 25 android:id="@+id/textView" 26 android:textSize="25dp" /> 27 28 <ListView 29 android:layout_width="match_parent" 30 android:layout_height="match_parent" 31 android:id="@android:id/list" 32 android:scrollbars="vertical" 33 android:divider="@android:color/holo_blue_light" 34 android:dividerHeight="2dp" 35 android:drawSelectorOnTop="false" 36 android:choiceMode="singleChoice"/> 37 38 39 <LinearLayout 40 android:orientation="vertical" 41 android:layout_width="fill_parent" 42 android:layout_height="match_parent" 43 android:layout_weight="3"> 44 45 <tina.musicplayer.AlwaysMarqueeTextView 46 android:layout_width="100dp" 47 android:layout_height="wrap_content" 48 android:id="@+id/nameDisplay" 49 android:layout_gravity="center_horizontal" 50 android:textSize="28dp" 51 android:ellipsize="marquee" 52 android:marqueeRepeatLimit="marquee_forever" 53 android:focusable="true" 54 android:singleLine="true" 55 android:layout_margin="5dp"/> 56 57 <RelativeLayout 58 android:orientation="horizontal" 59 android:layout_width="match_parent" 60 android:layout_height="wrap_content" 61 android:layout_gravity="center_horizontal"> 62 <TextView 63 android:layout_width="wrap_content" 64 android:layout_height="wrap_content" 65 android:text="00:00" 66 android:id="@+id/currTime" 67 android:layout_alignParentStart="true"/> 68 69 <TextView 70 android:layout_width="wrap_content" 71 android:layout_height="wrap_content" 72 android:text="00:00" 73 android:id="@+id/totalTime" 74 android:layout_alignParentEnd="true"/> 75 76 77 <SeekBar 78 android:layout_width="fill_parent" 79 android:layout_height="wrap_content" 80 android:id="@+id/seekBar" 81 android:layout_gravity="center_horizontal" 82 android:layout_margin="10dp"/> 83 84 <RelativeLayout 85 android:layout_width="match_parent" 86 android:layout_height="wrap_content" 87 android:layout_gravity="center_horizontal" 88 android:layout_margin="20dp"> 89 90 <ImageButton 91 android:layout_width="wrap_content" 92 android:layout_height="wrap_content" 93 android:id="@+id/previous" 94 android:layout_gravity="center_horizontal" 95 android:layout_marginStart="40dp" 96 android:src="@drawable/player_previous" 97 android:onClick="onPreviousClick" 98 android:background="@android:color/transparent" 99 android:layout_alignParentTop="true" 100 android:layout_alignParentStart="true" /> 101 102 <ImageButton 103 android:layout_width="wrap_content" 104 android:layout_height="wrap_content" 105 android:id="@+id/stop" 106 android:src="@drawable/player_stop" 107 android:layout_gravity="center_horizontal" 108 android:onClick="onStopClick" 109 android:background="@android:color/transparent" 110 android:layout_alignParentTop="true" 111 android:layout_centerHorizontal="true" 112 android:layout_toRightOf="@+id/previous" 113 android:layout_marginStart="30dp"/> 114 115 <ImageButton 116 android:layout_width="wrap_content" 117 android:layout_height="wrap_content" 118 android:id="@+id/play" 119 android:layout_gravity="center_horizontal" 120 android:src="@drawable/player_play" 121 android:onClick="onPlayClick" 122 android:background="@android:color/transparent" 123 android:layout_alignParentTop="true" 124 android:layout_toRightOf="@+id/stop" 125 android:layout_marginStart="30dp"/> 126 127 <ImageButton 128 android:layout_width="wrap_content" 129 android:layout_height="wrap_content" 130 android:layout_gravity="center_horizontal" 131 android:id="@+id/next" 132 android:src="@drawable/player_next" 133 android:onClick="onNextClick" 134 android:background="@android:color/transparent" 135 android:layout_alignParentTop="true" 136 android:layout_toRightOf="@+id/play" 137 android:layout_marginStart="30dp" /> 138 139 140 141
musiclist.xml:
1 23 android:layout_width="match_parent" android:layout_height="match_parent" 4 android:orientation="horizontal" 5 android:background="@drawable/selector"> 6 7 <TextView 8 android:layout_width="200dp" 9 android:layout_height="wrap_content" 10 android:text="New Text" 11 android:id="@+id/songName" 12 android:textSize="25dp" 13 android:textColor="@android:color/holo_purple" 14 android:layout_weight="2"/> 15 16 <TextView 17 android:layout_width="200dp" 18 android:layout_height="wrap_content" 19 android:text="New Text" 20 android:id="@+id/artistName" 21 android:textSize="25dp" 22 android:gravity="right" 23 android:textColor="@android:color/holo_purple" 24 /> 25
预览效果:
在播放页面实现的过程中,主要有以下几个重要的点:
1、自动水平滚动的TextView
为了增加音乐播放器的趣味性,我放置了一个可以水平滚动的TextView,用来显示当前选中的歌曲名称,这也就是常常说的走马灯的文字效果。那么如何实现呢?
首先,新建一个TextView的子类(AlwaysMarqueeTextView),重写isFocusd()方法,使得该类对象始终获得焦点。
1 package tina.musicplayer; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.widget.TextView; 6 7 /** 8 * Created by CW3479 on 2015/4/2. 9 */ 10 public class AlwaysMarqueeTextView extends TextView { 11 public AlwaysMarqueeTextView(Context context) { 12 super(context); 13 } 14 15 public AlwaysMarqueeTextView(Context context, AttributeSet attrs) { 16 super(context, attrs); 17 } 18 19 public AlwaysMarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) { 20 super(context, attrs, defStyleAttr); 21 } 22 23 @Override 24 public boolean isFocused() { 25 return true; 26 } 27 }
然后,在布局文件中,放置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)定义全局变量
1 private ListView musicListView; 2 private SimpleAdapter listAdapter; 3 private List> list=new ArrayList >();
(2)MainActivity继承ListActivity,设置ListAdapter。
1 musicListView=(ListView)findViewById(android.R.id.list); 2 listAdapter=new SimpleAdapter(MainActivity.this,list,R.layout.musiclist,new String[]{"name","artist"}, new int[]{R.id.songName,R.id.artistName}); 3 MainActivity.this.setListAdapter(listAdapter);
至此,完成一个音乐播放列表的基本框架。下面,再增加一点小功能。
在点击列表时,我希望能区别出选中的项,即:选中一首歌曲时,该项的背景变成另一种颜色。如何实现这种功能?
(1)在res/drawable文件夹中新建一个selector.xml文件,在里面定义TextView的不同状态下的背景。
(2)在musiclist.xml中,设置LinearLayout的属性android:background="@drawable/selector"
selector.xml:
1 23 4 <item 5 android:state_activated="true"> 6 7 <gradient 8 android:angle="270" 9 android:endColor="#99BD4C" 10 android:startColor="#C1C125" 11 /> 12 <corners 13 android:radius="8dp" 14 /> 15 16 17 18- 19
30 3120 <gradient 21 android:angle="270" 22 android:endColor="#A8C3B0" 23 android:startColor="#C0CFCE" 24 /> 25 <corners 26 android:radius="8dp" 27 /> 28 29
需要注意的是,区分列表项是否选中的属性是:"android:state_activated",当这个属性的值为true时,表明选项被选中。
以上,基本完成了音乐播放器的页面设计。在下一篇文章Android 实现简单音乐播放器(二)中,我将介绍音乐播放器的功能实现。