android 画廊效果(中间大两边小)的无限轮播banner

作者: 醉挽清风_666 | 来源:发表于2019-03-22 19:52 被阅读0次

    android 画廊效果(中间大两边小)的无限轮播banner

    ps: 项目要求做一个中间大两边小的轮播图,百度了一圈有了些灵感,分享一下心得,国际惯例先上效果图
    banner.gif

    废话不多说,直接上关键代码:

    /**
     * Created by tf on 2018/12/21.
     */
    
    import android.content.Context;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v4.view.PagerAdapter;
    import android.support.v4.view.ViewPager;
    import android.util.AttributeSet;
    import android.util.DisplayMetrics;
    import android.view.WindowManager;
    import android.view.animation.Interpolator;
    import android.widget.Scroller;
    import android.widget.TextView;
    
    import com.hexin.cardservice.R;
    
    import java.lang.ref.WeakReference;
    import java.lang.reflect.Field;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicBoolean;
    
    public class LoopViewPager extends ViewPager {
    
        OnPageChangeListener mOuterPageChangeListener;
        private LoopPagerAdapterWrapper mAdapter;
    
        private MyHandler mHandler;
        private final static int HANDLE_LOOP_MSG = 101;
        private AtomicBoolean isAutoLoop = new AtomicBoolean();
    
        public void setTxtPoints(List<TextView> txtPoints) {
            this.txtPoints = txtPoints;
        }
    
        private List<TextView> txtPoints;
    
        public void changePoints(int pos) {
            if (txtPoints != null) {
                for (int i = 0; i < txtPoints.size(); i++) {
                    if (pos == i) {
                        txtPoints.get(i).setBackgroundResource(R.mipmap.home_yuan_sel);
                    } else {
                        txtPoints.get(i).setBackgroundResource(R.mipmap.home_yuan);
                    }
                }
            }
        }
    
        @Override
        public void setAdapter(PagerAdapter adapter) {
            mAdapter = new LoopPagerAdapterWrapper(adapter);
            super.setAdapter(mAdapter);
            isAutoLoop.set(false);
            setCurrentItem(0, false);
        }
    
        @Override
        public PagerAdapter getAdapter() {
            return mAdapter != null ? mAdapter.getRealAdapter() : mAdapter;
        }
    
        /**
         * 获取当前真实的item
         *
         * @return
         */
        public int getRealItem() {
            return mAdapter != null ? mAdapter.toRealPosition(super.getCurrentItem()) : 0;
        }
    
        public void setCurrentItem(int item, boolean smoothScroll) {
            int realItem = mAdapter.toInnerPosition(item);
            super.setCurrentItem(realItem, smoothScroll);
        }
    
    
        @Override
        public void setOnPageChangeListener(OnPageChangeListener listener) {
            mOuterPageChangeListener = listener;
        }
    
        public LoopViewPager(Context context) {
            super(context);
            init();
        }
    
        public LoopViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            super.setOnPageChangeListener(onPageChangeListener);
            try {
                Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
                scrollerField.setAccessible(true);
                Field interpolator = ViewPager.class.getDeclaredField("sInterpolator");
                interpolator.setAccessible(true);
    
                Scroller scroller = new Scroller(getContext(), (Interpolator) interpolator.get(null)) {
                    @Override
                    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
                        //控制滑动速度
                        super.startScroll(startX, startY, dx, dy, (int) (1300 * (double) Math.abs(dx) / getWidth(getContext())));
                    }
                };
                scrollerField.set(this, scroller);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public void autoLoop(boolean isAuto) {
            if (mHandler == null) {
                mHandler = new MyHandler(getContext());
            }
            if (isAuto) {
                mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);
            } else {
                mHandler.removeCallbacksAndMessages(null);
            }
            isAutoLoop.set(isAuto);
        }
    
        private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
            private float mPreviousOffset = -1;
            private float mPreviousPosition = -1;
    
            @Override
            public void onPageSelected(int position) {
    
                int realPosition = mAdapter.toRealPosition(position);
                changePoints(realPosition);
                if (mPreviousPosition != realPosition) {
                    mPreviousPosition = realPosition;
                    if (mOuterPageChangeListener != null) {
                        mOuterPageChangeListener.onPageSelected(realPosition);
                    }
                }
            }
    
            @Override
            public void onPageScrolled(int position, float positionOffset,
                                       int positionOffsetPixels) {
                int realPosition = position;
                if (mAdapter != null) {
                    realPosition = mAdapter.toRealPosition(position);
    
                    if (positionOffset == 0
                            && mPreviousOffset == 0
                            && (position == 0 || position == mAdapter.getCount() - 1)) {
                        setCurrentItem(realPosition, false);
                    }
                }
    
                mPreviousOffset = positionOffset;
                if (mOuterPageChangeListener != null) {
                    if (realPosition != mAdapter.getRealCount() - 1) {
                        mOuterPageChangeListener.onPageScrolled(realPosition,
                                positionOffset, positionOffsetPixels);
                    } else {
                        if (positionOffset > .5) {
                            mOuterPageChangeListener.onPageScrolled(0, 0, 0);
                        } else {
                            mOuterPageChangeListener.onPageScrolled(realPosition,
                                    0, 0);
                        }
                    }
                }
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
                switch (state) {
                    case SCROLL_STATE_DRAGGING:
                        if (isAutoLoop.get()) {
                            mHandler.removeCallbacksAndMessages(null);
                        }
                        break;
                    case SCROLL_STATE_IDLE:
                        if (isAutoLoop.get()) {
                            mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);
                        }
                        break;
                    case SCROLL_STATE_SETTLING:
                        break;
                }
                if (mOuterPageChangeListener != null) {
                    mOuterPageChangeListener.onPageScrollStateChanged(state);
                }
            }
        };
    
    //    @Override
    //    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    //
    //        int height = 0;
    //        for (int i = 0; i < getChildCount(); i++) {
    //            View child = getChildAt(i);
    //            child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    //            int h = child.getMeasuredHeight();
    //            if (h > height)
    //                height = h;
    //        }
    //        int width = 0;
    //        for (int i = 0; i < getChildCount(); i++) {
    //            View child = getChildAt(i);
    //            child.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), heightMeasureSpec);
    //            int h = child.getMeasuredWidth();
    //            if (h > width)
    //                width = h;
    //        }
    //
    //        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
    //        widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
    //
    //        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //    }
    
        private class MyHandler extends Handler {
    
            WeakReference<Context> mWeakReference;
    
            public MyHandler(Context context) {
                mWeakReference = new WeakReference<>(context);
            }
    
            @Override
            public void handleMessage(Message msg) {
                final Context context = mWeakReference.get();
                if (context == null) {
                    return;
                }
                switch (msg.what) {
                    case HANDLE_LOOP_MSG:
                        int curItem = getCurrentItem();
                        setCurrentItem(++curItem);
                        changePoints(curItem % txtPoints.size() );
                        break;
                }
            }
        }
    
    
        public int getWidth(Context context) {
            WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics outMetrics = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(outMetrics);
            return outMetrics.widthPixels;
        }
    }
    
    
    • LoopPagerAdapterWrapper类
      package com.hexin.cardservice.ui.customView;
    
    /**
     * Created by 15061 on 2018/12/21.
     */
    
    import android.os.Parcelable;
    import android.support.v4.view.PagerAdapter;
    import android.view.View;
    import android.view.ViewGroup;
    
    public class LoopPagerAdapterWrapper extends PagerAdapter {
    
        private PagerAdapter mAdapter;
    
        LoopPagerAdapterWrapper(PagerAdapter adapter) {
            this.mAdapter = adapter;
        }
    
        @Override
        public void notifyDataSetChanged() {
            super.notifyDataSetChanged();
        }
    
        public int toInnerPosition(int realPosition) {
            return realPosition + getCount() / 2  - getCount() % getRealCount();
        }
    
        int toRealPosition(int position) {
            return position % getRealCount();
        }
    
        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }
    
        public int getRealCount() {
            return mAdapter.getCount();
        }
    
        public PagerAdapter getRealAdapter() {
            return mAdapter;
        }
    
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            int realPosition = position % getRealCount();
            return mAdapter.instantiateItem(container, realPosition);
        }
    
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            int realPosition = position % getRealCount();
            mAdapter.destroyItem(container, realPosition, object);
        }
    
        @Override
        public void finishUpdate(ViewGroup container) {
            mAdapter.finishUpdate(container);
        }
    
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return mAdapter.isViewFromObject(view, object);
        }
    
        @Override
        public void restoreState(Parcelable bundle, ClassLoader classLoader) {
            mAdapter.restoreState(bundle, classLoader);
        }
    
        @Override
        public Parcelable saveState() {
            return mAdapter.saveState();
        }
    
        @Override
        public void startUpdate(ViewGroup container) {
            mAdapter.startUpdate(container);
        }
    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            mAdapter.setPrimaryItem(container, position, object);
        }
    }
    
    

    配置文件代码

    <RelativeLayout
                    android:id="@+id/relativelayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="15dp">
    
                    <.LoopViewPager
                        android:id="@+id/myviewpager"
                        android:layout_width="match_parent"
                        android:layout_height="125dp" />
                    <!-- 存放圆点 -->
                    <LinearLayout
                        android:id="@+id/layout_dots"
                        android:layout_width="wrap_content"
                        android:layout_height="30dp"
                        android:layout_alignParentBottom="true"
                        android:layout_centerHorizontal="true"
                        android:gravity="center"
                        android:orientation="horizontal"/>
                </RelativeLayout>
    

    MainActivity 应用

    初始化ViewPager

    private void initViewPager() {
    
            mViewpager = view.findViewById(R.id.myviewpager);
            //图片圆角处理
            for (int i = 0; i < mBannerArr.length; i++) {
                ImageView view1 = new ImageView(getContext());
                RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), BitmapFactory.decodeResource(getResources(), mBannerArr[i]));
                //view1.setImageResource(R.mipmap.pic);
                roundedBitmapDrawable.setCornerRadius(30);
                view1.setImageDrawable(roundedBitmapDrawable);
                mImageList.add(view1);
            }
    
            mViewpager.setClipChildren(false);
            DisplayMetrics dm = getResources().getDisplayMetrics();
            mViewpager.setPageMargin(-dm.widthPixels / 13);//设置viewpage之间的间距
    
            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mViewpager.getLayoutParams();
            //高度根据图片进行适配(这里图片为750 *300)
            params.height = (int) (getResources().getDisplayMetrics().widthPixels * 330 / 750.0);
            params.width = getResources().getDisplayMetrics().widthPixels;
            mViewpager.setLayoutParams(params);
            mViewpager.setAdapter(new MyAdapter());
            mViewpager.setPageTransformer(true, new ViewPager.PageTransformer() {
                float scale = 0.85f;
    
                @Override
                public void transformPage(View page, float position) {
                    if (position >= 0 && position <= 1) {
                        page.setScaleY(scale + (1 - scale) * (1 - position));
                    } else if (position > -1 && position < 0) {
                        page.setScaleY(1 + (1 - scale) * position);
                    } else {
                        page.setScaleY(scale);
                    }
                }
            });
            mViewpager.autoLoop(true);
    }
    

    初始化指示器小圆点

    /**
         * 初始化小圆点
         */
        private void initCircle() {
            mLayoutPoints = view.findViewById(R.id.layout_dots);
            mTxtPoints = new ArrayList<>();
            int d = DensityUtils.dp2px(mContext, 6);
            int m = 10;
            for (int i = 0; i < mImageList.size(); i++) {
                TextView txt = new TextView(getContext());
                if (i == 0) {
                    txt.setBackgroundResource(R.mipmap.home_yuan_sel);
                } else {
                    txt.setBackgroundResource(R.mipmap.home_yuan);
                }
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(d, d);
                params.setMargins(m, m, m, m);
                txt.setLayoutParams(params);
                mTxtPoints.add(txt);
                mLayoutPoints.addView(txt);
            }
            mViewpager.setTxtPoints(mTxtPoints);
        }
    

    viewpager自定义适配器:

    class MyAdapter extends PagerAdapter {
    
            @Override
            public int getCount() {
                return mImageList.size();
            }
    
            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view == object;
            }
    
            @Override
            public Object instantiateItem(ViewGroup container, final int position) {
                ImageView view = mImageList.get(position);
                ViewParent viewParent = view.getParent();
                if (viewParent == null) {
                    container.addView(view);
                }
    
                view.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        log.d(TAG, "点击了第" + postion + "张图");
                    }
                });
                return view;
            }
    
            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView((View) object);
            }
        }
    

    PS:这些就是轮播效果图了,希望对读者有帮助。。。

    相关文章

      网友评论

        本文标题:android 画廊效果(中间大两边小)的无限轮播banner

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