Android 自定义轮播图

Posted 吹着空调哼着歌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 自定义轮播图相关的知识,希望对你有一定的参考价值。

android 自定义轮播图

定义Banner

主要使用ViewPager实现滑动

public class Banner extends FrameLayout 
    public Context context;
    private @LayoutRes
    int layoutId = R.layout.banner_view;
    private View inflate;
    private ViewPager pager;
    private AutoHandler mHandler;
    private PagerAdapter adapter;
    public IndicatorView indicatorView;

    public Banner(@NonNull Context context) 
        this(context, null);
    

    public Banner(@NonNull Context context, @Nullable AttributeSet attrs) 
        this(context, attrs, -1);
    

    public Banner(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    

    public void setAdapter(PagerAdapter adapter) 
        this.adapter = adapter;
        pager.setAdapter(adapter);
        indicatorView.setPager(pager);
    

    private void init(Context context, AttributeSet attrs, int defStyleAttr) 
        this.context = context;
        inflate = LayoutInflater.from(context).inflate(layoutId, this, true);
        pager = inflate.findViewById(R.id.banner_pager);
        indicatorView = inflate.findViewById(R.id.indicatorView);

        mHandler = new AutoHandler(pager);

        mHandler.start();

    

    public abstract static class BannerAdapter extends PagerAdapter 
        private List list;
        private Context context;

        public BannerAdapter(List list, Context context) 
            this.list = list;
            this.context = context;
        

        @Override
        public int getCount() 
            if (null == list || list.size() == 0) 
                return 1;
             else 
                return list.size();
            
        

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

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) 
            if (getLayout() > 0) 
                View inflate = LayoutInflater.from(context).inflate(getLayout(), container, false);
                container.addView(inflate);
                setView(inflate, position);
                return inflate;
             else 
                ImageView imageView = new ImageView(context);
                container.addView(imageView);
                if (list.size() > 0) 
                    Glide.with(context).load(list.get(position))
                            .apply(new RequestOptions().centerCrop())
                            .into(imageView);
                 else 
//                    Glide.with(context)
//                            .load(R.mipmap.ic_launcher)
//                            .apply(new RequestOptions().centerCrop())
//                            .into(imageView);
                    imageView.setBackgroundResource(R.mipmap.ic_launcher);
                
                return imageView;
            

        

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

        protected abstract void setView(View inflate, int position);

        protected abstract int getLayout();

    




定义定时器Handler

主要处理ViewPager的滚动 开启定时任务 ViewPager自动滚动


public class AutoHandler extends Handler 
    private ViewPager pager;
    public static int TIME = 1000 * 2;
    public boolean stopHandler;

    public AutoHandler(ViewPager pager) 
        this.pager = pager;
    

    @Override
    public void handleMessage(@NonNull Message msg) 
        super.handleMessage(msg);
        switch (msg.what) 
            case 100:
                if (!stopHandler) 

                    sendEmptyMessageDelayed(100, TIME);

                    int position = pager.getCurrentItem() + 1;

                    if (position >= pager.getAdapter().getCount()) 
                        position = 0;
                    
                    pager.setCurrentItem(position);

                 else 
                    removeMessages(100);
                
                break;
            default:
                removeMessages(100);
                break;
        
    

    public void start() 
        stopHandler = false;
        if (!hasMessages(100)) 
            sendEmptyMessageDelayed(100, TIME);
        
    

    public void stop() 
        stopHandler = true;
        if (hasMessages(100)) 
            removeMessages(100);
        
    



绘制一个下标指示器

主要根据需求自行绘制 可有可无 和ViewPager关联在一起 实现联动


public class IndicatorView extends View 
    private Context context;
    private ValueAnimator valueAnimator;
    private float value;
    public int indiWidth;
    public int indiHeight;
    public int indiDivide;
    //0圆角   1直角
    public int mode;
    private int normalColor;
    private int selectColor;
    private int curPosition;
    private int count;
    private Paint paint;
    private int width;
    private int height;
    private double lastPosition;
    private ViewPager pager;
    private PagerAdapter adapter;
    private DataSetObserver dataSetObserver;

    public void setPager(final ViewPager pager) 
        this.pager = pager;
        this.adapter = pager.getAdapter();
        dataSetObserver = new DataSetObserver() 
            @Override
            public void onChanged() 
                super.onChanged();
                setCount(adapter.getCount());
                setCurPosition(pager.getCurrentItem());
            
        ;
        if (null != adapter) 
            setCount(adapter.getCount());
            setCurPosition(pager.getCurrentItem());
            adapter.registerDataSetObserver(dataSetObserver);
        

        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() 
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 
                lastPosition = position;
            

            @Override
            public void onPageSelected(int position) 
                curPosition = position;
                setCurPosition(position);
            

            @Override
            public void onPageScrollStateChanged(int state) 

            
        );

        pager.addOnAdapterChangeListener(new ViewPager.OnAdapterChangeListener() 
            @Override
            public void onAdapterChanged(@NonNull ViewPager viewPager, @Nullable PagerAdapter oldAdapter, @Nullable PagerAdapter newAdapter) 
                if (oldAdapter != newAdapter) 
                    adapter = newAdapter;
                    setCount(adapter.getCount());
                    setCurPosition(viewPager.getCurrentItem());
                
            
        );
    

    public void setCount(int count) 
        this.count = count;
        if (count <= 1) 
            setVisibility(INVISIBLE);
        
        requestLayout();
        postInvalidate();
    

    public void setCurPosition(int curPos) 
        /*记录上次记录*/
        //lastPos = this.curPos;
        this.curPosition = curPos;
        //postInvalidate();
        valueAnimator.start();
    


    public IndicatorView(Context context) 
        this(context, null);
    

    public IndicatorView(Context context, @Nullable AttributeSet attrs) 
        this(context, attrs, -1);
    

    public IndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    

    private void init(Context context, AttributeSet attrs, int defStyleAttr) 
        this.context = context;
        valueAnimator = ValueAnimator.ofFloat(0, 1f);
        valueAnimator.setDuration(200);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() 
            @Override
            public void onAnimationUpdate(ValueAnimator animation) 
                value = (float) animation.getAnimatedValue();
                postInvalidate();
            
        );

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.IndicatorView);

        indiHeight = (int) typedArray.getDimension(R.styleable.IndicatorView_indi_height, getResources().getDimension(R.dimen.dp4));
        indiWidth = (int) typedArray.getDimension(R.styleable.IndicatorView_indi_width, getResources().getDimension(R.dimen.dp4));

        indiDivide = (int) typedArray.getDimension(R.styleable.IndicatorView_indi_divier, getResources().getDimension(R.dimen.dp4));

        normalColor = typedArray.getColor(R.styleable.IndicatorView_indi_color, Color.parseColor("#66dddddd"));
        selectColor = typedArray.getColor(R.styleable.IndicatorView_indi_color_select, Color.parseColor("#eedddddd"));

        mode = typedArray.getInteger(R.styleable.IndicatorView_indi_mode, 0);

        curPosition = 0;
        count = 0;

        paint = new Paint();
        paint.setAntiAlias(true);

        paint.setColor(normalColor);

    

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        width = indiWidth * count + (count - 1) * indiDivide;//每个的宽度加上中间间距的宽度
        height = indiHeight;

        setMeasuredDimension(width, height);
    

    @Override
    protected void onDraw(Canvas canvas) 
        super.onDraw(canvas);

        for (int i = 0; i < count; i++) 
            int x = i * (indiDivide + indiWidth);

            if (mode == 0) 
                paint.setColor(normalColor);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
                    canvas.drawRoundRect(x, 0, x + indiWidth, indiHeight, indiHeight / 2, indiHeight / 2, paint);
                

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
                    if (curPosition == i) 
                        paint.setColor(selectColor);
                        if (curPosition > lastPosition) 
                            canvas.drawRoundRect(x, 0, x + value * indiWidth, indiHeight, indiHeight / 2, indiHeight / 2, paint);
                         else 
                            canvas.drawRoundRect(x + (1 - value) * indiWidth, 0, x + indiWidth, indiHeight, indiHeight / 2, indiHeight / 2, paint);
                        
                    

                

                if (mode == 1) 
                    paint.setColor(normalColor);
                    canvas.drawRect(x, 0, x + indiWidth, indiHeight, paint);


                    if (curPosition == i) 
                        paint.setColor(selectColor);

                        if (curPosition > lastPosition) 
                            canvas.drawRect(x, 0, x + value * indiWidth, indiHeight, paint);
                         else 
                            canvas.drawRect(x + (1 - value) * indiWidth, 0, x + indiWidth, indiHeight, paint);
                        
                    

                
            
        
    


在Activity中使用

banner.setAdapter(new Banner.BannerAdapter(strings, this) 
            @Override
            protected void setView(View inflate, int position) 
                ImageView img = inflate.findViewById(R.id.img);
                Glide.with(MainActivity.this).load(strings.get(position))
                        .

以上是关于Android 自定义轮播图的主要内容,如果未能解决你的问题,请参考以下文章

Android自定义控件6--轮播图广告的实现

Android自定义控件5--轮播图广告ViewPager基本实现

Android 使用ViewPager和自定义PagerAdapter实现轮播图效果

Android轮播图封装,下拉刷新相结合

Android侧滑菜单和轮播图之滑动冲突

Android ViewPager+轮播图