android广告栏banner封装

一.原因

  最近在做开发时,发现一个问题:凡是涉及广告banner的地方都是一份代码拷贝来拷贝去,完全未封装,将所有的实现都暴露在activity和fragment中。这样子导致以后想在某个页面引入一个banner非常的繁琐麻烦,且不利于代码的维护。而且产品又特别喜欢在页面上加banner。最近时间较为充裕,我就尝试了一下把banner封装成一个自定义控件,供以后在项目中使用。

二.效果

android广告栏banner封装_第1张图片

三.原理

banner封装的原理已经不新鲜了,我把一些要点列在下面:

1.handler.postdelay形成循环(也有其他方案)。

2.因为viewpager忽然从17个位置切换回第0个位置效果非常糟糕,因此需要使用一些假象来解决这个问题:让viewpager很大(图片0,图片1,图片2,图片0,图片1,图片2,图片0,图片1,图片2,图片0,图片1,图片2…….)这样循环,初始的时候在中间(且是从图片0位置开始的),底部的指示器(点0,点1,点2)只有三个,底部循环变动,viewpager不断向后滑动(不循环,除非到了最大的位置)。

3.为解决手指放上去的时候,viewpager不自动滑动,需要拦截监听事件。

四.code(talk is cheep, show me your code)

代码:

public class BannerView extends RelativeLayout {
    private ViewPager mViewPager;
    private LinearLayout mLinearLayout;
    private Context mContext;
    private ImageView[] mIndicator;
    private Handler mHandler = new Handler();
    final List mList = new ArrayList<>();
    private OnBannerItemClickListener mOnBannerItemClickListener;
    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
            mHandler.postDelayed(mRunnable, 5000);
        }
    };
    private int mItemCount;

    public interface OnBannerItemClickListener {
        void onClick(int position);
    }

    public BannerView(Context context) {
        this(context, null);
    }

    public BannerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        init();
    }

    private void init() {
        View.inflate(mContext, R.layout.view_bannerview, this);
        // 取到布局中的控件
        mViewPager = (ViewPager) findViewById(R.id.viewpager);
        mLinearLayout = (LinearLayout) findViewById(R.id.ll_points);
    }

    /**
     * 给banner中的viewpager设置数据
     *
     * @param list
     */
    public void setList(List list) {
        if (mList.size() == 0) {
            mList.addAll(list);
            mItemCount = mList.size();
            initView();
        }

    }

    /**
     * banner item的点击监听
     *
     * @param onBannerItemClickListener
     */
    public void setOnBannerItemClickListener(OnBannerItemClickListener onBannerItemClickListener) {
        mOnBannerItemClickListener = onBannerItemClickListener;
    }

    private void initView() {
        // 给viewpager设置adapter
        BannerPagerAdapter bannerPagerAdapter = new BannerPagerAdapter(mList, mContext);
        mViewPager.setAdapter(bannerPagerAdapter);
        // 初始化底部点指示器
        initIndicator(mList, mContext);
        mViewPager.setCurrentItem(500 * mItemCount);

        // 给viewpager设置滑动监听
        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                switchIndicator(position % mItemCount);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                cancelRecycle();
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                startRecycle();
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    private void initIndicator(List list, Context context) {
        mIndicator = new ImageView[mItemCount];
        for (int i = 0; i < mIndicator.length; i++) {
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(12, 12);
            params.setMargins(6, 0, 6, 0);
            ImageView imageView = new ImageView(context);
            mIndicator[i] = imageView;
            if (i == 0) {
                mIndicator[i].setBackgroundResource(R.drawable.ptt_banner_dian_focus);
            } else {
                mIndicator[i].setBackgroundResource(R.drawable.ptt_banner_dian_white);
            }
            mLinearLayout.addView(imageView, params);
        }
        if (mItemCount == 1) {
            mLinearLayout.setVisibility(View.GONE);
        } else {
            mLinearLayout.setVisibility(View.VISIBLE);
        }
    }

    private void switchIndicator(int selectItems) {
        for (int i = 0; i < mIndicator.length; i++) {
            if (i == selectItems) {
                mIndicator[i].setBackgroundResource(R.drawable.ptt_banner_dian_focus);
            } else {
                mIndicator[i].setBackgroundResource(R.drawable.ptt_banner_dian_white);
            }
        }
    }

    private void startRecycle() {
        mHandler.postDelayed(mRunnable, 5000);
    }

    private void cancelRecycle() {
        mHandler.removeCallbacks(mRunnable);
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if (visibility == VISIBLE) {
            startRecycle();
        } else {
            cancelRecycle();
        }
    }


    private class BannerPagerAdapter extends PagerAdapter {
        private List imagesUrl;
        private Context context;

        public BannerPagerAdapter(List imagesUrl, Context context) {
            this.imagesUrl = imagesUrl;
            this.context = context;
        }

        @Override
        public int getCount() {
            return mItemCount == 1 ? 1 : Integer.MAX_VALUE;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, final int position) {
            View ret = null;
            ImageView imageView = new ImageView(context);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            // 联网取图片,根据自己的情况修改
            xxxxxxxxxxxxxxxxxxx
            ret = imageView;
            container.addView(ret);
            ret.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    mOnBannerItemClickListener.onClick(position);
                }
            });
            return ret;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }

}

布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    android.support.v4.view.ViewPager>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/viewpager"
        android:background="#33000000"
        android:orientation="vertical"
        android:padding="5dip" >

        <LinearLayout
            android:id="@+id/ll_points"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dip"
            android:layout_gravity="center_horizontal"
            android:orientation="horizontal" >
        LinearLayout>
    LinearLayout>

RelativeLayout>

五.说明及使用

  应用的时候直接作为自定义控件引入布局中,在代码中只需要setList,同时也可以对每个item添加点击事件,根据positon决定跳转到哪个位置。
bannerview.setOnBannerItemClickListener。

你可能感兴趣的:(自定义view与动画)