您的位置:首页 > 其它

ViewPager 优化

2015-09-03 15:15 330 查看
作者原帖是模仿了QQ音乐的一个功能,我觉得比较有用的是ViewPager的优化。提供了很好的性能优化示例。

转自 http://bxbxbai.gitcafe.io/2015/04/07/swipe-playbar/


可以滑动切歌的播放控制条(模仿QQ音乐)

发表于 Apr 7 2015 | 暂无评论

看了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和依赖包即可
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: