Android中广告条轮播(Banner)的实现

Android 自定义控件 专栏收录该内容
11 篇文章 0 订阅

在Android开发中经常用到广告条轮播控件。效果如下:

下面废话不多说,上代码:

控件的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="120dp">
    <android.support.v4.view.ViewPager
        android:id="@+id/vp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"/>
    <LinearLayout
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/tv_title"
            android:layout_gravity="center_vertical"
            android:text="广告条"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content" />
        <LinearLayout
            android:id="@+id/ll_points"
            android:orientation="horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</RelativeLayout>

控件对应的java代码:

//自定义控件
//1,封装
//2,制作特效
public class MyViewPager extends LinearLayout implements OnPageChangeListener, OnClickListener {

    private ViewPager vp;
    private String[] titles;
    private TextView tv_title;
    private LinearLayout ll_points;
    private int[] imgs;

    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        View.inflate(getContext(), R.layout.vp_main, this);
        initView();
    }

    private void initView() {
        vp = (ViewPager) findViewById(R.id.vp);
        tv_title = (TextView) findViewById(R.id.tv_title);
        ll_points = (LinearLayout) findViewById(R.id.ll_points);
    }

    // 修改部分:
    // 1,将适配器修改为优化后的适配器
    // 2,所有使用到初始化的ivs的地方全部删除掉
    public void setDatas(int[] imgs, String[] titles) {
        this.imgs = imgs;
        this.titles = titles;
        for (int i = 0; i < imgs.length; i++) {
            // 添加点
            View child = new View(getContext());
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(20, 20);
            params.leftMargin = 10;
            child.setLayoutParams(params);
            child.setBackgroundResource(R.drawable.point_selector);
            // 给点取个名字
            child.setTag(i);
            child.setOnClickListener(this);
            ll_points.addView(child);
        }
        vp.setAdapter(new MyAdapter());
        vp.setCurrentItem(1);
        tv_title.setText(titles[0]);
        // 默认让第0个点为红色
        ll_points.getChildAt(0).setEnabled(false);
        // 每隔一段时间让ViewPager自动滚动(调用vp.setCurrentItem方法)

    }

    private Handler handler = new Handler();

    // 在自定义控件创建的时候,添加监听
    // 当前自定义控件与窗体进行绑定
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        vp.addOnPageChangeListener(this);
        // 延迟执行参数1
        handler.postDelayed(new MyRunnable(), 1000);
    }

    private boolean isScroll=true;

    private class MyRunnable implements Runnable {
        @Override
        public void run() {
            if (isScroll) {
                vp.setCurrentItem(vp.getCurrentItem()+1);
                handler.postDelayed(this, 1000);
            }
        }
    }

    // 在自定义控件销毁的时候,移除监听
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        vp.removeOnPageChangeListener(this);
        isScroll=false;
    }

    private class MyAdapter extends PagerAdapter {

        private List<ImageView> caches;//定义缓存

        public MyAdapter() {
            caches = new ArrayList<>();
        }

        @Override
        public int getCount() {
            return titles.length + 2;
        }

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            if (caches.isEmpty()) {
                ImageView iv = new ImageView(getContext());
                caches.add(iv);
            }
            ImageView iv = caches.remove(0);
            if (position == 0) {
                iv.setImageResource(imgs[imgs.length - 1]);
            } else if (position == imgs.length + 1) {
                iv.setImageResource(imgs[0]);
            } else {
                iv.setImageResource(imgs[position - 1]);
            }
            container.addView(iv);
            return iv;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            ImageView iv = (ImageView) object;
            container.removeView(iv);
            caches.add(iv);
        }
    }

    // 页面滚动
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    private int modifyPosition;
    private int position;
    private int prePosition = 1;

    // 页面被选择
    @Override
    public void onPageSelected(int position) {
        // 记住修改位置
        this.modifyPosition = position;
        // 记住实际位置
        this.position = position;
        if (position == titles.length + 1) {
            modifyPosition = 1;
        } else if (position == 0) {
            modifyPosition = titles.length;
        }

        Log.i("test", "prePosition:" + prePosition + ", modifyPosition:" + modifyPosition);
        if (prePosition != modifyPosition) {
            tv_title.setText(titles[modifyPosition - 1]);
            // 让之前的点边白,让当前的点变红
            ll_points.getChildAt(modifyPosition - 1).setEnabled(false);
            ll_points.getChildAt(prePosition - 1).setEnabled(true);
            prePosition = modifyPosition;
        }
    }

    // 页面滚动状态改变
    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == OnScrollListener.SCROLL_STATE_IDLE) {
            // 当滑动到最开始或最结尾的位置的时候,需要跳到修改后的位置
            if (this.position == 0 || this.position == titles.length + 1) {
                // 参数2:顺滑的滚动,默认是true
                vp.setCurrentItem(modifyPosition, false);
            }
        }
    }

    @Override
    public void onClick(View v) {
        int tag = (int) v.getTag();
        // 跳转到对应位置的页面
        vp.setCurrentItem(tag);
    }

}

point_selector对应的xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
       <item android:state_enabled="true" android:drawable="@drawable/point_white"></item>
    <item android:state_enabled="false" android:drawable="@drawable/point_red"/>
</selector>

point_white xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval" >
    <solid android:color="@android:color/white" />
</shape>

point_red xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="#f00" />
</shape>
  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值