Android封装Banner控件方法介绍

目录
  • 代码展示
  • 调用方式
  • 代码分析
  • 结束

如上图所示效果我们应该都不陌生,这是一个简单的banner轮播效果,网上也有很多的开源项目,但有时候可能我们仅仅只需要一些简单的效果,并不需要其他过多的东西。这里简单的对banner进行一下封装,随时调用和添加一些新的功能。

代码展示

/**
 * Created by xiaolong on 2018/1/23.
 */
public class BannerView extends FrameLayout implements ViewPager.OnPageChangeListener{
    private ViewPager viewPager;
    //网络图片地址
    private List<String> imageUrls;
    //指示点的容器
    private LinearLayout pointLayout;
    //当前页面位置
    private int currentItem;
    //自动播放时间
    private int autoPlayTime = 2000;
    //是否自动播放
    private boolean isAutoPlay;
    //是否是一张图片
    private boolean isOneImage;
    //监听事件
    private OnBannerItemClick onBannerItemClick;
    //这里利用handler实现循环播放
    private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            currentItem++;
            currentItem = currentItem % (imageUrls.size() + 2);
            viewPager.setCurrentItem(currentItem);
            handler.sendEmptyMessageDelayed(0,autoPlayTime);
            return false;
        }
    });
    public BannerView(@NonNull Context context) {
        this(context,null);
    }
    public BannerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }
    public BannerView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.BannerView,0,0);
        //默认自动播放
        isAutoPlay = typedArray.getBoolean(R.styleable.BannerView_isAutoPlay,true);
        typedArray.recycle();
        viewPager = new ViewPager(getContext());
        pointLayout = new LinearLayout(getContext());
        //添加监听事件
        viewPager.addOnPageChangeListener(this);
        //利用布局属性将指示器容器放置底部并居中
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
        params.bottomMargin = 60;
        addView(viewPager);
        addView(pointLayout,params);
    }
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }
    @Override
    public void onPageSelected(int position) {
        currentItem = position;
        if (!isOneImage) {
            switchToPoint(toRealPosition(position));
        }
    }
    @Override
    public void onPageScrollStateChanged(int state) {
    //根据滑动松开后的状态,去判断当前的current 并跳转到指定current
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            int current = viewPager.getCurrentItem();
            int lastReal = viewPager.getAdapter().getCount() - 2;
            if (current == 0) {
                viewPager.setCurrentItem(lastReal, false);
            } else if (current == lastReal + 1) {
                viewPager.setCurrentItem(1, false);
            }
        }
    }
    //配置viewpager适配器
    private class BannerAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return imageUrls.size() + 2;
        }
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }
        @Override
        public Object instantiateItem(ViewGroup container, final int position) {
            ImageView imageView = new ImageView(getContext());
            imageView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (onBannerItemClick != null) {
                        onBannerItemClick.onItemClick(toRealPosition(position));
                    }
                }
            });
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            Glide.with(getContext()).load(imageUrls.get(toRealPosition(position))).into(imageView);
            container.addView(imageView);
            return imageView;
        }
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }
    //添加网络图片
    public void setImageUrls(List<String> imageUrls) {
        this.imageUrls = imageUrls;
        if (imageUrls.size() <= 1) {
            isOneImage = true;
        }else {
            isOneImage = false;
        }
        initViewPager();
    }
    //加载viewPager
    private void initViewPager() {
        if (!isOneImage) {
            //添加指示点
            addPoints();
        }
        BannerAdapter adapter = new BannerAdapter();
        viewPager.setAdapter(adapter);
        //默认当前图片
        viewPager.setCurrentItem(1);
        //判断是否自动播放和是否是一张图片的情况
        if (isAutoPlay && !isOneImage) {
            handler.sendEmptyMessageDelayed(0,autoPlayTime);
        }
    }
    //添加指示点
    private void addPoints() {
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lp.setMargins(10, 10, 10, 10);
        ImageView imageView;
        int length = imageUrls.size();
        for (int i = 0; i < length; i++) {
            imageView = new ImageView(getContext());
            imageView.setLayoutParams(lp);
            imageView.setImageResource(R.drawable.select_point_bg);
            pointLayout.addView(imageView);
        }
        switchToPoint(0);
    }
    //切换指示器
    private void switchToPoint(int currentPoint) {
        for (int i = 0; i < pointLayout.getChildCount(); i++) {
            pointLayout.getChildAt(i).setEnabled(false);
        }
        pointLayout.getChildAt(currentPoint).setEnabled(true);
    }
    //返回真实的位置
    private int toRealPosition(int position) {
        int realPosition;
        if (imageUrls.size() > 0) {
            realPosition = (position - 1) % imageUrls.size();
            if (realPosition < 0)
                realPosition += imageUrls.size();
        }else{
            realPosition = 0;
        }
        return realPosition;
    }
    public void setAutoPlay(boolean autoPlay) {
        isAutoPlay = autoPlay;
    }
    public void setOnBannerItemClick(OnBannerItemClick onBannerItemClick) {
        this.onBannerItemClick = onBannerItemClick;
    }
    //添加监听事件回调
    public interface OnBannerItemClick{
        void onItemClick(int position);
    }
}

调用方式

        //设置是否自动播放
        bannerView.setAutoPlay(true);
        //添加网络图片
        bannerView.setImageUrls(data);
        //banner的点击事件
        bannerView.setOnBannerItemClick(new BannerView.OnBannerItemClick() {
            @Override
            public void onItemClick(int position) {
                Toast.makeText(MainActivity.this,"图片" + position,Toast.LENGTH_LONG).show();
            }
        });

代码分析

这里我只考虑了使用网络图片进行展示,使用本地图片原理是一样的,在里面多加个方法即可。此效果代码不是很复杂,通俗易懂。唯一值得一说的是我在实现viewpager无限滑动时采用的是return imageUrls.size() + 2的方法。这里我们添加两条数据分别为第一条和最后一条。第一条代表着最后一张图片而最后一条则代表着第一张图片,这里手动画个图:

通过此图我们应该不难发现,当我们滑动到第二个0的时候则跳转到第一个0,滑动到第一个2的时候则跳转到第二个2。这里0代表第一张图片,2代表第二张图片。这样就可以实现无限滑动的效果了,可能有些人会觉得这样做有些复杂还要判断真实的位置不如直接将getConut()返回一个最大值然后取其中间值即可。但这样做其实代码性能并不是很高。

结束

这样一个常用的banner就写好了,当我们需要实现一些滑动动画的时候,可以在里面实现viewpager的动画属性即可。先从简单的入手,慢慢的就可以了解更多的原理和知识点,哈哈!这里贴出传送门以便参考。

到此这篇关于Android封装Banner控件方法介绍的文章就介绍到这了,更多相关Android封装Banner内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android自定义封装banner组件

    自定义封装 banner 组件,供大家参考,具体内容如下 1. 效果图预览  2.基本功能 一个简单方便的轮播图组件,基于viewpager 基础上进行的封装. 可设置 项目中图片,网络图片, View: 支持循环自动播放,手势滑动切换,item点击事件,可设置 点点的样式宽高.颜色.大小.位置 : 可设置蒙层:可设置 是否允许滑动:可设置 是否允许循环. 3.基本实现 1). 自定义属性 <declare-styleable name="BannerLayoutStyle"&g

  • Android BannerView通用封装详解

    之前封装过一个,但总觉得不够优雅,就有了这个通用封装,很简洁,不知道够不够优雅,不过原来那个有跟随指示器和丝滑滑动效果,感兴趣可以看一下. 封装过程 1.自定义属性 selectPoint:选中指示器图标 normalPoint:未选中指示器图标 pointWidth:图标宽度 switchTime:轮播间隔事件 location:指示器位置,下中或下右 <declare-styleable name="NewBannerView"> <attr name="

  • Android ListView列表控件的介绍和性能优化

    ListView列表控件 一.ListView显示数据的原理:mvc模式 m:mode 数据(用javabean规范封装) v:view ListView c:adapter 适配器,负责把数据展示到ListView上 二.ListView最常用适配器 BaseAdapter.SimpleAdapter.ArrayAdapter 三.ListView显示数据的步骤 1.创建ListView 2.自定义ListView的适配器继承BaseAdapter,重写baseAdapter的getCount

  • Android ListView 子控件onClick正确获取position的方法

    在实际开发中,我们有时候不仅需要响应ListView的onItemClick,还需要响应其子控件的点击事件,这个时候我们就会 发现,由于复用等原因,如果直接在子控件的onClick事件中调用getView()中的position,会出现数据或显示错位的问 题,原因就是position的值出现了重复或不准确,解决这个问题的方法是,在adapter每次加载数据的时候,为需要点击 的控件设置一个tag值,这个tag值就设置为当前这个控件对应的position,然后在点击事件中gettag(),获取这个

  • Android中获取控件宽高的4种方法集合

    借鉴自开发艺术 1.onWindowFocusChanged 这个方法会被调用多次,在View初始化完毕后会调用,当Activity的窗口得到焦点和失去焦点都会被调用一次(Activity继续执行和暂停执行时). @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { int width = view.getMeasur

  • Android TextView文本控件介绍

    目录 讲解 基础属性介绍 后台调用 总结 讲解 TextView作为Android最基础也是最常用的组件之一,他承担着文本的显示重任.要注意,其显示的文本内容是无法在界面直接被用户修改的.不过作为程序员,可以通过后台代码去修改TextView的内容和各项属性.另外要注意的是,TextView控件是需要放在容器里面的,比如LinearLayout容器(一般控件都要放在容器里面). 基础属性介绍 属性 说明 id 设置一个组件id(唯一),通过findViewById()的方法获取到该对象,然后进行

  • Android SearchView搜索控件使用方法详解

    本文实例为大家分享了Android SearchView搜索控件的具体实现代码,供大家参考,具体内容如下 方法介绍 setQueryHint 设置 Hint 的文字内容 setMaxWidth 设置搜索框的最大宽度 setSubmitButtonEnabled 是否显示提交按钮,默认是false setIconified 搜索框是否展开,false表示展开 setIconifiedByDefault 是否锁定搜索框为展开状态,false表示锁定(放大镜在搜索框外) onActionViewExp

  • Android编程之控件ListView使用方法

    本文实例讲述了Android编程之控件ListView使用方法.分享给大家供大家参考.具体分析如下: 控件ListView是一个重要的控件,可以被用作用户列表等显示,下面进行它的操作测试. 下面代码实现了生成了一个ListView显示,并对每个条目的单击事件作出响应. 源代码: package com.list; import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import an

  • Android实现EditText控件禁止输入内容的方法(附测试demo)

    本文实例讲述了Android实现EditText控件禁止输入内容的方法.分享给大家供大家参考,具体如下: 问题: android如何实现EditText控件禁止往里面输入内容? 修改版解决方法: EditText editText = (EditText) findViewById(R.id.editText1); editText.setKeyListener(null); 看到这个问题大家可能有点奇怪了,EditText的功能不就是往上面写入内容吗? 再者,如果真要禁止输入文本,在布局文件中

  • Android编程获取控件宽和高的方法总结分析

    本文总结分析了Android编程获取控件宽和高的方法.分享给大家供大家参考,具体如下: 我们都知道在onCreate()里面获取控件的高度是0,这是为什么呢?我们来看一下示例: 首先我们自己写一个控件,这个控件非常简单: public class MyImageView extends ImageView { public MyImageView(Context context, AttributeSet attrs) { super(context, attrs); } public MyIm

  • Android编程之控件可拖动的实现方法

    本文实例讲述了Android编程之控件可拖动的实现方法.分享给大家供大家参考,具体如下: 点击和触摸的区别是什么? 点击: 一组动作的集合 手指按下着按钮 手指要在按钮停留一段时间 手指离开按钮 private static final String TAG = "DragViewActivity"; private ImageView iv_dv_view; private TextView tv_drag_view; private int startx; private int

  • Android ListView里控件添加监听方法的实例详解

    Android ListView里控件添加监听方法的实例详解 关于ListView,算是android中比较常见的控件,在ListView我们通常需要一个模板,这个模板指的不是住模块,而是配置显示在ListView里面的东西,今天做项目的时候发现想要添加一个ImageView监听方法,发现崩了,也许是好久没有动ListView竟然忘了不能直接在主UI的xml文件里面调用其他xml文件的控件,哪怕ListView用的是这个xml文件. [错误示范]: 直接调用ImageView这个控件是ListV

随机推荐