今天掐指一算,學習Android長達近兩個月了,今天開始,對過去一段時間的學習收獲以及遇到的疑難雜症做一些總結。
簡單音樂播放器是我自己完成的第一個功能較為完整的APP,可以說是我的Android學習之路上的一個小小里程碑,給我增加了很多信心(~~真容易獲得滿足~~)。從下面開始,我將詳細介紹MusicPlayer的設計過程。
首先,先看一下這個項目的工程目錄和運行效果:
從上面的圖片看到,整個工程的布局文件有兩個:activity_main.xml和musiclist.xml,其中,musiclist.xml中放置了兩個TextView,分別對應歌曲名稱和演唱者,結合activity_main.xml中的ListView,完成一張音樂文件列表。播放頁面的其他組件的布局則由activity_main.xml完成。具體如下:
activity_main.xml:

1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 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 </LinearLayout> 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 </RelativeLayout> 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 </RelativeLayout> 139 </LinearLayout> 140 </LinearLayout> 141 </RelativeLayout>
musiclist.xml:

1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 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 </LinearLayout>
預覽效果:
在播放頁面實現的過程中,主要有以下幾個重要的點:
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<HashMap<String,String>> list=new ArrayList<HashMap<String,String>>();
(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 <?xml version="1.0" encoding="utf-8"?> 2 <selector xmlns:android="http://schemas.android.com/apk/res/android"> 3 <!--被選中時的布局--> 4 <item 5 android:state_activated="true"> 6 <shape> 7 <gradient 8 android:angle="270" 9 android:endColor="#99BD4C" 10 android:startColor="#C1C125" 11 /> 12 <corners 13 android:radius="8dp" 14 /> 15 </shape> 16 </item> 17 <!--默認的布局--> 18 <item> 19 <shape> 20 <gradient 21 android:angle="270" 22 android:endColor="#A8C3B0" 23 android:startColor="#C0CFCE" 24 /> 25 <corners 26 android:radius="8dp" 27 /> 28 </shape> 29 </item> 30 31 </selector>
需要注意的是,區分列表項是否選中的屬性是:"android:state_activated",當這個屬性的值為true時,表明選項被選中。
以上,基本完成了音樂播放器的頁面設計。在下一篇文章Android 實現簡單音樂播放器(二)中,我將介紹音樂播放器的功能實現。