可以滑动切歌的播放控制条(模仿QQ音乐)
看了QQ音乐Android版有这个功能,觉得挺好玩的,就模仿它做了一个demo,可以滑动切歌(转换的gif严重失真,只能截图了 -.-)
项目地址:https://github.com/bxbxbai/SwipePlaybarDemo
下载地址:http://vdisk.weibo.com/s/GGofvp4_QVU/1428410542
底部播放条的歌曲信息可以滑动切换,并且专辑图会转动
看看截图
这个是4个播放条的截图:
实现
这个功能就是使用ViewPager这个组件来实现,然后最主要的就是为这个ViewPager写一个PagerAapter。这个PagerAdapter写起来也容易,但是我在这个类里做了一些优化。
这个PagerAdapter的全部代码就在下面:
/**
* PlayBar ViewPager Adapter
*
* @author bxbxbai
*/
public class PlayCtrlBarPagerAdapter extends PagerAdapter {
private static final int NUM_SONGS = 10;
private static final int ANIMATOR_DURATION = 1000 * 10;
private LayoutInflater mInflater;
private Queue<View> mReusableViews;
public PlayCtrlBarPagerAdapter(Context context) {
mInflater = LayoutInflater.from(context);
mReusableViews = new ArrayDeque<>(NUM_SONGS);
}
@Override
public int getCount() {
return NUM_SONGS;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (object instanceof View) {
container.removeView((View) object);
mReusableViews.add((View) object);
}
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View v = mReusableViews.poll();
if (v == null) {
v = mInflater.inflate(R.layout.layout_music, container, false);
setAnimator(v);
}
bindData(v, position);
container.addView(v);
return v;
}
private void bindData(View v, int position) {
TextView songName = ButterKnife.findById(v, R.id.tv_song_name);
songName.setText("Try - " + position);
ImageView artistImage = ButterKnife.findById(v, R.id.iv_artist_cover);
if (position % 2 == 1) {
artistImage.setImageResource(R.drawable.adele);
} else {
artistImage.setImageResource(R.drawable.bxbxbai);
}
}
@Override
public float getPageWidth(int position) {
return 1.0f;
}
public static void setAnimator(View view) {
ObjectAnimator animator = ObjectAnimator.ofFloat(view.findViewById(R.id.iv_artist_cover), "rotation", 0f, 360f);
animator.setRepeatCount(Integer.MAX_VALUE);
animator.setDuration(ANIMATOR_DURATION);
animator.setInterpolator(new LinearInterpolator());
view.setTag(R.id.tag_animator, animator);
}
}
优化PagerAdapter
PagerAdapter和Android中ListView的Adapter类似,但是一个主要的不同就是PagerAdapter提供了一个回调方法来让我们处理销毁的Item。
一个ViewPager默认的offScreenPageLimit为1,也就是说当一个ViewPager当前显示页为2,那么PagerAdapter中还存在左右两个Pager,也就是1和3。此时,如果我们将ViewPager滑向3,那么PagerAdapter首先会通过public void destroyItem(ViewGroup container, int position, Object object)方法销毁第1个Item,然后通过public Object instantiateItem(ViewGroup container, int position)生成第4的Item,并且显示当前的Item(为3)。此时,PagerAdapter中存在的Item为2和4
从这个思路出发,我也就可以在destroyItem方法中保存这个object,然后在instantiateItem中使用。
看上面的代码
我写了一个Queue<View> mReusableViews;在destroyItem中保存被销毁的Item,然后在instantiateItem方法中首先去mReusableViews中获取。
如果存在可以重用的Item,那么就不用inflate一个View了,直接绑定数据就可以。否则就创建一个新的View来使用
在实验过程中发现,如果ViewPager的offScreenPageLimit为1,那么只需要创建3个View,其他的View都可以重复使用,这样就可以提升性能了
##如何让ImageView转起来
在View绑定数据的时候通过一个工具方法,为每个View都设置一个ObjectAnimator属性动画。然后我为这个ViewPager专门写了一个ViewPager.PageTransformer类
其实代码也很简单,就是当某一个page完全显示的时候(position为0),开始动画,否则停止动画
如果你需要在ViewPager上添加一些其他特效,那么可以通过addTransformer方法添加PageTransformer
/**
* 播放条的PagerTransformer
*
* @author bxbxbai
*/
public class PlaybarPagerTransformer implements ViewPager.PageTransformer {
private List<ViewPager.PageTransformer> mTransformers = new ArrayList<>();
@Override
public void transformPage(View page, float position) {
for (ViewPager.PageTransformer transformer : mTransformers) {
transformer.transformPage(page, position);
}
//处理图片旋转
StopWatch.log("page: " + page + ", pos: " + position);
if (position == 0) {
ObjectAnimator animator = (ObjectAnimator) page.getTag(R.id.tag_animator);
if (animator != null) {
animator.start();
}
} else if (position == -1 || position == -2 || position == 1) {
ObjectAnimator animator = (ObjectAnimator) page.getTag(R.id.tag_animator);
if (animator != null) {
animator.end();
}
}
}
public void addTransformer(ViewPager.PageTransformer transformer) {
if (transformer != null) {
mTransformers.add(transformer);
}
}
}
Dependency - 依赖
- Java Development Kit (JDK) 7 +
- com.android.tools.build:gradle:1.0.0
- Android SDK
- Android SDK Build-tools 21.1.2
Build - 构建
git clone https://github.com/bxbxbai/SwipePlaybarDemo.git
用最新的IntelliJ IDE导入工程(Import Project),然后等待IDE下载gradle和依赖包即可