美文网首页
动态轮播图,banner切换动画效果

动态轮播图,banner切换动画效果

作者: Db_z | 来源:发表于2019-11-11 17:30 被阅读0次

    轮播图 可以实现动图gif 滑动切换动态效果展示, 一个自定义的飘落雪花的功能,(让我用来实现下红包雨的功能了)

    废话不多说  直接 上图   
    
    image image.gif ​ image image.gif

    上面轮播图 可以切换滑动效果, 有很多种滑动,自己去试吧(可能在处理滑动的时候没有考虑动图优化, 有点小卡顿, 如果有兴趣就自己看看源码)

    下面是切换滑动特效

    private void switchAnimation() {
            try {
                if (!mPresenter.getTransformerData().isEmpty()) {
                    if (mPresenter.getTransformerData().size() == index) {
                        index = 0;
                    }
                    mTransforemerName = mPresenter.getTransformerData().get(index);
                    Class cls = Class.forName("com.ToxicBakery.viewpager.transforms." + mTransforemerName);
                    mTransforemer = (ABaseTransformer) cls.newInstance();
                    mBanner.setPageTransformer(mTransforemer);
                    mBanner.getViewPager().setPageTransformer(true, mTransforemer);
                    //部分3D特效需要调整滑动速度
                    if (mTransforemerName.equals("StackTransformer")) {
                        mBanner.setScrollDuration(1200);
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    
    image.gif
    然后是设置banner数据
    
    @Override
        public void refreshData(List<String> data) {
            if (!mPresenter.isDataMissing()) return;
            switchAnimation();
            mBanner.setPages(new CBViewHolderCreator<ViewHolder>() {
                @Override
                public ViewHolder createHolder() {
                    return new ViewHolder();
                }
            }, data).setPageIndicator(new int[]{R.drawable.ic_page_indicator, R.drawable.ic_page_indicator_focused})
                    .setPageIndicatorAlign(ConvenientBanner.PageIndicatorAlign.ALIGN_PARENT_RIGHT)
                    .setPageTransformer(mTransforemer)
                    .startTurning(3000);
        }
    
    image.gif

    还有个实现类ViewHolder 需要实现Holder

    public class ViewHolder implements Holder<String> {
    
        private GifImageView imageView;
    
        @Override
        public View createView(Context context) {
            imageView = new GifImageView(context);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            return imageView;
        }
    
        @Override
        public void UpdateUI(Context context, int position, String data) {
            if (data.length() > 3) {
                if (data.substring(data.length() - 3).equals("gif")) {
                    try {
                        byte[] bytes = new GifDataAsyncTask().execute(data).get();
                        imageView.setBytes(bytes);
                        imageView.startAnimation();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    Picasso.with(context).load(data).into(imageView);
                }
            }
        }
    }
    
    
    image.gif

    以上基本就是轮播图了, 还算是比较简单

    下面说一下 下红包雨的功能

    两种实现方式, 都是自定义类

    一种继承 SurfaceView 实现 SurfaceHolder.Callback 方法

    public class Snow extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private SnowFlake[]   mFlakes;
        private int           mViewWidth  = 200;
        private int           mViewHeight = 100;
        private int           mFlakeCount = 20;
        private int           mMinSize    = 50;
        private int           mMaxSize    = 70;
        private int           mSpeedX     = 10;
        private int           mSpeedY     = 20;
        private Bitmap mSnowBitmap = null;
        private boolean       mStart      = false;
    
        public Snow(Context context) {
            this(context, null);
        }
    
        public Snow(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public Snow(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initHolder();
            setZOrderOnTop(true);
    
            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.Snow, defStyleAttr, 0);
            int cnt = array.getIndexCount();
            for (int i = 0; i < cnt; i++) {
                int attr = array.getIndex(i);
                switch (attr) {
                case R.styleable.Snow_flakeCount:
                    mFlakeCount = array.getInteger(attr, 0);
                    break;
                case R.styleable.Snow_minSize:
                    mMinSize = array.getInteger(attr, 50);
                    break;
                case R.styleable.Snow_maxSize:
                    mMaxSize = array.getInteger(attr, 70);
                    break;
                case R.styleable.Snow_flakeSrc:
                    Integer srcId = array.getResourceId(attr, R.drawable.snow_flake);
                    mSnowBitmap   = BitmapFactory.decodeResource(getResources(), srcId);
                    break;
                case R.styleable.Snow_speedX:
                    mSpeedX = array.getInteger(attr, 10);
                    break;
                case R.styleable.Snow_speedY:
                    mSpeedY = array.getInteger(attr, 10);
                    break;
                default:
                    break;
                }
            }
            if (mMinSize > mMaxSize) {
                mMaxSize = mMinSize;
            }
            array.recycle();
        }
    
        private void initHolder() {
            mHolder = this.getHolder();
            mHolder.setFormat(PixelFormat.TRANSLUCENT);
            mHolder.addCallback(this);
        }
    
        private void initSnowFlakes() {
            mFlakes = new SnowFlake[mFlakeCount];
            boolean isRightDir = new Random().nextBoolean();
            for (int i = 0; i < mFlakes.length; i++) {
                mFlakes[i] = new SnowFlake();
                mFlakes[i].setWidth(new Random().nextInt(mMaxSize-mMinSize) + mMinSize);
                mFlakes[i].setHeight(mFlakes[i].getWidth());
                mFlakes[i].setX(new Random().nextInt(mViewWidth));
                mFlakes[i].setY(-(new Random().nextInt(mViewHeight)));
                mFlakes[i].setSpeedY(new Random().nextInt(4) + mSpeedY);
                if (isRightDir) {
                    mFlakes[i].setSpeedX(new Random().nextInt(4) + mSpeedX);
                }
                else {
                    mFlakes[i].setSpeedX(-(new Random().nextInt(4) + mSpeedX));
                }
            }
        }
    
        private void updatePara() {
            int x;
            int y;
            for (SnowFlake flake : mFlakes) {
                if (flake == null) {
                    break;
                }
                x = flake.getX() + flake.getSpeedX();
                y = flake.getY() + flake.getSpeedY();
                if ((x > mViewWidth + 20 || x < 0)
                        || (y > mViewHeight + 20)) {
                    x = new Random().nextInt(mViewWidth);
                    y = 0;
                }
                flake.setX(x);
                flake.setY(y);
            }
        }
    
        private void drawView() {
            if (mHolder == null) {
                return;
            }
            Canvas canvas = mHolder.lockCanvas();
            if (canvas == null) {
                return;
            }
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            drawSnow(canvas);
            mHolder.unlockCanvasAndPost(canvas);
        }
    
        private void drawSnow(Canvas canvas) {
            Rect rect  = new Rect();
            Paint paint = new Paint();
            for (SnowFlake flake : mFlakes) {
                rect.left   = flake.getX();
                rect.top    = flake.getY();
                rect.right  = rect.left + flake.getWidth();
                rect.bottom = rect.top  + flake.getHeight();
                canvas.drawBitmap(mSnowBitmap, null, rect, paint);
            }
        }
    
        @Override
        protected void onVisibilityChanged(View changedView, int visibility) {
            super.onVisibilityChanged(changedView, visibility);
            mStart = (visibility == VISIBLE);
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            initSnowFlakes();
            start();
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
    
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            //--- measure the view's width
            int widthMode  = MeasureSpec.getMode(widthMeasureSpec);
            if (widthMode == MeasureSpec.EXACTLY) {
                mViewWidth = MeasureSpec.getSize(widthMeasureSpec);
            } else {
                mViewWidth = (getPaddingStart() + mSnowBitmap.getWidth() + getPaddingEnd());
            }
    
            //--- measure the view's height
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            if (heightMode == MeasureSpec.EXACTLY) {
                mViewHeight = MeasureSpec.getSize(heightMeasureSpec);
            } else {
                mViewHeight = (getPaddingTop() + mSnowBitmap.getHeight() + getPaddingBottom());
            }
    
            setMeasuredDimension(mViewWidth, mViewHeight);
        }
    
        public void start() {
            new Thread(){
                @Override
                public void run() {
                    while (true) {
                        try {
                            if (mStart) {
                                updatePara();
                                drawView();
                            }
                            Thread.sleep(20);
                        }
                        catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            }.start();
        }
    }
    
    image.gif

    另一种直接继承View

    public class FallingView extends View {
    
        private boolean mStart = false;
        private List<FallObject> fallObjects;
    
        private int viewWidth;
        private int viewHeight;
    
        private static final int defaultWidth = 600;//默认宽度
        private static final int defaultHeight = 1000;//默认高度
        private static final int intervalTime = 5;//重绘间隔时间
    
        public FallingView(Context context) {
            super(context);
            init();
        }
    
        public FallingView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            fallObjects = new ArrayList<>();
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int height = measureSize(defaultHeight, heightMeasureSpec);
            int width = measureSize(defaultWidth, widthMeasureSpec);
            setMeasuredDimension(width, height);
    
            viewWidth = width;
            viewHeight = height;
        }
    
        private int measureSize(int defaultSize, int measureSpec) {
            int result = defaultSize;
            int specMode = View.MeasureSpec.getMode(measureSpec);
            int specSize = View.MeasureSpec.getSize(measureSpec);
    
            if (specMode == View.MeasureSpec.EXACTLY) {
                result = specSize;
            } else if (specMode == View.MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
            return result;
        }
    
        @Override
        protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
            super.onVisibilityChanged(changedView, visibility);
            mStart = (visibility == VISIBLE);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            // 只有在显示的时候才会去绘制
            if (mStart){
                if (fallObjects.size() > 0) {
                    for (int i = 0; i < fallObjects.size(); i++) {
                        //然后进行绘制
                        fallObjects.get(i).drawObject(canvas);
                    }
                    // 隔一段时间重绘一次, 动画效果
                    getHandler().postDelayed(runnable, intervalTime);
                }
            }
        }
    
        // 重绘线程
        private Runnable runnable = new Runnable() {
            @Override
            public void run() {
                invalidate();
            }
        };
    
        /**
         * 向View添加下落物体对象
         *
         * @param fallObject 下落物体对象
         * @param num
         */
        public void addFallObject(final FallObject fallObject, final int num) {
            getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    getViewTreeObserver().removeOnPreDrawListener(this);
                    for (int i = 0; i < num; i++) {
                        FallObject newFallObject = new FallObject(fallObject.builder, viewWidth, viewHeight);
                        fallObjects.add(newFallObject);
                    }
                    invalidate();
                    return true;
                }
            });
        }
    }
    
    image.gif

    但这种需要一个容器 来设置一些参数

    在调用的时候

     private void start(){
            //初始化一个雪花样式的fallObject
            FallObject.Builder builder = new FallObject.Builder(getResources(), R.drawable.hongbao);
            FallObject fallObject = builder
                    .setSpeed(7,true) // 设置物体的初始下落速度
                    .setSize(50,50,true) // 设置物体大小
                    .setWind(5,true,true) // 设置风力等级、方向以及随机因素
                    .build();
            fallingView.addFallObject(fallObject,50);//添加50个下落物体对象
        }
    

    两种哪种都可以实现, 具体还是看需求

    下载地址:https://github.com/xiaobinAndroid421726260/Android_SnowBanner2019_11_5Demo.git

    相关文章

      网友评论

          本文标题:动态轮播图,banner切换动画效果

          本文链接:https://www.haomeiwen.com/subject/xknrvctx.html