实用控件Android开发进阶Android之界面

Android自定义带动画无限自动轮播的Banner控件

2017-04-02  本文已影响3742人  笑说余生

显示的效果请往下看,先说一下需求,可以自动轮播,按下停止轮播,松手开始轮播,不可见时停止轮播,自动轮播时带动画,手动滑动时不带动画,点击时要有水波纹效果,下拉刷新回到第一页,页面不能卡顿等等。参考了一些网上的想法,结合自己的认知,总结如下。


先上效果图

<img width="0" src="http:https://img.haomeiwen.com/i2786991/34861ad3cdcb4231.gif?imageMogr2/auto-orient/strip"></img>

自定义BannerView控件

为了以后开发的方便,这里将Banner封装成一个控件来使用,以后就可以直接在布局里引用。

做这种轮播效果一般采用的都是ViewPager,所以这个控件也是对ViewPager的封装,为了解耦,这里没有把适配器放在BannerView,只是提供了基类适配器和接口,使用很方便。

讲一下具体如何实现封装:
第一步:自定义控件,实现构造,初始化属性和视图。

   private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BannerView);
        pageMargin = (int) a.getDimension(R.styleable.BannerView_bannerPageMargin, pageMargin);
        pagePercent = a.getFloat(R.styleable.BannerView_bannerPagePercent, pagePercent);
        scaleMin = a.getFloat(R.styleable.BannerView_bannerPageScale, scaleMin);
        alphaMin = a.getFloat(R.styleable.BannerView_bannerPageAlpha, alphaMin);
        ...
        a.recycle();
    }
    private void initView() {
        mRootView = LayoutInflater.from(getContext()).inflate(R.layout.banner_view, this);
        mViewPager = (ViewPager) mRootView.findViewById(R.id.viewPager);
        LayoutParams params = (LayoutParams) mViewPager.getLayoutParams();
        params.width = (int) (getScreenWidth() * pagePercent);
        params.gravity = Gravity.CENTER;
        mViewPager.setLayoutParams(params);
        mViewPager.setPageMargin(pageMargin);
        mViewPager.setPageTransformer(false, new BannerPageTransformer());
        mViewPager.setOffscreenPageLimit(5);
        // 自动轮播任务
        mScrollTask = new AutoScrollTask();
        // 如果动画轮播
        if (isAnimScroll) {
            setAnimationScroll((int) mAnimDuration);
        }
    }

第二步:滑动动画实现

    public void transformPage(View page, float position) {
       // 不同位置的缩放和透明度
       float scale = (position < 0)
                ? ((1 - scaleMin) * position + 1)
                : ((scaleMin - 1) * position + 1);
       float alpha = (position < 0)
                ? ((1 - alphaMin) * position + 1)
                : ((alphaMin - 1) * position + 1);
       // 保持左右两边的图片位置中心
       if (position < 0) {
            ViewCompat.setPivotX(page, page.getWidth());
            ViewCompat.setPivotY(page, page.getHeight() / 2);
        } else {
            ViewCompat.setPivotX(page, 0);
            ViewCompat.setPivotY(page, page.getHeight() / 2);
        }
        Log.d(TAG, "transformPage: scale=" + scale);
        ViewCompat.setScaleX(page, scale);
        ViewCompat.setScaleY(page, scale);
        ViewCompat.setAlpha(page, Math.abs(alpha));
    }

第三步:无限自动轮播和轮播动画处理

   @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        // 视图初始化完毕,开始轮播任务
        if (mScrollTask == null) mScrollTask = new AutoScrollTask();
        if (isAutoScroll) startAutoScroll();
    }
 public void startScroll(int startX, int startY, int dx,
                                        int dy, int duration) {
      // 如果手动滚动,则加速滚动
         // TODO 使用这种设置极不稳定,需要抽离
         if (System.currentTimeMillis() - mRecentTouchTime > mScrollDuration && isAnimScroll) {
             // 动画滑动
             duration = during;
         } else {
             // 手势滚动
             duration /= 2;

         }
         super.startScroll(startX, startY, dx, dy, duration);
     }

BannerView的基类适配器封装

private class BannerAdapter extends BannerBaseAdapter<BannerBean> {
        public BannerAdapter(Context context) {
            super(context);
        }
        @Override
        protected int getLayoutResID() {
            return R.layout.item_banner;
        }
        @Override
        protected void convert(View convertView, BannerBean data) {
            setImage(R.id.pageImage, data.imageRes);
            setText(R.id.pageText, data.title);
        }
  }

使用教程

 <com.pinger.widget.banner.BannerView
      android:id="@+id/bannerView"
      android:layout_width="match_parent"
      android:layout_height="200dp"
      app:bannerPageAlpha="1.0"
      app:bannerPageMargin="8dp"
      app:bannerPagePercent="0.8"
      app:bannerPageScale="0.8"
      app:bannerAnimScroll="true"
      app:bannerAutoScroll="true"
      app:bannerScrollDuration="4000"
      app:bannerAnimDuration="1500"/>
  final BannerView bannerView = (BannerView) findViewById(R.id.bannerView);
  bannerView.setAdapter(mAdapter = new BannerAdapter(this));
  initData();  // 初始化数据
  mAdapter.setData(mDatas);
  mAdapter.setOnPageTouchListener(...);

Demo下载地址

欢迎大家访问我的简书博客GitHub

上一篇 下一篇

猜你喜欢

热点阅读