ViewPager 优化

来源:互联网 发布:淘宝拍图片要多少钱 编辑:程序博客网 时间:2024/04/29 21:02

作者原帖是模仿了QQ音乐的一个功能,我觉得比较有用的是ViewPager的优化。提供了很好的性能优化示例。

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


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

看了QQ音乐Android版有这个功能,觉得挺好玩的,就模仿它做了一个demo,可以滑动切歌(转换的gif严重失真,只能截图了 -.-)

项目地址:https://github.com/bxbxbai/SwipePlaybarDemo

下载地址:http://vdisk.weibo.com/s/GGofvp4_QVU/1428410542

底部播放条的歌曲信息可以滑动切换,并且专辑图会转动

##看看截图
这个是4个播放条的截图:
playbar

##实现

这个功能就是使用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中ListViewAdapter类似,但是一个主要的不同就是PagerAdapter提供了一个回调方法来让我们处理销毁的Item。

一个ViewPager默认的offScreenPageLimit为1,也就是说当一个ViewPager当前显示页为2,那么PagerAdapter中还存在左右两个Pager,也就是13。此时,如果我们将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为24

从这个思路出发,我也就可以在destroyItem方法中保存这个object,然后在instantiateItem中使用。

###看上面的代码

我写了一个Queue<View> mReusableViews;destroyItem中保存被销毁的Item,然后在instantiateItem方法中首先去mReusableViews中获取。

如果存在可以重用的Item,那么就不用inflate一个View了,直接绑定数据就可以。否则就创建一个新的View来使用

在实验过程中发现,如果ViewPageroffScreenPageLimit为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和依赖包即可


0 0
原创粉丝点击