? ? ? ?學習Android有一個多月,看完了《第一行代碼》以及mars老師的第一期視頻通過音樂播放器小項目加深對知識點的理解。從本文開始,將詳細的介紹簡單仿多米音樂播放器的實現(xiàn),以及網(wǎng)絡解析數(shù)據(jù)獲取百度音樂最新排行音樂以及下載功能。
? ? ? ??功能介紹如下:?? ?
? ? ? ??1、獲取本地歌曲列表,實現(xiàn)歌曲播放功能。?
? ? ? ? 2、利用jsoup解析網(wǎng)頁數(shù)據(jù),從網(wǎng)絡獲取歌曲列表,同時實現(xiàn)歌曲和歌詞下載到手機本地的功能。?
? ? ? ? 3、通知欄提醒,實現(xiàn)仿QQ音樂播放器的通知欄功能.?? ? ?
? ? ???涉及的技術(shù)有:?
? ? ? ?1、jsoup解析網(wǎng)絡網(wǎng)頁,從而獲取需要的數(shù)據(jù)?
? ? ? ?2、android中訪問網(wǎng)絡,獲取文件到本地的網(wǎng)絡請求技術(shù),以及下載文件到本地實現(xiàn)斷點下載?
? ? ? ?3、線程池?
? ? ? ?4、圖片緩存?
? ? ? ?5、service一直在后臺運行?
? ? ? ?6、Activity與Fragment間的切換以及通信?
? ? ? ?7、notification通知欄設計?
? ? ? ?8、自定義廣播?
? ? ? ?9、android系統(tǒng)文件管
? ? ?音樂播放器思路及源碼下載見:【android】音樂播放器之設計思路
? ? ? ?Ui界面的最終顯示效果如下:
? ??
? ? ? ?馬上來看看UI界面是如何實現(xiàn)的,不過先得做些準備工作~~啟動界面的設計。細心的朋友肯定注意到目前一些主流app登陸時候都有封面展示的效果,啟動界面的制作就是為了實現(xiàn)這個效果:加載一個布局全屏展示一張封面,并2s跳轉(zhuǎn)到主布局MainActivity.
public class SplashActivity extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// no titlerequestWindowFeature(Window.FEATURE_NO_TITLE);// 全屏getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(R.layout.splash_layout);// 2s跳轉(zhuǎn)到主界面new Handler().postDelayed(new Runnable() {@Overridepublic void run() {startActivity(new Intent(SplashActivity.this, MainActivity.class));finish();}}, 2000);}
}
? ? ? ?有了上面的準備工作,可以設計主界面以及主界面中的5個Fragment(不是4個嘛!!!!~!~我這邊直接將本地音樂列表這個Fragment直接放到MainActivity中)。目前,主流的app主界面實現(xiàn)由四種方式:
? ? ? ??(1)ViewPager實現(xiàn)
? ? ? ? (2)Fragment實現(xiàn)
? ? ? ? (3)FragmentPagerAdapter+ViewPager實現(xiàn)
? ? ? ? (4)ViewPagerIndicator+ViewPager實現(xiàn)
? ? ? 就挑個最熟練的實現(xiàn)方式:Fragment實現(xiàn)。(哈哈,目前水平比較低。。。ViewPager后文有使用分析,其余還是想每一種都有機會去嘗試用到代碼中去。) 小編這邊的都是使用動態(tài)Fragment
[html]?view plaincopy
<LinearLayout?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:orientation="vertical"?>?? ????<include?layout="@layout/top"?/>?? ?????? ????<FrameLayout??? ????????android:id="@+id/id_content"?? ????????android:layout_width="fill_parent"?? ????????android:layout_height="0dp"?? ????????android:layout_weight="1">?? ????????? ????</FrameLayout>?? ?? ????<include?layout="@layout/bottom"?/>?? ?? </LinearLayout>??
? ? ? ??
頂部和底部的布局就補貼出來了,到時直接看源碼就明白了。在MainActivity中通過監(jiān)聽底部的按鈕獲取FragmentManager方式開啟一個事務添加一個Fragment或者去隱藏一個Fragment。當然這邊也可以直接調(diào)用事務的raplace方法替代原布局中的Fragment
(~·~
后文將介紹相關(guān)的Api以及總結(jié)Fragment和Activity的通信
),主要代碼段如下:
[html]?view plaincopy
public?void?setSelect(int?i)?? ????{?? ????????FragmentManager?fm?=?getSupportFragmentManager();?? ????????FragmentTransaction?transaction?=?fm.beginTransaction();?? ????????hideFragment(transaction);?? ????????//?把圖片設置為亮的?? ????????//?設置內(nèi)容區(qū)域?? ????????switch?(i)?? ????????{?? ????????case?TAB_USER:?? ????????????if?(mTab01?==?null)?? ????????????{?? ????????????????mTab01?=?new?UserFragment();?? ????????????????transaction.add(R.id.id_content,?mTab01);?? ????????????}?else?? ????????????{?? ????????????????transaction.show(mTab01);?? ????????????}?? ????????????mImguser.setImageResource(R.drawable.icon_user_selected);?? ????????????mTitle.setText("我的音樂");?? ?????????????? ????????????break;?? ????????case?TAB_CD:?? ????????????if?(mTab02?==?null)?? ????????????{?? ????????????????mTab02?=?new?CdFragment();?? ????????????????transaction.add(R.id.id_content,?mTab02);?? ????????????}?else?? ????????????{?? ????????????????transaction.show(mTab02);?? ?????????????????? ????????????}?? ????????????mImgcd.setImageResource(R.drawable.icon_cd_selected);?? ????????????mTitle.setText("音樂架");?? ????????????break;?? ????????case?TAB_SEARCH:?? ????????????if?(mTab03?==?null)?? ????????????{?? ????????????????mTab03?=?new?SearchFragment();?? ????????????????transaction.add(R.id.id_content,?mTab03);?? ????????????}?else?? ????????????{?? ????????????????transaction.show(mTab03);?? ????????????}?? ????????????mImgsearch.setImageResource(R.drawable.icon_search_selected);?? ????????????mTitle.setText("搜索");?? ????????????break;?? ????????case?TAB_COMPASS:?? ????????????if?(mTab04?==?null)?? ????????????{?? ????????????????mTab04?=?new?CompassFragment();?? ????????????????transaction.add(R.id.id_content,?mTab04);?? ????????????}?else?? ????????????{?? ????????????????transaction.show(mTab04);?? ????????????}?? ????????????mImgcompass.setImageResource(R.drawable.icon_compass_selected);?? ????????????mTitle.setText("發(fā)現(xiàn)");?? ????????????break;?? ????????case?TAB_SONGLIST:?? ????????????if?(mTab05?==?null)?? ????????????{?? ????????????????mTab05?=?new?LocalFragment();?? ????????????????transaction.add(R.id.id_content,?mTab05);?? ????????????}?else?? ????????????{?? ????????????????transaction.show(mTab05);?? ????????????}?? ????????????resetImgs();?? ????????????setVisibility(TOP_MENU);?? ????????????mTitle.setText("本地音樂");?? ????????????break;?? ?????????????? ????????default:?? ????????????break;?? ????????}?? ?? ????????transaction.commit();?? ????}??
? ? ? ?
[html]?view plaincopy
private?void?hideFragment(FragmentTransaction?transaction)?? ????{?? ????????setVisibility(TOP_JUMP);?? ????????if?(mTab01?!=?null)?? ????????{?? ????????????transaction.hide(mTab01);?? ????????}?? ????????if?(mTab02?!=?null)?? ????????{?? ????????????transaction.hide(mTab02);?? ????????}?? ????????if?(mTab03?!=?null)?? ????????{?? ????????????transaction.hide(mTab03);?? ????????}?? ????????if?(mTab04?!=?null)?? ????????{?? ????????????transaction.hide(mTab04);?? ????????}?? ????????if?(mTab05?!=?null)?? ????????{?? ????????????transaction.hide(mTab05);?? ?????????????? ????????}?? ????}??
? ? ? ??
? ? ? ? ?每個Fragment中的控件也都是最最常用的控件,這邊就不一一介紹。。。其余除Ui之外更詳細的分析可以看看小編其他相關(guān)的博客。其中,應該注意的是:在本地音樂這個Fragment中通過短點擊ListView歌曲Items跳轉(zhuǎn)啟動PlayAcyivity加載播放界面。也終于到了講ViewPager這塊了!!!~!~
? ? ???ViewPager添加一個VIew或者刪除一個View是通過我們自定義的PagerAdapter控制的,于是我們可以在View中維系一個ArrayList<view>。然后滑動的時候通過get(position)取出對應的view:
? ? ? ?ViewPager添加一個VIew或者刪除一個View是通過我們自定義的PagerAdapter控制的,于是我們可以在View中維系一個ArrayList<view>。然后滑動的時候通過get(position)取出對應的view:
[html]?view plaincopy
/**?? ?????*?初始化viewpager的內(nèi)容?? ?????*/?? ????private?void?initViewPagerContent()?{?? ????????View?cd?=?View.inflate(this,?R.layout.play_pager_item_1,?null);?? ????????mCdView?=?(CDView)?cd.findViewById(R.id.play_cdview);?? ????????mTextArtistTitle?=?(TextView)?cd.findViewById(R.id.play_singer);?? ????????mLrcViewOnFirstPage?=?(LrcView)?cd.findViewById(R.id.play_first_lrc);?? ?????????? ????????View?lrcView?=?View.inflate(this,?R.layout.play_pager_item_2,?null);?? ????????mLrcViewOnSecondPage?=?(LrcView)?lrcView.findViewById(R.id.play_first_lrc_2);?? ?????????? ????????mViewPagerContent.add(cd);?? ????????mViewPagerContent.add(lrcView);?? ????}??
[html]?view plaincopy
private?PagerAdapter?mPagerAdapter?=?new?PagerAdapter()?{?? ????????@Override?? ????????public?int?getCount()?{?? ????????????return?mViewPagerContent.size();?? ????????}?? ?? ????????@Override?? ????????public?boolean?isViewFromObject(View?view,?Object?obj)?{?? ????????????return?view?==?obj;?? ????????}?? ?????????? ????????@Override?? ????????public?Object?instantiateItem(ViewGroup?container,?int?position)?{?? ????????????container.addView(mViewPagerContent.get(position));?? ????????????return?mViewPagerContent.get(position);?? ????????}?? ?????????? ????????@Override?? ????????public?void?destroyItem(ViewGroup?container,?int?position,?Object?object)?{?? ????????????((ViewPager)?container).removeView((View)?object);?? ????????}?? ????};??
? ? ? ? ?內(nèi)容太多了,只能講主要的Ui布局實現(xiàn)。其他細節(jié)可以參考我其他博文或者源代碼。
? ? ??? ?下面我想共享下下面的一些關(guān)于Fragment的小總結(jié)!
? ? ? ? Fragment家族常用的API
? ? ? ? ??Fragment常用的三個類:(1)android.app.Fragment 主要用于定義Fragment;(2)android.app.FragmentManager 主要用于在Activity中操作Fragment;(3)android.app.FragmentTransaction 保證一些列Fragment操作的原子性,熟悉事務這個詞,一定能明白~
? ? ? ? ?a、獲取FragmentManage的方式:getFragmentManager() // v4中,getSupportFragmentManager
? ? ? ? ?b、主要的操作都是FragmentTransaction的方法:1)FragmentTransaction transaction = fm.benginTransatcion();//開啟一個事務;2)transaction.add()?往Activity中添加一個Fragment;3)transaction.remove()從Activity中移除一個Fragment,如果被移除的Fragment沒有添加到回退棧(回退棧后面會詳細說),這個Fragment實例將會被銷毀;4)transaction.replace():使用另一個Fragment替換當前的,實際上就是remove()然后add()的合體~;5)transaction.hide():隱藏當前的Fragment,僅僅是設為不可見,并不會銷毀;6)transaction.show():顯示之前隱藏的Fragment
7)detach()會將view從UI中移除,和remove()不同,此時fragment的狀態(tài)依然由FragmentManager維護;8)attach()重建view視圖,附加到UI上并顯示。
transatcion.commit()//提交一個事務
? ? ? ? 注意:常用Fragment的哥們,可能會經(jīng)常遇到這樣Activity狀態(tài)不一致:State loss這樣的錯誤。主要是因為:commit方法一定要在Activity.onSaveInstance()之前調(diào)用。
? ? ? ? ?上述,基本是操作Fragment的所有的方式了,在一個事務開啟到提交可以進行多個的添加、移除、替換等操作。值得注意的是:如果你喜歡使用Fragment,一定要清楚這些方法,哪個會銷毀視圖,哪個會銷毀實例,哪個僅僅只是隱藏,這樣才能更好的使用它們。
總結(jié)
以上是生活随笔為你收集整理的【android】音乐播放器之UI设计的点点滴滴的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。