Fragment是 android3.0之后出现的概念, 目前广泛使用与各种App中,比如大家非常熟悉的微信,QQ等的切换,我使用了Fragment实现 我的 / 歌手 / 专辑 列表切换,下面是利用Fragment搭建UI的过程
MySongFragment.java
package com.saberhao.fragment; import java.util.List; import android.app.Activity; import android.app.ListFragment; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import android.annotation.SuppressLint; import com.saberhao.Adapter.MusicListAdapter; import com.saberhao.support.MusicInfo; import com.saberhao.mediaplayer.R; import com.saberhao.musichandle.CursorHandle; @SuppressLint("NewApi") public class MySongFragment extends ListFragment{ private static String TAG = "MySongFragment"; MusicListAdapter listAdapter; private List<MusicInfo> musicInfolist = null; OnArticleSelectedListener mListener; public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); musicInfolist = CursorHandle.getMusicInfos(getActivity()); listAdapter = new MusicListAdapter(getActivity(),musicInfolist); setListAdapter(listAdapter); } public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View mysonglayout = inflater.inflate(R.layout.mysong_listview, container, false); return mysonglayout; } @Override public void onListItemClick(ListView l, View v, int position, long id) { System.out.println("Click On List Item!!!"); Log.e(TAG, "Click the music list!!!!!"); super.onListItemClick(l, v, position, id); } }
关键有两点,一是需要在 onCreateView中,在通过inflate 获取view ,进行listview的装载, 对应的mysong_listview.xml 如下
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@+id/android:list" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </RelativeLayout>
二是,通过MusicListAdapt将数据和视图联系起来
listAdapter = new MusicListAdapter(getActivity(),musicInfolist);
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if(convertView == null) { viewHolder = new ViewHolder(); convertView = LayoutInflater.from(context).inflate(R.layout.mysong_layout, null); viewHolder.musicTitle = (TextView) convertView.findViewById(R.id.music_title_show); viewHolder.musicArtist = (TextView) convertView.findViewById(R.id.music_singer_show); viewHolder.musicDuration = (TextView) convertView.findViewById(R.id.music_time_show); convertView.setTag(viewHolder); //表示给View添加一个格外的数据, } else { viewHolder = (ViewHolder)convertView.getTag();//通过getTag的方法将数据取出来 } mp3Info = mp3Infos.get(position); viewHolder.musicTitle.setText(mp3Info.getTitle()); //显示标题 viewHolder.musicArtist.setText(mp3Info.getArtist()); //显示艺术家 viewHolder.musicDuration.setText(CursorHandle.formatTime(mp3Info.getDuration()));//显示时长 return convertView; } public class ViewHolder { //所有控件对象引用 //public ImageView albumImage; //专辑图片 public TextView musicTitle; //音乐标题 public TextView musicDuration; //音乐时长 public TextView musicArtist; //音乐艺术家 } }
mysong_layout.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="70dp" android:background="#3f000000"> <RelativeLayout android:id="@+id/music_about_layout" android:layout_width="250dp" android:layout_height="55dp" android:layout_alignParentBottom="true" > <TextView android:id="@+id/music_title_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_marginLeft="7.0dp" android:layout_marginTop="7.0dp" android:textSize="15sp" android:singleLine="true" android:text="@string/song" android:textColor="@android:color/white" /> <TextView android:id="@+id/music_singer_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@id/music_title_show" android:layout_marginBottom="1.0dp" android:layout_marginLeft="7.0dp" android:textSize="13sp" android:text="@string/singer" android:textColor="@android:color/white" /> </RelativeLayout> <TextView android:id="@+id/music_time_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5.0dp" android:layout_marginRight="12.0dp" android:layout_marginTop="5.0dp" android:layout_alignTop="@id/music_about_layout" android:layout_toRightOf="@id/music_about_layout" android:layout_alignParentRight="true" android:gravity="right" android:textSize="13sp" android:ellipsize="marquee" android:marqueeRepeatLimit="marquee_forever" android:singleLine="true" android:text="@string/time" android:textColor="@android:color/white" /> </RelativeLayout>
接下来 要做的就是在 主界面中装载对应的 fragment, 对应的主界面布局文件如下
activity_main.xml
<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" android:background="@drawable/wood_bg2" tools:context=".MainActivity" > <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:background="#3f000000" > <Button android:id="@+id/mysong_btn" style ="?android:attr/buttonBarButtonStyle" android:layout_width="0dp" android:layout_height="match_parent" android:gravity="center" android:layout_weight="1" android:text="@string/mysong" android:textColor="#ceefff" /> <Button android:id="@+id/singer_btn" style ="?android:attr/buttonBarButtonStyle" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="@string/singer" android:textColor="#ceefff" /> <Button android:id="@+id/album_btn" style ="?android:attr/buttonBarButtonStyle" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="@string/album" android:textColor="#ceefff" /> </LinearLayout> <FrameLayout android:id="@+id/musiclist" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </FrameLayout> <RelativeLayout android:layout_width="fill_parent" android:layout_height="52dp" android:background="#5f000000"> <ImageView android:id="@+id/default_pic_bar" android:layout_width="0dp" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentBottom="true" android:background="#0000" android:src="@drawable/defaul_pic_2" /> <RelativeLayout android:id="@+id/music_about_layout" android:layout_width="180dp" android:layout_height="match_parent" android:layout_alignParentBottom="true" android:layout_alignTop="@id/default_pic_bar" android:layout_toRightOf="@id/default_pic_bar" > <TextView android:id="@+id/music_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_marginLeft="7.0dp" android:layout_marginTop="5.0dp" android:textSize="17sp" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:marqueeRepeatLimit="marquee_forever" android:singleLine="true" android:text="@string/song" android:textColor="@android:color/white" /> <TextView android:id="@+id/music_singer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@id/music_title" android:layout_marginBottom="4.0dp" android:layout_marginLeft="7.0dp" android:textSize="12sp" android:text="@string/singer" android:textColor="@android:color/white" /> </RelativeLayout> <ImageButton android:id="@+id/play_bar" android:layout_width="50dp" android:layout_height="fill_parent" android:layout_marginRight="5dp" android:background="#0000" android:layout_toRightOf="@id/music_about_layout" android:layout_alignTop="@id/music_about_layout" android:src="@drawable/play" /> <ImageButton android:id="@+id/next_bar" android:layout_width="50dp" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:background="#0000" android:layout_marginRight="5dp" android:layout_alignTop="@id/play_bar" android:layout_toRightOf="@id/play_bar" android:src="@drawable/next" /> </RelativeLayout> </LinearLayout>
MainActivity.java
package com.saberhao.mediaplayer; import java.util.List; import com.saberhao.fragment.MyLoveFragment; import com.saberhao.fragment.MySongFragment; import com.saberhao.fragment.ArtistFragment; import com.saberhao.fragment.AlbumFragment; import com.saberhao.musichandle.CursorHandle; public class MainActivity extends Activity implements MySongFragment.OnArticleSelectedListener{ private static String TAG = "MainActivity"; private static int INVALID = -1; private MySongFragment mysongFragment; private MyLoveFragment myloveFragment; private ArtistFragment singerFragment; private AlbumFragment albumFragment; private FragmentManager fragmentManager; private Button mysongBtn; //private Button myloveBtn; private Button singerBtn; private Button albumBtn; private ImageButton playBtn; private ImageButton nextBtn; private View musicAboutLayout; private TextView musicSinger; private TextView musicTitle; private String url; // 歌曲路径 private String titleName; private int type = Common.PlayerType.TYPE_ALL; private int type0; private List<MusicInfo> MusicInfos = null; private boolean isPlaying = false; // 正在播放 private int listposition = 0; private MainBroadcastReceiver MainBroadcastReceiver; public static final String ACTION_UPDATE_INFO = "android.intent.action.ACTION_UPDATE_INFO"; @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); MusicInfos = CursorHandle.getMusicInfos(MainActivity.this); //注册广播接收器 registerReceiver(); //初始化布局 initView(); //获取FragmentManager 以便对Fragment进行管理 fragmentManager = getFragmentManager(); setTabSeletion(0); //发送intent更新音乐播放进度 } /** * 将所有的Fragment都置为隐藏状态。 * * @param transaction * 用于对Fragment执行操作的事务 , * Fragment只是被隐藏起来,这样可以节省不断new fragment的内存消耗 */ private void hideFragments(FragmentTransaction transaction) { // TODO Auto-generated method stub if(null != mysongFragment) transaction.hide(mysongFragment); if(null != myloveFragment) transaction.hide(myloveFragment); if(null != singerFragment) transaction.hide(singerFragment); if(null != albumFragment) transaction.hide(albumFragment); } /** * 清除掉所有的选中状态。 */ private void initView() { // TODO Auto-generated method stub mysongBtn = (Button)findViewById(R.id.mysong_btn); //myloveBtn = (Button)findViewById(R.id.mylove_btn); singerBtn = (Button)findViewById(R.id.singer_btn); albumBtn = (Button)findViewById(R.id.album_btn); playBtn = (ImageButton)findViewById(R.id.play_bar); nextBtn = (ImageButton)findViewById(R.id.next_bar); musicAboutLayout = findViewById(R.id.music_about_layout); musicSinger = (TextView)findViewById(R.id.music_singer); musicTitle = (TextView)findViewById(R.id.music_title); //设置播放bar显示 MusicInfo musicInfo = MusicInfos.get(listposition); musicTitle.setText(musicInfo.getTitle()); // 显示歌曲标题 musicSinger.setText(musicInfo.getArtist()); //显示歌手名字 //设置监听 ViewOnClickListener viewOnClickListener = new ViewOnClickListener(); mysongBtn.setOnClickListener(viewOnClickListener); //myloveBtn.setOnClickListener(viewOnClickListener); singerBtn.setOnClickListener(viewOnClickListener); albumBtn.setOnClickListener(viewOnClickListener); PlayBarOnClickListener playBarOnClickListener = new PlayBarOnClickListener(); playBtn.setOnClickListener(playBarOnClickListener); nextBtn.setOnClickListener(playBarOnClickListener); musicAboutLayout.setOnClickListener(playBarOnClickListener); } private void clearSelection() { // TODO Auto-generated method stub //淡化字体颜色 选中时设置为 颜色加深 #ceefff mysongBtn.setTextColor(Color.parseColor("#a6bff2")); //myloveBtn.setTextColor(Color.parseColor("#a6bff2")); singerBtn.setTextColor(Color.parseColor("#a6bff2")); albumBtn.setTextColor(Color.parseColor("#a6bff2")); //提高透明度 前两位为透明度 00代表全透明, ff代表不透明 选中时用 #3f000000 mysongBtn.setBackgroundColor(Color.parseColor("#3f000000")); //myloveBtn.setBackgroundColor(Color.parseColor("#3f000000")); singerBtn.setBackgroundColor(Color.parseColor("#3f000000")); albumBtn.setBackgroundColor(Color.parseColor("#3f000000")); } /** * 根据传入的index参数来设置选中的tab页。 * * @param index * 每个tab页对应的下标。0表示 "我的",1表示"最爱",2表示"歌手",3表示"专辑"。 */ private void setTabSeletion(int index) { // TODO Auto-generated method stub // 1. 清除当前状态 clearSelection(); // 2. 开启Fragment事务 FragmentTransaction transaction = fragmentManager.beginTransaction(); // 3. 隐藏所有Fragment,以防止多个fragment显示 hideFragments(transaction); switch(index){ case 0: // 点击"我的"按钮, UI变化 mysongBtn.setTextColor(Color.parseColor("#ceefff")); mysongBtn.setBackgroundColor(Color.parseColor("#5f000000")); if(null == mysongFragment){ mysongFragment = new MySongFragment(); transaction.add(R.id.musiclist, mysongFragment); }else { transaction.show(mysongFragment); } break; case 2: // 点击"歌手"按钮, UI变化 singerBtn.setTextColor(Color.parseColor("#ceefff")); singerBtn.setBackgroundColor(Color.parseColor("#5f000000")); if(null == singerFragment){ singerFragment = new ArtistFragment(); transaction.add(R.id.musiclist, singerFragment); }else { transaction.show(singerFragment); } break; case 3: // 点击"专辑"按钮, UI变化 albumBtn.setTextColor(Color.parseColor("#ceefff")); albumBtn.setBackgroundColor(Color.parseColor("#5f000000")); if(null == albumFragment){ albumFragment = new AlbumFragment(); transaction.add(R.id.musiclist, albumFragment); }else { transaction.show(albumFragment); } break; default: break; } //事务提交 transaction.commit(); } //监听tab点击动作,选择对应的fragment动态加载 private class ViewOnClickListener implements OnClickListener { @Override public void onClick(View arg0) { // TODO Auto-generated method stub switch(arg0.getId()) { case R.id.mysong_btn: setTabSeletion(0); break; case R.id.singer_btn: setTabSeletion(2); break; case R.id.album_btn: setTabSeletion(3); break; default: break; } } } }
过程中遇到了个问题 和大家分享下, 就是旋转屏幕之后,会有重影, 度娘了下, 大概有3中解决办法
1. 讲背景颜色设置为不透明
android:background="#ffffffff"这个方法虽好,但是没有根本上解决问题,这是让上图层完全遮住了下面图层,同时存在两个图层,只是下面的图层被挡住了,没有采用
2. 使用 transaction.replace 代替 transaction.add
transaction.replace(R.id.musiclist, mysongFragment);这种方法就是将原有图层销毁,然后在新建一个图层,可以解决问题,但是,fragment的优势就是可以隐藏而不重绘,可以节省系统资源,显然这个方法和fragment的原意有点不搭,所以我还是坚持使用add 方法
3. 旋转屏幕为什么会出现重影? 其实旋转屏幕会重现调用onCreat方法进行重绘,由于原来fragment没有销毁,所以产生了重影的现象,解决的办法,旋转不onCreate!
在Androidmanifest.xml 的 MainActivity声明中添加
android:configChanges="orientation|screenSize"即可解决
重要的事情,源码请猛戳 这里 下载
下篇文章 Android音乐播放器 -- 实现框架 将介绍MediaPlayer的基本框架,敬请期待~