<android>自定义banner 带标题及扁圆Indicator 轮播效果 及手势等处理

                       自定义banner 带标题及扁圆Indicator 轮播效果 及手势等处理 


先上图:

                                                     

分析:这里我们用viewpager来实现,圆角效果用cardview来包裹,小圆点用画笔绘制,加上动画就搞定。

第一步:

重写viewpager(AutoScrollViewPager类):

public class AutoScrollViewPager extends ViewPager {
    private static final String TAG = "AutoScrollViewPager";
    private AutoScrollHandler autoScrollHandler;
    private Context mContext;
    private int change_anmin;
    private int change_duration;
    int speed = 500; //默认移动速度
    private int indexCount;
    private float mXp;
    private float mYp;
    FixedSpeedScroller mScroller = null;

    public AutoScrollViewPager(@NonNull Context context) {
        this(context, null);
        mContext = context;
    }

    public AutoScrollViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.BannerIndicator);
        change_anmin = array.getInteger(R.styleable.AutoScrollViewPager_change_anmin, 1);
        change_duration = array.getInteger(R.styleable.AutoScrollViewPager_change_duration, 5000);
        autoScrollHandler = new AutoScrollHandler(this, change_duration);
        controlViewPagerSpeed();
        setPageMargin(20);
    }

    public AutoScrollViewPager(@NonNull Context context, @Nullable AttributeSet attrs, Context mContext) {
        super(context, attrs);
        this.mContext = mContext;
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.BannerIndicator);
        change_anmin = array.getInteger(R.styleable.AutoScrollViewPager_change_anmin, 1);
        change_duration = array.getInteger(R.styleable.AutoScrollViewPager_change_duration, 5);
        autoScrollHandler = new AutoScrollHandler(this, change_duration);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        /**
         * 根据getAdapter获取外部传递的size是多少,如果为1则不允许移动 只允许点击
         * 否则允许滑动和点击切按住时通知轮播,放开时启动轮播
         */
        if (indexCount == 1) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mXp = ev.getX();
                    mYp = ev.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    return false;

                case MotionEvent.ACTION_UP:
                    return super.dispatchTouchEvent(ev);
            }
            return super.dispatchTouchEvent(ev);

        } else {
            int action = ev.getAction();
            if (action == ACTION_UP || action == ACTION_CANCEL || action == ACTION_OUTSIDE) {
                startAutoPlay();
            } else if (action == ACTION_DOWN) {
                stopAutoPlay();
            }
            return super.dispatchTouchEvent(ev);
        }
    }

    /**
     * 开启轮播 同时获取count
     */
    public void startAutoPlay() {
        if (autoScrollHandler != null) {
            stopAutoPlay();
            autoScrollHandler.start();
        }

        ViewPagerAdapter adapter = (ViewPagerAdapter) getAdapter();
        assert adapter != null;
        indexCount = adapter.ssss();
    }

    /**
     * 停止轮播 同时获取count
     */
    public void stopAutoPlay() {
        if (autoScrollHandler != null) {
            autoScrollHandler.stop();
            autoScrollHandler.removeCallbacksAndMessages(null);
        }
        ViewPagerAdapter adapter = (ViewPagerAdapter) getAdapter();
        assert adapter != null;
        indexCount = adapter.ssss();
    }

    // 传递速度值
    public void setSpeed(int speed) {
        this.speed = speed;
    }


    /**
     * 修改vp移动速度
     */
    private void controlViewPagerSpeed() {
        try {
            Field mField;
            mField = ViewPager.class.getDeclaredField("mScroller");
            mField.setAccessible(true);
            mScroller = new FixedSpeedScroller(mContext, new AccelerateInterpolator());
            mScroller.setmDuration(speed); // 2000ms
            mField.set(this, mScroller);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

改变vp移动速度继承scroller的重写:

public class FixedSpeedScroller extends Scroller {
    private int mDuration = 1000;

    public FixedSpeedScroller(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    public FixedSpeedScroller(Context context, Interpolator interpolator) {
        super(context, interpolator);
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        // Ignore received duration, use fixed one instead
        super.startScroll(startX, startY, dx, dy, mDuration);
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy) {
        // Ignore received duration, use fixed one instead
        super.startScroll(startX, startY, dx, dy, mDuration);
    }

    public void setmDuration(int time) {
        mDuration = time;
    }

    public int getmDuration() {
        return mDuration;
    }
}

第二步 构建Handler定时器(AutoScrollHandler类):

public class AutoScrollHandler extends Handler {
    private static final String TAG = "AutoScrollHandler";
    private WeakReference<AutoScrollViewPager> mBannerRef;
    private static final int MSG_CHANGE_SELECTION = 1;
    private static int AUTO_SCROLL_TIME = 0;

    public AutoScrollHandler(AutoScrollViewPager autoScrollViewPager, int change_duration) {
        mBannerRef = new WeakReference<>(autoScrollViewPager);
        AUTO_SCROLL_TIME = change_duration;
    }


    public void start() {
        removeMessages(MSG_CHANGE_SELECTION);
        sendEmptyMessageDelayed(MSG_CHANGE_SELECTION, AUTO_SCROLL_TIME);
    }

    public void stop() {
        removeMessages(MSG_CHANGE_SELECTION);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if (msg.what == MSG_CHANGE_SELECTION) {
            if (mBannerRef == null || mBannerRef.get() == null) {
                return;
            }
            AutoScrollViewPager banner = mBannerRef.get();
            int current = banner.getCurrentItem();
/*            if (current == banner.getAdapter().getCount() - 1)
                current = -1;*/
            banner.setCurrentItem(current + 1);
            sendEmptyMessageDelayed(MSG_CHANGE_SELECTION, AUTO_SCROLL_TIME);
        }
    }

}

第三步:绘制indicator(BannerItemView类)

ublic class BannerItemView extends View {
    private static final String TAG = "BannerItemView";
    private Paint mPaint;
    private float rectWidth;
    private RectF rectF;
    public static final int CENTER = 0;
    public static final int LEFT = 1;
    public static final int RIGHT = 2;
    private int loaction = CENTER;

    public BannerItemView(Context context) {
        this(context, null);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        rectF = new RectF();
        mPaint.setColor(Color.RED);
    }

    public BannerItemView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        rectF = new RectF();
        mPaint.setColor(Color.RED);
    }

    public BannerItemView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        rectF = new RectF();
        mPaint.setColor(Color.RED);
    }

    public BannerItemView(Context context, int loaction) {
        this(context);
        this.loaction = loaction;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        switch (loaction) {
            case CENTER:
                rectF.left = getWidth() / 2 - getHeight() / 2 - rectWidth;
                rectF.right = getHeight() / 2 + getWidth() / 2 + rectWidth;
                rectF.top = 0;
                rectF.bottom = getHeight();
                break;
            case LEFT:
                rectF.left = getWidth() - getHeight() - rectWidth;
                rectF.right = getWidth();
                rectF.top = 0;
                rectF.bottom = getHeight();
                break;
            case RIGHT:
                rectF.left = 0;
                rectF.right = getHeight() - rectWidth;
                rectF.top = 0;
                rectF.bottom = getHeight();
                break;
        }
        canvas.drawRoundRect(rectF, getHeight() / 2, getHeight() / 2, mPaint);
    }

    public float getRectWidth() {
        return rectWidth;
    }


    public void setColor(int color) {

        mPaint.setColor(color);
    }

    public void setRectWidth(float rectWidth) {
        this.rectWidth = rectWidth;

        invalidate();
    }

    public int getLoaction() {
        return loaction;
    }

    public void setLoaction(int loaction) {
        this.loaction = loaction;
    }
}

第四步:将绘制的Indicator加入布局(BannerIndicator类)

public class BannerIndicator extends LinearLayout {
    private static final String TAG = "BannerIndicator";

    private int dashGap;
    private int position;
    private ViewPager viewPager;
    private int slider_width;
    private int slider_height;
    private int sliderAlign;
    private int current_color;
    private int pasted_color;
    private int change_speech = 200;
    private List<GetTopBannerBena.ResultBean.DataBean.ListBean.BannerBean> drawableList;

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

    public BannerIndicator(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BannerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setOrientation(HORIZONTAL);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.BannerIndicator);
        dashGap = (int) array.getDimension(R.styleable.BannerIndicator_gap, 3);
        slider_width = (int) array.getDimension(R.styleable.BannerIndicator_slider_width, 12);
        slider_height = (int) array.getDimension(R.styleable.BannerIndicator_slider_height, 4);
        sliderAlign = array.getInt(R.styleable.BannerIndicator_slider_align, 1);

        current_color = array.getColor(R.styleable.BannerIndicator_current_color, Color.RED); //当前颜色
        pasted_color = array.getColor(R.styleable.BannerIndicator_pasted_color, Color.BLACK); //过去亚颜色
        change_speech = array.getInt(R.styleable.BannerIndicator_change_speech, 200); //动画时间

        array.recycle();
    }


    public void setUpWidthViewPager(final ViewPager viewPager, final List<GetTopBannerBena.ResultBean.DataBean.ListBean.BannerBean> drawableList1) {

        drawableList = new ArrayList<>();
        if (this.drawableList != null && drawableList.size() != 0)
            this.drawableList.clear();
        this.drawableList.addAll(drawableList1);

        removeAllViews();
        if (viewPager == null || viewPager.getAdapter() == null)
            return;
        position = 0;
        this.viewPager = viewPager;
        for (int i = 0; i < drawableList.size(); i++) {
            BannerItemView imageView = new BannerItemView(getContext(), sliderAlign);
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(slider_width, slider_height);
            if (i > 0) {
                layoutParams.setMargins(dashGap, 0, 0, 0);
                imageView.setAlpha(0.4f);
            } else {
                layoutParams.setMargins(0, 0, 0, 0);
                imageView.setAlpha(1);
            }
            imageView.setLayoutParams(layoutParams);
            addView(imageView);
            setLarge(0);
        }
        viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {

                try {
                    if (BannerIndicator.this.position != position % drawableList.size()) {
                        resetSize(BannerIndicator.this.position, position % drawableList.size());
                        BannerIndicator.this.position = position % drawableList.size();
                    }
                } catch (Exception e) {

                }

            }
        });
    }

    private void resetSize(int position, int current) {
        setLarge(current);
        setSmall(position);
    }


    //指示器增大同时设置透明度变化
    private void setLarge(int position) {
        if (getChildAt(position) instanceof BannerItemView) {
            AnimatorSet set = new AnimatorSet();
            ValueAnimator animator = getEnlarge((BannerItemView) getChildAt(position));
            ValueAnimator alpha = ObjectAnimator.ofFloat(getChildAt(position), "alpha", 1f, 1f);
            set.play(animator).with(alpha);
            set.setDuration(change_speech);
            set.start();

            try {
                for (int i = 0; i < drawableList.size(); i++) {
                    if (position == i) {
                        BannerItemView childAt = (BannerItemView) getChildAt(i);
                        childAt.setColor(current_color);
                    } else {
                        BannerItemView childAt = (BannerItemView) getChildAt(i);
                        childAt.setColor(pasted_color);
                    }
                }

            } catch (Exception e) {

            }

        }
    }


    //放大动画
    private ValueAnimator getEnlarge(BannerItemView roundRectView) {
        return ObjectAnimator.ofFloat(roundRectView,
                "rectWidth",
                0, getOffset(roundRectView));
    }

    //根据大小变化方向获取指示器大小偏移量
    private int getOffset(BannerItemView bannerItemView) {
        int offsest = 0;
        switch (bannerItemView.getLoaction()) {
            case BannerItemView.CENTER:
                offsest = (slider_width - slider_height) / 2;
                break;
            case BannerItemView.LEFT:
                offsest = slider_width - slider_height;
                break;
            case BannerItemView.RIGHT:
                offsest = slider_width - slider_height;
                break;
        }
        return offsest;
    }

    //缩小动画
    private ValueAnimator getShrink(BannerItemView roundRectView) {
        return ObjectAnimator.ofFloat(roundRectView,
                "rectWidth",
                getOffset(roundRectView), 0);
    }

    //缩小动画同事伴随透明度变化
    public void setSmall(int small) {
        if (getChildAt(small) instanceof BannerItemView) {
            AnimatorSet set = new AnimatorSet();
            ValueAnimator alpha = ObjectAnimator.ofFloat(getChildAt(position), "alpha", 1, 0.4f);
            ValueAnimator animator = getShrink((BannerItemView) getChildAt(small));
            set.play(animator).with(alpha);
            set.setDuration(618);
            set.start();
        }
    }
}

第五步: viewpager的适配器(ViewPagerAdapter类)

public class ViewPagerAdapter extends PagerAdapter {
    private Context mContext;
    private List<View> mCache;
    List<View> views = new ArrayList<>();
    private List<GetTopBannerBena.ResultBean.DataBean.ListBean.BannerBean> drawableList;
    private final RequestOptions optionss;

    public ViewPagerAdapter(List<GetTopBannerBena.ResultBean.DataBean.ListBean.BannerBean> list, Context context) {
        drawableList = new ArrayList<>();
        optionss = new RequestOptions();
        optionss.placeholder(R.mipmap.pre_img);//图片加载出来前,显示的图片
        optionss.fallback(R.mipmap.pre_img); //url为空的时候,显示的图片
        optionss.error(R.mipmap.pre_img);//图片加载失败后,显示的图片

        if (drawableList.size() != 0)
            drawableList.clear();

        drawableList.addAll(list);
        mContext = context;
        mCache = new ArrayList<>();
        for (int i = 0; i < drawableList.size(); i++) {
            ImageView imageView = new ImageView(mContext);
            Glide.with(mContext).load(drawableList.get(i).getPic()).apply(optionss).into(imageView);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            views.add(imageView);
        }
    }

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

    @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, final int position) {
        if (drawableList != null && drawableList.size() > 0) {
            View imageView = null;
            if (mCache.isEmpty()) {
                imageView = View.inflate(container.getContext(), R.layout.item_imagess, null);
            } else {
                imageView = mCache.remove(0);
            }
            ImageView xxximg_ = (ImageView) imageView.findViewById(R.id.xxximg_);
            TextView show_tv_show = (TextView) imageView.findViewById(R.id.show_tv_show);
            Glide.with(mContext).load(drawableList.get(position % drawableList.size()).getPic()).into(xxximg_);
            show_tv_show.setText(drawableList.get(position % drawableList.size()).getB_name() + "");
            xxximg_.setScaleType(ImageView.ScaleType.FIT_XY);
            container.addView(imageView);
            final View finalImageView = imageView;
            imageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    try {

                        bannerListener.ItemClick(position % drawableList.size(), drawableList.get(position % drawableList.size()));

                    } catch (Exception e) {

                    }
                }
            });
            return imageView;
        }

        return null;
    }


    /**
     * 页面宽度所占ViewPager测量宽度的权重比例,默认为1
     */
    @Override
    public float getPageWidth(int position) {
        return (float) 1;
    }


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

    BannerListener bannerListener = null;

    public void setItemClickListener(BannerListener bannerListener) {
        this.bannerListener = bannerListener;
    }


    public interface BannerListener {
        void ItemClick(int postion, GetTopBannerBena.ResultBean.DataBean.ListBean.BannerBean data);
    }


    public int ssss(){
        return drawableList.size();
    }

}

收尾:用法

xml中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff"
    android:orientation="vertical">


    <android.support.v7.widget.CardView
        android:id="@+id/sdsdsds"
        android:layout_width="match_parent"
        android:layout_height="145dp"
        android:layout_below="@+id/app_oneword"
        android:layout_marginBottom="10dp"
        android:layout_marginLeft="12dp"
        android:layout_marginRight="12dp"
        android:layout_marginTop="5dp"
        app:cardCornerRadius="4dp"
        app:cardElevation="2dp">


        <com.watcn.wat.view.banner.AutoScrollViewPager
            android:id="@+id/auto_scroll_viewpager"
            android:layout_width="match_parent"
            android:layout_height="145dp"
            android:clipChildren="false"
            app:change_duration="200" />


        <TextView
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_gravity="bottom"
            android:background="#33000000"
            android:gravity="left|center"
            android:paddingBottom="5dp"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:paddingTop="5dp"
            android:text="这个夏季爆品星巴克、喜茶、一点点都在推,为什么你不能卖?"
            android:textColor="#ffffff"
            android:textSize="16sp"
            android:visibility="gone" />


    </android.support.v7.widget.CardView>


    <com.watcn.wat.view.banner.BannerIndicator
        android:id="@+id/indicator"
        android:layout_width="match_parent"
        android:layout_height="17dp"
        android:gravity="center"
        app:change_speech="800"
        app:current_color="#E60012"
        app:pasted_color="#D8D8D8"
        app:slider_align="Center"
        app:slider_height="6dp"
        app:slider_width="10dp" />


</LinearLayout>


java代码中:

ViewPagerAdapter pagerAdapter = new ViewPagerAdapter(topBannerList, getActivity());
autoScrollViewPager.setAdapter(pagerAdapter);
bannerIndicator.setUpWidthViewPager(autoScrollViewPager, topBannerList);
if (topBannerList.size() == 1) {
    autoScrollViewPager.stopAutoPlay();
} else {
    autoScrollViewPager.startAutoPlay();
}
pagerAdapter.setItemClickListener(new ViewPagerAdapter.BannerListener() {
    @Override
    public void ItemClick(int postion, GetTopBannerBena.ResultBean.DataBean.ListBean.BannerBean bannerDatas) {
   
   

});

结束:如果需要切换动画:可以实现ViewPager.PageTransformer接口 如下

public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = 1f;
    private static final float MIN_ALPHA = 1f;

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        int pageHeight = view.getHeight();

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);

        } else if (position <= 1) { // [-1,1]
            // Modify the default slide transition to shrink the page as well
            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
            if (position < 0) {
                view.setTranslationX(horzMargin - vertMargin / 2);
            } else {
                view.setTranslationX(-horzMargin + vertMargin / 2);
            }

            // Scale the page down (between MIN_SCALE and 1)
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

            // Fade the page relative to its size.
            view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));



        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/csdn_lg_one/article/details/91041344
今日推荐