Android歌詞秀設計思路(7)水到渠成
我們用了6篇文章的篇幅做了鋪墊,終於到了真正的應用程式了。這部分還是一如既往的簡單。
有關應用的類有兩個,一個是LiryicMain,一個是SelectFileActivity。都是差不多最低限度的內容,沒有任何華麗的內容。
先看看這兩個類在整個軟體中的位置。從圖中可以看出LyricMain是軟體全體的控制者。SelectFileActivity也為LyricMain提供服務。
SelectFileActivity太過簡單,本文中就不再說明了。我們集中篇幅說明一下LyricMain。
首先是資料成員。一個是LyricPlayerServiceProxy,歌詞播放服務的代理,一個是用來儲存歌詞結束位置的List。
- privateLyricPlayerServiceProxymProxy=newLyricPlayerServiceProxy(this);
- private ArrayList<Integer>mLyricEndList=newArrayList<Integer>();
LyricPlayerServiceProxy是前面已經介紹過的內容,在這裡就不在重複了。mLyricEndList需要說明一下。在這個軟體中我們將所有歌詞都表示在一個TextEditView中,為了能夠表示當前播放中的歌詞,我們將每一句歌詞的位置儲存在mLyricEndList中,這樣當播放中的歌詞發生變化時,只要將這句歌詞設為選中狀態就可以了。
接下來是LyricMediaInfoProvider的最簡單實現,提供了固定的歌名和歌曲檔案的位置資訊。如果需要切換歌曲,需要再複雜一些。
- privateclassLyricMediaInfoProviderimplementsMediaPlayerService.MediaInfoProvider{
- StringmUrl;
- StringmTitle;
- LyricMediaInfoProvider(Stringurl,Stringtitle){
- mUrl=url;
- mTitle=title;
- }
- @Override
- publicbooleanmoveToPrev(){
- //TODOAuto-generatedmethodstub
- returnfalse;
- }
- @Override
- publicbooleanmoveToNext(){
- //TODOAuto-generatedmethodstub
- returnfalse;
- }
- @Override
- publicStringgetUrl(){
- returnmUrl;
- }
- @Override
- publicStringgetTitle(){
- //TODOAuto-generatedmethodstub
- returnmTitle;
- }
- }
接下來是onCreate方法。主要做了幾件事
1.建立和LyricPlayerServiceProxy之間的聯絡。
2.提供了的實現NotificationProvider(詳細資訊請參照:Android歌詞秀設計思路(4)通用的音樂播放服務(下) )
3.設定ImageButton的尺寸。
- /**Calledwhentheactivityisfirstcreated.*/
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- mLyricEdit=(EditText)this.findViewById(R.id.editLyric);
- mProxy.setConnectionListener(this);
- mProxy.setLyricPlayerListener(this);
- mProxy.setNotificationProvider(newMediaPlayerService.NotificationProvider(){
- @Override
- publicNotificationcreateNotification(Contextcontext){
- Notificationnotification=newNotification(R.drawable.button_blue_play,mProxy.getTitle(),System.currentTimeMillis());
- //ThePendingIntenttolaunchouractivityiftheuserselectsthisnotification
- PendingIntentcontentIntent=PendingIntent.getActivity(context,0,newIntent(context,LyricMain.class),0);
- //Settheinfofortheviewsthatshowinthenotificationpanel.
- notification.setLatestEventInfo(context,getText(R.string.media_player_label),mProxy.getTitle(),contentIntent);
- returnnotification;
- }
- });
- mProxy.startAndBindService();
- mLyricEndList.clear();
- DisplayMetricsmetrics=newDisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(metrics);
- intbtnId[]={R.id.buttonPrev,R.id.buttonStop,R.id.buttonPlay,R.id.buttonPause,R.id.buttonNext};
- intbtnSize=Math.min(metrics.widthPixels,metrics.heightPixels)/(btnId.length+1);
- //調整按鍵尺寸。
- for(inti=0;i<btnId.length;++i){
- ImageButtonib=(ImageButton)this.findViewById(btnId[i]);
- ib.setAdjustViewBounds(true);
- ib.setMaxHeight(btnSize);
- ib.setMaxWidth(btnSize);
- }
- ImageButtonselectFile=(ImageButton)this.findViewById(R.id.buttonSelectFile);
- selectFile.setAdjustViewBounds(true);
- selectFile.setMaxHeight(btnSize*2/3);
- selectFile.setMaxWidth(btnSize*2/3);
- updateButtonState();
- }
再下來是onDestroy方法,如果音樂在播放中,就接觸和播放服務之間的關係,退出程式,這是歌曲播放會繼續。如果播放出於停止或暫停狀態,就連同播放服務一起關閉,完全退出程式。
- @Override
- protectedvoidonDestroy(){
- super.onDestroy();
- mProxy.setConnectionListener(null);
- mProxy.setLyricPlayerListener(null);
- if(!mProxy.isPlaying()){
- mProxy.stopService();
- }
- }
啟動選擇檔案的SelectFileActivity
- publicvoidOnSelectFile(Viewv){
- Intenti=newIntent(this,SelectFileActivity.class);
- startActivityForResult(i,0);
- }
SelectFileActivity關閉,取得選中的媒體檔案的資訊並通知的LyricPlayerServiceProxy
接下來是按鍵處理
- publicvoidOnOperationButtonClick(Viewv){
- switch(v.getId()){
- caseR.id.buttonPrev:
- mProxy.seekToPrevLyric();
- break;
- caseR.id.buttonStop:
- if(mProxy.isPlaying()||mProxy.isPausing()){
- mProxy.stop();
- }
- break;
- caseR.id.buttonPlay:
- if(!mProxy.isPlaying()){
- mProxy.start();
- }
- break;
- caseR.id.buttonPause:
- if(mProxy.isPlaying()){
- mProxy.pause();
- }
- break;
- caseR.id.buttonNext:
- mProxy.seekToNextLyric();
- break;
- }
- }
根據播放狀態更新各個按鍵的狀態。
- protectedvoidupdateButtonState(){
- ((ImageButton)this.findViewById(R.id.buttonPrev)).setEnabled(mProxy.isPlaying()||mProxy.isPausing());
- ((ImageButton)this.findViewById(R.id.buttonStop)).setEnabled(mProxy.isPlaying()||mProxy.isPausing());
- ((ImageButton)this.findViewById(R.id.buttonPlay)).setEnabled(mProxy.getDataSource()!=null&&(!mProxy.isPlaying()||mProxy.isPausing()));
- ((ImageButton)this.findViewById(R.id.buttonPause)).setEnabled(mProxy.isPlaying());
- ((ImageButton)this.findViewById(R.id.buttonNext)).setEnabled(mProxy.isPlaying()||mProxy.isPausing());
- }
如果是程式啟動時已經有歌曲在播放,就更新一下檔案標題和按鈕狀態。
- //implementofLyricPlayerServiceProxy.ServiceConnectionListener
- publicvoidonServiceConnected(){
- Stringtitle=mProxy.getTitle();
- if(title!=null){
- TextViewtv=(TextView)this.findViewById(R.id.fileTitle);
- tv.setText(title);
- }
- updateButtonState();
- }
- publicvoidonServiceDisconnected(){
- }
實現LyricPlayerListener的程式碼,負責處理歌詞播放服務的各種通知。
- //implementofLyricPlayerService.LyricPlayerListener
- publicvoidonLyricLoaded(){
- mLyricEndList.clear();
- Stringlyric=newString();
- for(inti=0;i<mProxy.getLyricCount();++i){
- lyric+=mProxy.getLyric(i);
- lyric+="\r\n";
- mLyricEndList.add(newInteger(lyric.length()));
- }
- mLyricEdit.setText(lyric);
- }
- publicvoidonStateChanged(){
- updateButtonState();
- }
- publicvoidonPositionChanged(longposition){
- }
- publicvoidonLyricChanged(intlyric_index){
- intlyricStart=0;
- if(lyric_index>0){
- lyricStart=mLyricEndList.get(lyric_index-1);
- }
- intlyricEnd=mLyricEndList.get(lyric_index);
- mLyricEdit.setSelection(lyricStart,lyricEnd);
- mLyricEdit.invalidate();
- Log.i(TAG,String.format("lyric=%d,setSelection(%d,%d)",lyric_index,lyricStart,lyricEnd));
- }
在歌詞讀入時,將所有歌詞練成一個長字串,並記住每一句歌詞在字串中的位置。
在播放服務的狀態發生變化時,更新按鈕的狀態。
在當前歌詞發生變化時,根據前面儲存的位置資訊將當前歌詞設定成高亮。
最後是跳到選定歌詞的程式碼,還是一樣的簡單。
- publicvoidOnLyricClick(Viewv){
- EditTextet=(EditText)v;
- intsel_start=et.getSelectionStart();
- for(inti=0;i<mLyricEndList.size();++i){
- if(sel_start<mLyricEndList.get(i))
- {
- mProxy.seekToLyric(i);
- break;
- }
- }
- }
結合選中的位置,和儲存的歌詞位置資訊,找到歌詞的序號,讓播放服務跳到那句就行了。
轉載於:https://blog.51cto.com/craftsman1970/667904