Android仿天天动听音乐播放器(三)

播放器程序的主要流程图在这里:

先介绍下MainContentActivity,后面所有的Activity和Fragment都是基于这个类之上,看下代码:

package com.ldw.music.activity;

import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.ldw.music.MusicApp;
import com.ldw.music.R;
import com.ldw.music.db.MusicInfoDao;
import com.ldw.music.fragment.MainFragment;
import com.ldw.music.fragment.MenuFragment;
import com.ldw.music.slidemenu.SlidingMenu;
import com.ldw.music.utils.MusicUtils;
import com.ldw.music.utils.SplashScreen;

/**
 * 主类,首次进入应用会到这里
 * 该类提供了首页MainFragment的显示和侧滑MenuFragment的显示
 * @author longdw
 *
 */
@SuppressLint("HandlerLeak")
public class MainContentActivity extends FragmentActivity implements IConstants {

	public static final String ALARM_CLOCK_BROADCAST = "alarm_clock_broadcast";
	public SlidingMenu mSlidingMenu;
	private List<OnBackListener> mBackListeners = new ArrayList<OnBackListener>();
	public MainFragment mMainFragment;

	private Handler mHandler;
	private MusicInfoDao mMusicDao;
	private SplashScreen mSplashScreen;
	private int mScreenWidth;

	public interface OnBackListener {
		public abstract void onBack();
	}

	@Override
	protected void onCreate(Bundle arg0) {
		super.onCreate(arg0);

		DisplayMetrics metric = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metric);
		mScreenWidth = metric.widthPixels;

		initSDCard();

		IntentFilter filter = new IntentFilter();
		filter.addAction(ALARM_CLOCK_BROADCAST);
		registerReceiver(mAlarmReceiver, filter);

		setContentView(R.layout.frame_main);
		mSplashScreen = new SplashScreen(this);
		mSplashScreen.show(R.drawable.image_splash_background,
				SplashScreen.SLIDE_LEFT);
		// set the Above View
		mMainFragment = new MainFragment();
		getSupportFragmentManager().beginTransaction()
				.replace(R.id.frame_main, mMainFragment).commit();

		// configure the SlidingMenu
		mSlidingMenu = new SlidingMenu(this);
		mSlidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
		mSlidingMenu.setMode(SlidingMenu.RIGHT);
		mSlidingMenu.setShadowWidthRes(R.dimen.shadow_width);
		mSlidingMenu.setShadowDrawable(R.drawable.shadow);
		mSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
		mSlidingMenu.setFadeDegree(0.35f);
		mSlidingMenu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
		mSlidingMenu.setMenu(R.layout.frame_menu);
		getSupportFragmentManager().beginTransaction()
				.replace(R.id.frame_menu, new MenuFragment()).commit();

		mMusicDao = new MusicInfoDao(this);

		mHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				mSplashScreen.removeSplashScreen();
			}
		};

		getData();
	}

	private void initSDCard() {
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.setPriority(1000);// 设置最高优先级
		intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);// sd卡被插入,且已经挂载
		intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);// sd卡存在,但还没有挂载
		intentFilter.addAction(Intent.ACTION_MEDIA_REMOVED);// sd卡被移除
		intentFilter.addAction(Intent.ACTION_MEDIA_SHARED);// sd卡作为
															// USB大容量存储被共享,挂载被解除
		intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);// sd卡已经从sd卡插槽拔出,但是挂载点还没解除
		// intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);// 开始扫描
		// intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);// 扫描完成
		intentFilter.addDataScheme("file");
		registerReceiver(sdCardReceiver, intentFilter);// 注册监听函数
	}

	private void getData() {
		new Thread(new Runnable() {

			@Override
			public void run() {
				if (mMusicDao.hasData()) {
					// 如果有数据就等三秒跳转
					mHandler.sendMessageDelayed(mHandler.obtainMessage(), 3000);
				} else {
					MusicUtils.queryMusic(MainContentActivity.this,
							START_FROM_LOCAL);
					MusicUtils.queryAlbums(MainContentActivity.this);
					MusicUtils.queryArtist(MainContentActivity.this);
					MusicUtils.queryFolder(MainContentActivity.this);
					mHandler.sendEmptyMessage(1);
				}
			}
		}).start();
	}

	public void registerBackListener(OnBackListener listener) {
		if (!mBackListeners.contains(listener)) {
			mBackListeners.add(listener);
		}
	}

	public void unRegisterBackListener(OnBackListener listener) {
		mBackListeners.remove(listener);
	}

	@Override
	public void onBackPressed() {
		if (mSlidingMenu.isMenuShowing()) {
			mSlidingMenu.showContent();
		} else {
			if (mBackListeners.size() == 0) {
				// super.onBackPressed();
				// 在activity中调用 moveTaskToBack (boolean nonRoot)方法即可将activity
				// 退到后台,注意不是finish()退出。
				// 参数为false代表只有当前activity是task根,指应用启动的第一个activity时,才有效;
				moveTaskToBack(true);
			}
			for (OnBackListener listener : mBackListeners) {
				listener.onBack();
			}
		}
	}

	private final BroadcastReceiver sdCardReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (action.equals("android.intent.action.MEDIA_REMOVED")// 各种未挂载状态
					|| action.equals("android.intent.action.MEDIA_UNMOUNTED")
					|| action.equals("android.intent.action.MEDIA_BAD_REMOVAL")
					|| action.equals("android.intent.action.MEDIA_SHARED")) {
				finish();
				Toast.makeText(MainContentActivity.this, "SD卡以外拔出,本地数据没法初始化!",
						Toast.LENGTH_SHORT).show();
			}
		}
	};

	public void showSleepDialog() {

		if (MusicApp.mIsSleepClockSetting) {
			cancleSleepClock();
			Toast.makeText(getApplicationContext(), "已取睡眠模式!",
					Toast.LENGTH_SHORT).show();
			return;
		}

		View view = View.inflate(this, R.layout.sleep_time, null);
		final Dialog dialog = new Dialog(this, R.style.lrc_dialog);
		dialog.setContentView(view);
		dialog.setCanceledOnTouchOutside(false);

		Window dialogWindow = dialog.getWindow();
		WindowManager.LayoutParams lp = dialogWindow.getAttributes();
		dialogWindow.setGravity(Gravity.CENTER);
		// lp.x = 100; // 新位置X坐标
		// lp.y = 100; // 新位置Y坐标
		lp.width = (int) (mScreenWidth * 0.7); // 宽度
		// lp.height = 400; // 高度

		// 当Window的Attributes改变时系统会调用此函数,可以直接调用以应用上面对窗口参数的更改,也可以用setAttributes
		// dialog.onWindowAttributesChanged(lp);
		dialogWindow.setAttributes(lp);

		dialog.show();

		final Button cancleBtn = (Button) view.findViewById(R.id.cancle_btn);
		final Button okBtn = (Button) view.findViewById(R.id.ok_btn);
		final EditText timeEt = (EditText) view.findViewById(R.id.time_et);
		OnClickListener listener = new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (v == cancleBtn) {
					dialog.dismiss();
				} else if (v == okBtn) {
					String timeS = timeEt.getText().toString();
					if (TextUtils.isEmpty(timeS)
							|| Integer.parseInt(timeS) == 0) {
						Toast.makeText(getApplicationContext(), "输入无效!",
								Toast.LENGTH_SHORT).show();
						return;
					}
					setSleepClock(timeS);
					dialog.dismiss();
				}
			}
		};

		cancleBtn.setOnClickListener(listener);
		okBtn.setOnClickListener(listener);
	}

	/**
	 * 设置睡眠闹钟
	 * 
	 * @param timeS
	 */
	private void setSleepClock(String timeS) {
		Intent intent = new Intent(ALARM_CLOCK_BROADCAST);
		PendingIntent pendingIntent = PendingIntent.getBroadcast(
				MainContentActivity.this, 0, intent, 0);
		// 设置time时间之后退出程序
		int time = Integer.parseInt(timeS);
		long longTime = time * 60 * 1000L;
		AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
		am.set(AlarmManager.RTC, System.currentTimeMillis() + longTime,
				pendingIntent);
		MusicApp.mIsSleepClockSetting = true;
		Toast.makeText(getApplicationContext(), "将在"+timeS+"分钟后退出软件", Toast.LENGTH_SHORT)
				.show();
	}

	/**
	 * 取消睡眠闹钟
	 */
	private void cancleSleepClock() {
		Intent intent = new Intent(ALARM_CLOCK_BROADCAST);
		PendingIntent pendingIntent = PendingIntent.getBroadcast(
				MainContentActivity.this, 0, intent, 0);
		AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
		am.cancel(pendingIntent);
		MusicApp.mIsSleepClockSetting = false;
	}

	private BroadcastReceiver mAlarmReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			//退出程序
			finish();
		}

	};

	@Override
	public void onDestroy() {
		super.onDestroy();
		unregisterReceiver(sdCardReceiver);
		unregisterReceiver(mAlarmReceiver);
		MusicApp.mServiceManager.exit();
		MusicApp.mServiceManager = null;
		MusicUtils.clearCache();
		cancleSleepClock();
		System.exit(0);
	}

}

该类使用SlideMenu控制着MainFragment和MenuFragment,监听SD卡的变化,具体的实现代码中写的很详细,接下来看看MainFragment:

package com.ldw.music.fragment;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.ldw.music.MusicApp;
import com.ldw.music.R;
import com.ldw.music.activity.IConstants;
import com.ldw.music.aidl.IMediaService;
import com.ldw.music.db.AlbumInfoDao;
import com.ldw.music.db.ArtistInfoDao;
import com.ldw.music.db.FavoriteInfoDao;
import com.ldw.music.db.FolderInfoDao;
import com.ldw.music.db.MusicInfoDao;
import com.ldw.music.interfaces.IOnServiceConnectComplete;
import com.ldw.music.model.MusicInfo;
import com.ldw.music.service.ServiceManager;
import com.ldw.music.uimanager.MainBottomUIManager;
import com.ldw.music.uimanager.SlidingDrawerManager;
import com.ldw.music.uimanager.UIManager;
import com.ldw.music.uimanager.UIManager.OnRefreshListener;
import com.ldw.music.utils.MusicTimer;

/**
 * 首页内容
 * 该类展示了软件的几大模块
 * 另外要注意嵌套的两层ViewPager
 * @author longdw
 *
 */
public class MainFragment extends Fragment implements IConstants,
		IOnServiceConnectComplete, OnRefreshListener, OnTouchListener {

	private GridView mGridView;
	private MyGridViewAdapter mAdapter;
	protected IMediaService mService;

	private MusicInfoDao mMusicDao;
	private FolderInfoDao mFolderDao;
	private ArtistInfoDao mArtistDao;
	private AlbumInfoDao mAlbumDao;
	private FavoriteInfoDao mFavoriteDao;
	public UIManager mUIManager;

	private MusicTimer mMusicTimer;
	private MusicPlayBroadcast mPlayBroadcast;
	private MainBottomUIManager mBottomUIManager;
	private SlidingDrawerManager mSdm;
	private RelativeLayout mBottomLayout, mMainLayout;
	private Bitmap defaultArtwork;
	private ServiceManager mServiceManager;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mMusicDao = new MusicInfoDao(getActivity());
		mFolderDao = new FolderInfoDao(getActivity());
		mArtistDao = new ArtistInfoDao(getActivity());
		mAlbumDao = new AlbumInfoDao(getActivity());
		mFavoriteDao = new FavoriteInfoDao(getActivity());
		mServiceManager = MusicApp.mServiceManager;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {

		View view = inflater.inflate(R.layout.frame_main1, container, false);
		mGridView = (GridView) view.findViewById(R.id.gridview);
		mAdapter = new MyGridViewAdapter();

		mMainLayout = (RelativeLayout) view
				.findViewById(R.id.main_layout);
		mMainLayout.setOnTouchListener(this);
		mBottomLayout = (RelativeLayout) view.findViewById(R.id.bottomLayout);

		MusicApp.mServiceManager.connectService();
		MusicApp.mServiceManager.setOnServiceConnectComplete(this);

		mGridView.setAdapter(mAdapter);

		mUIManager = new UIManager(getActivity(), view);
		mUIManager.setOnRefreshListener(this);

		mSdm = new SlidingDrawerManager(getActivity(), mServiceManager, view);
		mBottomUIManager = new MainBottomUIManager(getActivity(), view);
		mMusicTimer = new MusicTimer(mSdm.mHandler, mBottomUIManager.mHandler);
		mSdm.setMusicTimer(mMusicTimer);

		mPlayBroadcast = new MusicPlayBroadcast();
		IntentFilter filter = new IntentFilter(BROADCAST_NAME);
		filter.addAction(BROADCAST_NAME);
		getActivity().registerReceiver(mPlayBroadcast, filter);

		return view;
	}

	private class MyGridViewAdapter extends BaseAdapter {

		private int[] drawable = new int[] { R.drawable.icon_local_music,
				R.drawable.icon_favorites, R.drawable.icon_folder_plus,
				R.drawable.icon_artist_plus, R.drawable.icon_album_plus };
		private String[] name = new String[] { "我的音乐", "我的最爱", "文件夹", "歌手",
				"专辑" };
		private int musicNum = 0, artistNum = 0, albumNum = 0, folderNum = 0, favoriteNum = 0;

		@Override
		public int getCount() {
			return 5;
		}

		@Override
		public Object getItem(int arg0) {
			return null;
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		public void setNum(int music_num, int artist_num, int album_num,
				int folder_num, int favorite_num) {
			musicNum = music_num;
			artistNum = artist_num;
			albumNum = album_num;
			folderNum = folder_num;
			favoriteNum = favorite_num;
			notifyDataSetChanged();
		}

		@Override
		public View getView(final int position, View convertView,
				ViewGroup parent) {

			ViewHolder holder;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = getActivity().getLayoutInflater().inflate(
						R.layout.main_gridview_item, null);
				holder.iv = (ImageView) convertView
						.findViewById(R.id.gridview_item_iv);
				holder.nameTv = (TextView) convertView
						.findViewById(R.id.gridview_item_name);
				holder.numTv = (TextView) convertView
						.findViewById(R.id.gridview_item_num);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			switch (position) {
			case 0:// 我的音乐
				holder.numTv.setText(musicNum + "");
				break;
			case 1:// 我的最爱
				holder.numTv.setText(favoriteNum + "");
				break;
			case 2:// 文件夹
				holder.numTv.setText(folderNum + "");
				break;
			case 3:// 歌手
				holder.numTv.setText(artistNum + "");
				break;
			case 4:// 专辑
				holder.numTv.setText(albumNum + "");
				break;
			}

			convertView.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					int from = -1;
					switch (position) {
					case 0:// 我的音乐
						from = START_FROM_LOCAL;
						break;
					case 1:// 我的最爱
						from = START_FROM_FAVORITE;
						break;
					case 2:// 文件夹
						from = START_FROM_FOLDER;
						break;
					case 3:// 歌手
						from = START_FROM_ARTIST;
						break;
					case 4:// 专辑
						from = START_FROM_ALBUM;
						break;
					}
					mUIManager.setContentType(from);
				}
			});

			holder.iv.setImageResource(drawable[position]);
			holder.nameTv.setText(name[position]);

			return convertView;
		}

		private class ViewHolder {
			ImageView iv;
			TextView nameTv, numTv;
		}
	}

	@Override
	public void onServiceConnectComplete(IMediaService service) {
		// service绑定成功会执行到这里
		refreshNum();
	}

	public void refreshNum() {
		int musicCount = mMusicDao.getDataCount();
		int artistCount = mArtistDao.getDataCount();
		int albumCount = mAlbumDao.getDataCount();
		int folderCount = mFolderDao.getDataCount();
		int favoriteCount = mFavoriteDao.getDataCount();

		mAdapter.setNum(musicCount, artistCount, albumCount, folderCount, favoriteCount);
	}

	private class MusicPlayBroadcast extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(BROADCAST_NAME)) {
				MusicInfo music = new MusicInfo();
				int playState = intent.getIntExtra(PLAY_STATE_NAME, MPS_NOFILE);
				int curPlayIndex = intent.getIntExtra(PLAY_MUSIC_INDEX, -1);
				Bundle bundle = intent.getBundleExtra(MusicInfo.KEY_MUSIC);
				if (bundle != null) {
					music = bundle.getParcelable(MusicInfo.KEY_MUSIC);
				}
				switch (playState) {
				case MPS_INVALID:// 考虑后面加上如果文件不可播放直接跳到下一首
					mMusicTimer.stopTimer();
					mSdm.refreshUI(0, music.duration, music);
					mSdm.showPlay(true);

					mBottomUIManager.refreshUI(0, music.duration, music);
					mBottomUIManager.showPlay(true);
					break;
				case MPS_PAUSE:
					mMusicTimer.stopTimer();
					mSdm.refreshUI(mServiceManager.position(), music.duration,
							music);
					mSdm.showPlay(true);

					mBottomUIManager.refreshUI(mServiceManager.position(), music.duration,
							music);
					mBottomUIManager.showPlay(true);

					mServiceManager.cancelNotification();
					break;
				case MPS_PLAYING:
					mMusicTimer.startTimer();
					mSdm.refreshUI(mServiceManager.position(), music.duration,
							music);
					mSdm.showPlay(false);

					mBottomUIManager.refreshUI(mServiceManager.position(), music.duration,
							music);
					mBottomUIManager.showPlay(false);

					break;
				case MPS_PREPARE:
					mMusicTimer.stopTimer();
					mSdm.refreshUI(0, music.duration, music);
					mSdm.showPlay(true);

					mBottomUIManager.refreshUI(0, music.duration, music);
					mBottomUIManager.showPlay(true);

					// 读取歌词文件
					mSdm.loadLyric(music);
					break;
				}
			}
		}
	}

	@Override
	public void onRefresh() {
		refreshNum();
	}

	int oldY = 0;
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		int bottomTop = mBottomLayout.getTop();
		System.out.println(bottomTop);
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			oldY = (int) event.getY();
			if (oldY > bottomTop) {
				mSdm.open();
			}
		}
		return true;
	}
}

布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg"
    android:gravity="center"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/top_layout"
        android:layout_width="fill_parent"
        android:layout_height="50dip"
        android:background="@color/half_transparent"
        android:gravity="center" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="我的首页"
            android:textColor="@color/white"
            android:textSize="@dimen/title_text_sp" />
    </LinearLayout>

    <RelativeLayout
        android:id="@+id/bottomLayout"
        android:layout_width="fill_parent"
        android:layout_height="64dip"
        android:layout_alignParentBottom="true"
        android:background="@color/bottom_color" >

        <ImageView
            android:id="@+id/headicon_iv"
            android:layout_width="64dip"
            android:layout_height="64dip"
            android:background="@drawable/img_album_background" />

        <ImageButton
            android:id="@+id/btn_menu2"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_margin="4.0dip"
            android:background="@drawable/selector_music_btn"
            android:padding="6.0dip"
            android:src="@drawable/icon_menu_point" />

        <View
            android:id="@+id/split"
            android:layout_width="1.5dip"
            android:layout_height="64dip"
            android:layout_marginLeft="6.0dip"
            android:layout_marginRight="6.0dip"
            android:layout_toLeftOf="@id/btn_menu2"
            android:background="#6a5e8a" />

        <ImageButton
            android:id="@+id/btn_playNext2"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@id/split"
            android:background="@drawable/selector_music_btn"
            android:padding="6.0dip"
            android:src="@drawable/icon_next_normal" />

        <FrameLayout
            android:id="@+id/playLayout"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_centerVertical="true"
            android:layout_marginRight="12.0dip"
            android:layout_toLeftOf="@id/btn_playNext2" >

            <ImageButton
                android:id="@+id/btn_pause2"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                android:background="@drawable/selector_music_btn"
                android:padding="6.0dip"
                android:src="@drawable/icon_pause_normal"
                android:visibility="gone" />

            <ImageButton
                android:id="@+id/btn_play2"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                android:background="@drawable/selector_music_btn"
                android:padding="6.0dip"
                android:src="@drawable/icon_play_normal" />
        </FrameLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="6.0dip"
            android:layout_toLeftOf="@id/playLayout"
            android:layout_toRightOf="@id/headicon_iv"
            android:orientation="vertical" >

            <com.ldw.music.view.AlwaysMarqueeTextView
                android:id="@+id/artist_tv2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="marquee"
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:marqueeRepeatLimit="marquee_forever"
                android:scrollHorizontally="true"
                android:singleLine="true"
                android:textColor="@color/white"
                android:textSize="12sp" />

            <com.ldw.music.view.AlwaysMarqueeTextView
                android:id="@+id/musicname_tv2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="marquee"
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:marqueeRepeatLimit="marquee_forever"
                android:scrollHorizontally="true"
                android:singleLine="true"
                android:textColor="@color/white" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal" >

                <TextView
                    android:id="@+id/position_tv2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="@color/white"
                    android:text="00:00" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text=" - "
                    android:textColor="@color/white" />

                <TextView
                    android:id="@+id/duration_tv2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="@color/white"
                    android:text="00:00" />
            </LinearLayout>
        </LinearLayout>
    </RelativeLayout>

    <ProgressBar
        android:id="@+id/playback_seekbar2"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/bottomLayout"
        android:max="100"
        android:maxHeight="2.0dip"
        android:minHeight="2.0dip"
        android:progressDrawable="@drawable/playback_seekbar2" />

    <GridView
        android:id="@+id/gridview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@id/top_layout"
        android:layout_above="@id/playback_seekbar2"
        android:layout_margin="8.0dip"
        android:horizontalSpacing="6.0dip"
        android:numColumns="3"
        android:verticalSpacing="6.0dip" />

    <com.ldw.music.view.MySlidingDrawer
        android:id="@+id/slidingDrawer"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@drawable/sliding_bg"
        android:content="@+id/content"
        android:handle="@+id/handle"
        android:visibility="invisible" >

        <include layout="@layout/sliding_handle" />

        <include layout="@layout/sliding_content" />
    </com.ldw.music.view.MySlidingDrawer>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="invisible" >
    </android.support.v4.view.ViewPager>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPagerSub"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="invisible" >
    </android.support.v4.view.ViewPager>

</RelativeLayout>

MainFragment控制着主要的UI部分,从布局文件中可以看出,我这里用了两个ViewPager,原因是从文件夹、列表、歌手进入的时候会有两级目录才能进入歌曲列表,当然天天动听不是这么做的,我这里为了方便用了现成的ViewPager来控制,效果还行。还有就是UIManager类,该类控制从主页的GridView进入其他界面。

还有一些诸如自定义View之类的我这里就不做介绍了,大家可以看下源码就知道了,下面是项目在github上的地址,发帖不容易,希望大家多提提宝贵的意见也算是给我的鼓励。

项目地址

《Android仿天天动听音乐播放器(三)》上有11条评论

  1. sdcard的监听是怎样实现的,难道是定义了那个sdCardReceiver,可是它并没有处理如何扫描文件

    1. sdcard监听没有处理扫描哦,很简单的,在onReceive里面监听到sd卡发生了变化就重新扫描就行了,我这里只是做了sd卡没有mount的情况。

    1. aidl,进程间通信,也就是你其他进程也可以访问到,音乐播放器这个应用其实用不用aidl无所谓的,我主要是为了方便操作service

  2. 还没看代码,简单看了下功能。发现一个小BUG:点击换肤的时候会出一点小问题。比如在(1)首页——>(2)歌手——>(3)张杰 ——>进入音频列表。此时换肤,(1)(3)成功换肤,但是(2)还没换过来,需要刷新一下再次感谢隆笛大神,您的开源让我收益良多。

  3. 本人java开发,现在在学android呢,看到你的代码,学习了,我QQ:895713007

评论已关闭。