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; //音乐艺术家
}
}
通过 LayoutInflater获取布局mysong_layout.xml,对于每个ListView, 我们使用了下面的mysong_layout.xml进行定义
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>
activity 动态转载 fragment
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的基本框架,敬请期待~