Android 音乐播放器的实现(二)界面的实现
来源:互联网 发布:免费seo软件 编辑:程序博客网 时间:2024/06/06 07:51
写程序的过程中,想法总会不断地变,有时候会很纠结,到底做哪种效果好,怎么做好呢?
就比如这个音乐播放器,我原来的想法是把列表页面跟歌词页面放在同一个Activity中的两个Fragment,然后通过左右滑动来进行页面的切换。
但是看了酷狗的播放器,它是在启动页面点击了左下角的按钮,就会把歌词页面从右下角斜切上来,我觉得也挺帅的呀,又想做这个效果了。
不管怎么样,先做出一个来再说吧。
下面先看一下效果动态图,机器有点差,开个模拟器真是慢到死。
做得比较匆忙,其实还是有不少Bug的,还有一些功能,比如歌词也还没实现,请各位多包涵。
效果图:
下面我们分几步来讲:
界面:
目前只有两个界面,列表界面MainActivity和歌词DetailActivity。
列表界面也分两部分,上面是一个ListView,下面是一个RelativeLayout,里面放了一个按钮(去歌词界面),一个进度条,一个TextView去显示歌名,两个控制按钮,播放和前进(酷狗就是只有这两个按钮,有点好奇设计的理念是什么,为什么不加前一首?),这个看布局的xml就一目了然了。
\res\layout\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" tools:context=".MainActivity" > <ListView android:id="@+id/lvSongs" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="8" android:cacheColorHint="#00000000" /> <RelativeLayout android:layout_width="match_parent" android:background="#BBBBBB" android:layout_height="0dp" android:layout_weight="1" > <Button android:id="@+id/btnDetail" android:layout_width="48dip" android:layout_height="48dip" android:layout_margin="0dip" android:background="@drawable/music_app" android:layout_alignParentBottom="true" android:layout_alignParentTop="true"/> <SeekBar android:id="@+id/pbDuration" style="?android:attr/progressBarStyleHorizontal" android:layout_width="wrap_content" android:layout_marginTop="3dip" android:layout_height="10dip" android:layout_marginBottom="3dip" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/btnDetail" android:maxHeight="1dip" android:minHeight="1dip" android:progressDrawable="@drawable/progress_style" android:thumbOffset="0dip" android:thumb="@drawable/seekbar_thumb"/> <TextView android:id="@+id/tvCurrentMusic" android:layout_width="190dp" android:layout_height="32dip" android:layout_alignBaseline="@+id/btnNext" android:layout_toRightOf="@+id/btnDetail" android:gravity="left|center_vertical" android:paddingLeft="5dip" android:paddingRight="5dip" /> <Button android:id="@+id/btnStartStop" android:layout_width="32dip" android:layout_height="32dip" android:layout_alignBaseline="@+id/btnNext" android:layout_below="@+id/pbDuration" android:layout_toLeftOf="@+id/btnNext" android:background="@drawable/play" android:layout_marginRight="5dip" /> <Button android:id="@+id/btnNext" android:layout_width="24dp" android:layout_height="24dp" android:layout_alignParentRight="true" android:layout_below="@+id/pbDuration" android:layout_marginRight="20dip" android:background="@drawable/forward" /> </RelativeLayout></LinearLayout>其中进度条是用自定义的风格的(也是在CSDN上找的,还没去具体了解,到时了解了再讲一下)。
下面是DetailActivity的布局xml.
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res/com.example.nature" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/tvTitle" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" android:background="#00EEEE" android:gravity="center_vertical" android:paddingLeft="5dip" android:paddingRight="5dip" /> <TextView android:id="@+id/tvLyric" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="9" android:gravity="center_vertical" android:text="To Continue...." /> <LinearLayout android:id="@+id/llProgress" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" android:gravity="center_horizontal" android:orientation="horizontal" > <TextView android:id="@+id/tvTimeElapsed" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|center_vertical" android:layout_weight="1" android:text="00:00" /> <SeekBar android:id="@+id/pbDuration" style="?android:attr/progressBarStyleHorizontal" android:layout_width="0dip" android:layout_height="10dip" android:layout_gravity="center_horizontal|center_vertical" android:layout_weight="6" android:maxHeight="1dip" android:minHeight="1dip" android:progressDrawable="@drawable/progress_style" android:secondaryProgress="0" android:thumb="@drawable/seekbar_thumb" android:thumbOffset="0dip" /> <TextView android:id="@+id/tvDuration" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|center_vertical" android:layout_weight="1" android:text="00:00" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="2" android:orientation="horizontal" > <com.example.nature.CustomAudioIcon android:id="@+id/btnMode" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" custom:type="mode" custom:color="#66DD22" /> <com.example.nature.CustomAudioIcon android:id="@+id/btnPrevious" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" custom:type="backward" custom:color="#66DD22" /> <com.example.nature.CustomAudioIcon android:id="@+id/btnStartStop" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" custom:type="start" custom:color="#66DD22" /> <com.example.nature.CustomAudioIcon android:id="@+id/btnNext" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" custom:type="forward" custom:color="#66DD22" /> <com.example.nature.CustomAudioIcon android:id="@+id/btnExit" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" custom:type="exit" custom:color="#66DD22" /> </LinearLayout></LinearLayout>这里面有三部分:
上端的是一个TextView,用来显示歌曲名的。
中间的是一个歌词显示,目前还没实现,所以显示了“To Continue...”。
最下面是五个自定义按钮(上网找图标真是很麻烦的,自定义按钮的实现,请看前一篇博文
Android 音乐播放器的实现(一)自定义按钮的实现
控制逻辑
说完界面,下面就是来说我们控制逻辑。
下面是Activity的代码,先贴上来,我再仔细说一下实现。
public class MainActivity extends Activity implements OnClickListener{public static final String TAG = "com.example.nature.MAIN_ACTIVITY";private ListView lvSongs;private SeekBar pbDuration;private TextView tvCurrentMusic;private List<MusicInfo> musicList;private int currentMusic; // The music that is playing.private int currentPosition; //The position of the music is playing.private int currentMax;private Button btnStartStop;private Button btnNext;private Button btnDetail;private ProgressReceiver progressReceiver;private NatureBinder natureBinder;private ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {natureBinder = (NatureBinder) service;}};private void connectToNatureService(){Intent intent = new Intent(MainActivity.this, NatureService.class);bindService(intent, serviceConnection, BIND_AUTO_CREATE);}@Overrideprotected void onCreate(Bundle savedInstanceState) {Log.v(TAG, "OnCreate");super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MusicLoader musicLoader = MusicLoader.instance(getContentResolver());musicList = musicLoader.getMusicList();connectToNatureService();initComponents();}public void onResume(){Log.v(TAG, "OnResume register Progress Receiver");super.onResume();registerReceiver();if(natureBinder != null){if(natureBinder.isPlaying()){btnStartStop.setBackgroundResource(R.drawable.pause);}else{btnStartStop.setBackgroundResource(R.drawable.play);}natureBinder.notifyActivity();}}public void onPause(){Log.v(TAG, "OnPause unregister Progress Receiver");super.onPause();unregisterReceiver(progressReceiver);}public void onStop(){Log.v(TAG, "OnStop");super.onStop();}public void onDestroy(){Log.v(TAG, "OnDestroy");super.onDestroy();if(natureBinder != null){unbindService(serviceConnection);}}private void initComponents(){pbDuration = (SeekBar) findViewById(R.id.pbDuration);pbDuration.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {if(fromUser){natureBinder.changeProgress(progress);}}});tvCurrentMusic = (TextView) findViewById(R.id.tvCurrentMusic);btnStartStop = (Button)findViewById(R.id.btnStartStop);btnStartStop.setOnClickListener(this);btnNext = (Button)findViewById(R.id.btnNext);btnNext.setOnClickListener(this);btnDetail = (Button) findViewById(R.id.btnDetail);btnDetail.setOnClickListener(this);MusicAdapter adapter = new MusicAdapter();lvSongs = (ListView) findViewById(R.id.lvSongs);lvSongs.setAdapter(adapter);lvSongs.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {currentMusic = position;natureBinder.startPlay(currentMusic,0);if(natureBinder.isPlaying()){btnStartStop.setBackgroundResource(R.drawable.pause);}}});}private void registerReceiver(){progressReceiver = new ProgressReceiver();IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(NatureService.ACTION_UPDATE_PROGRESS);intentFilter.addAction(NatureService.ACTION_UPDATE_DURATION);intentFilter.addAction(NatureService.ACTION_UPDATE_CURRENT_MUSIC);registerReceiver(progressReceiver, intentFilter);}class MusicAdapter extends BaseAdapter{@Override public int getCount() {return musicList.size();}@Overridepublic Object getItem(int position) {return musicList.get(position);}@Overridepublic long getItemId(int position) {return musicList.get(position).getId();}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder viewHolder; if(convertView == null){convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.music_item, null);ImageView pImageView = (ImageView) convertView.findViewById(R.id.albumPhoto);TextView pTitle = (TextView) convertView.findViewById(R.id.title);TextView pDuration = (TextView) convertView.findViewById(R.id.duration);TextView pArtist = (TextView) convertView.findViewById(R.id.artist);viewHolder = new ViewHolder(pImageView, pTitle, pDuration, pArtist);convertView.setTag(viewHolder);}else{viewHolder = (ViewHolder) convertView.getTag();}viewHolder.imageView.setImageResource(R.drawable.audio);viewHolder.title.setText(musicList.get(position).getTitle());viewHolder.duration.setText(FormatHelper.formatDuration(musicList.get(position).getDuration()));viewHolder.artist.setText(musicList.get(position).getArtist());return convertView;}}class ViewHolder{public ViewHolder(ImageView pImageView, TextView pTitle, TextView pDuration, TextView pArtist){imageView = pImageView;title = pTitle;duration = pDuration;artist = pArtist;}ImageView imageView;TextView title;TextView duration;TextView artist;}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btnStartStop:play(currentMusic,R.id.btnStartStop);break;case R.id.btnNext:natureBinder.toNext();break;case R.id.btnDetail:Intent intent = new Intent(MainActivity.this,DetailActivity.class);intent.putExtra(DetailActivity.MUSIC_LENGTH, currentMax);intent.putExtra(DetailActivity.CURRENT_MUSIC, currentMusic);intent.putExtra(DetailActivity.CURRENT_POSITION, currentPosition);startActivity(intent);break;}}private void play(int position, int resId){if(natureBinder.isPlaying()){natureBinder.stopPlay();btnStartStop.setBackgroundResource(R.drawable.play);}else{natureBinder.startPlay(position,currentPosition);btnStartStop.setBackgroundResource(R.drawable.pause);}}class ProgressReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if(NatureService.ACTION_UPDATE_PROGRESS.equals(action)){int progress = intent.getIntExtra(NatureService.ACTION_UPDATE_PROGRESS, 0);if(progress > 0){currentPosition = progress; // Remember the current positionpbDuration.setProgress(progress / 1000);}}else if(NatureService.ACTION_UPDATE_CURRENT_MUSIC.equals(action)){//Retrive the current music and get the title to show on top of the screen.currentMusic = intent.getIntExtra(NatureService.ACTION_UPDATE_CURRENT_MUSIC, 0);tvCurrentMusic.setText(musicList.get(currentMusic).getTitle());}else if(NatureService.ACTION_UPDATE_DURATION.equals(action)){//Receive the duration and show under the progress bar//Why do this ? because from the ContentResolver, the duration is zero.currentMax = intent.getIntExtra(NatureService.ACTION_UPDATE_DURATION, 0);int max = currentMax / 1000;Log.v(TAG, "[Main ProgressReciver] Receive duration : " + max);pbDuration.setMax(currentMax / 1000);}}}}
接下来说说主要的实现逻辑:
1)加载歌曲,写了一个MusicLoader来读取本地sdcard中的歌曲,这一方面的请参考:
Android中利用ContentResolver获取本地音乐和相片
2)将歌曲放到ListView中,写了一个继承于BaseAdapter的MusicAdapter,一般实现BaseAdapter,都会用到下面两种优化方式:
2.1)重复利用ConvertView,保证同一个时刻在列表的View不会太多
2.3)利用ViewHolder,来存放加载过的View,不用每次都要重新用findViewById去实例化View,节省成本
3)绑定Service,音乐播放器主要的操作,包括播放,暂停,前进,后退等,都是在Service中实现的,我们在Service里面实现了一个Binder,在里面定义了几种操作,然后传给Activity,让Activity可以跟Service进行互动。
4)继承BroadcastReceiver 实现一个自定义的Receiver,接收从Service传过来的广播,比如当前播放的位置,播放的前/后一首是什么,播放的当前模式是什么,这些都要从Service传回到Activity中,从而让Activity可以根据这些状态去更新按钮的状态。
基本的功能就是这样。
在这里面有一点要注意的就是,注册广播的时候,最好是在OnResume中,因为在OnPause的时候我们会将这个广播给卸掉,这样从歌词界面切回来的时候,系统只会调用OnResume函数,从而就会重新将广播给注册上,而不需要让广播一直监听信息(即使Activity都没显示了)。
基本的逻辑大概就是这样了,但是这里面还是会有很多小细节需要完善的。
比如在Detail界面中一首歌播完了,开始播下一首,那么Service会传个广播回到这个Activity,告诉当前界面要更新歌曲名,歌曲长度,但是如果这个时候我们切回Main界面的话,
Service是不会知道要发送广播回Main界面告诉它要更新的(因为只有在一首歌结束的时候,进入下一首歌的时候才发广播), 那么此时就要在MainActivity恢复(OnResume)的时候,让Service发送广播回来,所以可以在MainActivity中看到如下的代码:
public void onResume(){Log.v(TAG, "OnResume register Progress Receiver");super.onResume();registerReceiver();if(natureBinder != null){...natureBinder.notifyActivity();}}在Service中的Binder也提供了这样一个接口,来让Activity告诉Service,我想知道当前在播哪一首歌。。。
所以在Service中的Binder类,其实我们要实现比较多的接口来跟Activity中交互的,先列举一下,下一篇文章会详细说一下Service
class NatureBinder extends Binder{public void startPlay(int currentMusic, int currentPosition){play(currentMusic,currentPosition);}public void stopPlay(){stop();}public void toNext(){playNext();}public void toPrevious(){playPrevious();}/** * MODE_ONE_LOOP = 1; * MODE_ALL_LOOP = 2; * MODE_RANDOM = 3; * MODE_SEQUENCE = 4; */public void changeMode(){currentMode = (currentMode + 1) % 4;Log.v(TAG, "[NatureBinder] changeMode : " + currentMode);Toast.makeText(NatureService.this, MODE_DESC[currentMode], Toast.LENGTH_SHORT).show();}/** * return the current mode * MODE_ONE_LOOP = 1; * MODE_ALL_LOOP = 2; * MODE_RANDOM = 3; * MODE_SEQUENCE = 4; * @return */public int getCurrentMode(){return currentMode; }/** * The service is playing the music * @return */public boolean isPlaying(){return isPlaying;}/** * Notify Activities to update the current music and duration when current activity changes. */public void notifyActivity(){toUpdateCurrentMusic();toUpdateDuration();}/** * Seekbar changes * @param progress */public void changeProgress(int progress){...}
public class DetailActivity extends Activity implements OnClickListener{private static final String TAG = "com.example.natrue.DetailActivity";public static final String MUSIC_LENGTH = "com.example.nature.DetailActivity.MUSIC_LENGTH";public static final String CURRENT_POSITION = "com.example.nature.DetailActivity.CURRENT_POSITION";public static final String CURRENT_MUSIC = "com.example.nature.DetailActivity.CURRENT_MUSIC";private SeekBar pbDuration;private TextView tvTitle,tvTimeElapsed, tvDuration;private List<MusicInfo> musicList;private int currentMusic;private int currentPosition;private ProgressReceiver progressReceiver;private NatureBinder natureBinder;private int[] btnResIds = new int[] {R.id.btnMode,R.id.btnPrevious, R.id.btnStartStop, R.id.btnNext,R.id.btnExit };private ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {natureBinder = (NatureBinder) service;if(natureBinder.isPlaying()){CustomAudioIcon btnStartStop = (CustomAudioIcon)findViewById(R.id.btnStartStop);btnStartStop.setFlagStart(false);}CustomAudioIcon btnMode = (CustomAudioIcon)findViewById(R.id.btnMode);btnMode.setCurrentMode(natureBinder.getCurrentMode());}};private void connectToNatureService(){Intent intent = new Intent(DetailActivity.this, NatureService.class);bindService(intent, serviceConnection, BIND_AUTO_CREATE);}@Overridepublic void onCreate(Bundle savedInstanceState){Log.v(TAG, "OnCreate");super.onCreate(savedInstanceState);overridePendingTransition(R.anim.push_right_in,R.anim.hold);MusicLoader musicLoader = MusicLoader.instance(getContentResolver());musicList = musicLoader.getMusicList();setContentView(R.layout.detail_layout);connectToNatureService();initComponents();}public void onResume(){Log.v(TAG, "OnResume");super.onResume();initReceiver();}public void onPause(){Log.v(TAG, "OnPause unregister progress receiver");super.onPause();unregisterReceiver(progressReceiver);overridePendingTransition(R.anim.hold, R.anim.push_right_out);}public void onStop(){Log.v(TAG, "OnStop");super.onStop();}public void onDestroy(){Log.v(TAG, "Destroy");super.onDestroy();if(natureBinder != null){unbindService(serviceConnection);}}private void initComponents(){tvTitle = (TextView) findViewById(R.id.tvTitle);currentMusic = getIntent().getIntExtra(CURRENT_MUSIC,0);tvTitle.setText(musicList.get(currentMusic).getTitle());tvDuration = (TextView) findViewById(R.id.tvDuration);int max = getIntent().getIntExtra(MUSIC_LENGTH, 0);tvDuration.setText(FormatHelper.formatDuration(max));pbDuration = (SeekBar) findViewById(R.id.pbDuration);pbDuration.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {if(fromUser){natureBinder.changeProgress(progress);}}});pbDuration.setMax(max/1000);currentPosition = getIntent().getIntExtra(CURRENT_POSITION,0);pbDuration.setProgress(currentPosition / 1000);tvTimeElapsed = (TextView) findViewById(R.id.tvTimeElapsed);tvTimeElapsed.setText(FormatHelper.formatDuration(currentPosition));for(int resId : btnResIds){CustomAudioIcon icon = (CustomAudioIcon)findViewById(resId);icon.setOnClickListener(this);}}private void initReceiver(){progressReceiver = new ProgressReceiver();IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(NatureService.ACTION_UPDATE_PROGRESS);intentFilter.addAction(NatureService.ACTION_UPDATE_DURATION);intentFilter.addAction(NatureService.ACTION_UPDATE_CURRENT_MUSIC);registerReceiver(progressReceiver, intentFilter);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btnStartStop:play(currentMusic,R.id.btnStartStop);break;case R.id.btnNext:natureBinder.toNext();break;case R.id.btnPrevious:natureBinder.toPrevious();break;case R.id.btnExit:finish();break;case R.id.btnMode:natureBinder.changeMode();break;default:break;}}private void play(int currentMusic, int resId){CustomAudioIcon btnStartStop = (CustomAudioIcon) findViewById(resId);if(btnStartStop.isStartStatus()){natureBinder.stopPlay();}else{natureBinder.startPlay(currentMusic,currentPosition);}}class ProgressReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if(NatureService.ACTION_UPDATE_PROGRESS.equals(action)){int progress = intent.getIntExtra(NatureService.ACTION_UPDATE_PROGRESS, currentPosition);if(progress > 0){currentPosition = progress; // Remember the current positiontvTimeElapsed.setText(FormatHelper.formatDuration(progress));pbDuration.setProgress(progress / 1000);}}else if(NatureService.ACTION_UPDATE_CURRENT_MUSIC.equals(action)){//Retrieve the current music and get the title to show on top of the screen.currentMusic = intent.getIntExtra(NatureService.ACTION_UPDATE_CURRENT_MUSIC, 0);tvTitle.setText(musicList.get(currentMusic).getTitle());}else if(NatureService.ACTION_UPDATE_DURATION.equals(action)){//Receive the duration and show under the progress bar//Why do this ? because from the ContentResolver, the duration is zero.int duration = intent.getIntExtra(NatureService.ACTION_UPDATE_DURATION, 0);tvDuration.setText(FormatHelper.formatDuration(duration));pbDuration.setMax(duration / 1000);}}}实现的功能也是类似的,不过为了实现动画效果斜切入的一个功能,我们可以看到在OnCreate函数和OnPause函数中,分别有如下两行代码:
@Override public void onCreate(Bundle savedInstanceState){ ... overridePendingTransition(R.anim.push_right_in,R.anim.hold); ... } @Override public void onPause(){ ... overridePendingTransition(R.anim.hold, R.anim.push_right_out) ; }
这就是为了实现动画斜切效果的一个函数,进入当前Activity的效果是要在OnCreate的SetContentView之前,也就是在添加View到窗口展示前要把这个效果设置进去,而离开当前的Activity的效果要在OnPause的时候,也就是OnStop之前,在界面不见之前把效果给设置进去。
这个函数有两个参数,其中第一个参数是进入下一个Activity的动画,后一个参数是离开当前Activity的动画。
public void overridePendingTransition(int enterAnim, int exitAnim) { try { ActivityManagerNative.getDefault().overridePendingTransition( mToken, getPackageName(), enterAnim, exitAnim); } catch (RemoteException e) { } }
我们再来看一下动画效果的设置,是利用xml来设置的,
res/anim/push_right_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"><translate android:fromYDelta="100%p" android:toYDelta="0" android:fromXDelta="100%p" android:toXDelta="0" android:duration="500"/><rotate android:fromDegrees="90" android:toDegrees="0" android:pivotX="100%p" android:pivotY="100%p" android:duration="500"/><alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="500" /></set>
res/anim/push_right_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"><translate android:fromXDelta="0" android:toXDelta="100%p" android:fromYDelta="0" android:toYDelta="100%p" android:duration="500"/><rotate android:fromDegrees="0" android:toDegrees="90" android:pivotX="100%p" android:pivotY="100%p" android:duration="500"/><alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="500" /></set>
res/anim/hold.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"><translate android:fromXDelta="0" android:toXDelta="0" android:duration="500"/></set>
其中push_right_in 和 push_right_out实现的是相反的效果,一个是从右边斜切进来,一个是斜切出去,而hold是为了保证MainActivity不动的。
关于界面显示的大概就是这么多了,有一些逻辑是跟Service相关的,下一篇讲Service的实现的时候再提一些。
源代码下载
4 0
- Android 音乐播放器的实现(二)界面的实现
- 音乐播放器-引导界面的实现
- 基于android的网络音乐播放器-添加viewpager和fragment实现滑动切换多个界面(二)
- 最简单的音乐播放器,实现基本功能(二)
- 一个简单音乐播放器的Java实现(二)
- 实现一个android的音乐播放器
- Android:音乐播放器的实现
- Android 音乐播放器的实现
- Android简易的音乐播放器实现
- android实现简单的音乐播放器
- Android音乐播放器的简单实现
- android 简易音乐播放器的实现
- 基于android的网络音乐播放器-回调实现音乐播放及音乐收藏的实现(三)
- 自己动手开发音乐播放器《八》迷你界面的实现
- Android开发---音乐播放器(服务类的实现)
- android-音乐播放器实现及源码下载(二)
- android-音乐播放器实现及源码下载(二)
- Android实战 - 音心播放器 (MusicActivity-音乐播放页面界面实现)
- 三 手游开发神器 cocos2d-x editor 之基础工具 intellij idea
- 2001
- 扩展Jquery cookie插件
- 设置UILabel的背景色为透明
- [Java] 反射机制 02 - Good!
- Android 音乐播放器的实现(二)界面的实现
- MySql计算两个日期的时间差函数
- apache+tomcat集群处理
- User-agent 类型汇总
- linux下程序烧写(dnw+minicom)
- POJ 2411 Mondriaan's Dream
- 玩转Web之servlet(一)---怎样创建一个servlet
- 理财:互联网金融货币基金
- 居然没找到空间域名在哪里设置??