Android中使用ViewPager实现一屏多页面的功能

效果图【录制后使用扣扣秀视频制作的gif,看见水印请别见怪】:

Android中使用ViewPager实现一屏多页面的功能_第1张图片

实现的主要注意点【关于view pager的使用就忽略了】

1、
Adapter需要重写函数——
@Override
public float getPageWidth(int position);

2、clipChildren属性的使用—-决定了一屏三页还是一屏两页,三页的就比如爱奇艺的横向滑动的左右两边有相互接壤的页面一部分,两页的就是效果图展示。
当前页所占屏幕宽度,不可以设置ViewPager属性clipToPadding=”false”
* 或者clipChildren=”false”,否则不起作用,设置clipToPadding=”false”同一屏幕将会出现三个页,true时仅有一个页。
3、
ShadowTransformer的使用。

下面上做过简要封装后的代码(代码中因为需要有三个部分的页面样式,故而有做过一个分组,具体可见Adapter抽象基类):
1) 定义接口:

public interface ICardViewPagerAdapter {
    /*
    用于计算阴影
     */
    int MAX_ELEVATION_FACTOR = 8;
    /*
    CardView阴影
     */
    float getBaseElevation();

    View getCardViewAt(int position);

    int getCount();
    /**
     是否使用阴影效果【主要针对CardView言】
     false:
     app:cardElevation="0px" //阴影大小
     app:cardMaxElevation="2px"//最大阴影大小,该值最小2px
     app:cardUseCompatPadding="false"//不显示阴影
     app:contentPaddingBottom="-20dp"
     app:contentPaddingTop="-20dp"
     */
    boolean elevatieUsable();
}

2) Adapter基类实现

public abstract class CardPagerAdapter  extends PagerAdapter implements ICardViewPagerAdapter {

    private List mViews;
    /**
     * 数据源
     */
    private List mResourceData;
    private float mBaseElevation;

    protected boolean isUsableEleVation = true;

    protected TypeInflateView mTypeInflateView;
    /**
     * 子控件-亨元.
     */
    private SparseArray viewWidgets = new SparseArray<>();

    /**
     * 缓存-避免多次新建对象
     */
    private SparseArray rootViews = new SparseArray<>();

    public boolean isUsableEleVation() {
        return isUsableEleVation;
    }

    public void setUsableEleVation(boolean usableEleVation) {
        isUsableEleVation = usableEleVation;
    }

    public CardPagerAdapter() {
        mResourceData = new ArrayList<>();
        mViews = new ArrayList<>();
    }

    public void addCardItem(T item) {
        mViews.add(null);
        mResourceData.add(item);
    }

    public void addAllCardItem(List allData){
        mResourceData.addAll(allData);
        int i = 0;
        while (i < allData.size()){
            mViews.add(null);
            i++;
        }
    }

    public View findWidgetViewById(View view , int resId){
        View viewWidget = viewWidgets.get(resId);
        if (viewWidget == null){
            viewWidget = view.findViewById(resId);
            viewWidgets.put(resId, viewWidget);
        }
        return viewWidget;
    }

    public float getBaseElevation() {
        return mBaseElevation;
    }

    public enum TypeInflateView{
        FirstPageType, CenterPageType, LastPageType
    }

    /**
     * 当前页所占屏幕宽度,不可以设置ViewPager属性clipToPadding="false"
     * 或者clipChildren="false",否则不起作用,设置clipToPadding="false"同一屏幕将会出现三个页,true时仅有一个页。
     * @param position
     * @return
     */
    @Override
    public float getPageWidth(int position) {
        return (float) 0.63;
    }

    @Override
    public View getCardViewAt(int position) {
        return mViews.get(position);
    }

    @Override
    public int getCount() {
        return mResourceData.size();
    }

    @Override
    public boolean elevatieUsable() {
        return isUsableEleVation();
    }

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

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view  = rootViews.get(position);
        if (view == null) {
            if (position == 0) {
                mTypeInflateView = TypeInflateView.FirstPageType;
                view = LayoutInflater.from(container.getContext())
                        .inflate(onObtainLayoutR(mTypeInflateView, position), container, false);
            } else if (getCount() - 1 == position) {
                mTypeInflateView = TypeInflateView.LastPageType;
                view = LayoutInflater.from(container.getContext())
                        .inflate(onObtainLayoutR(mTypeInflateView, position), container, false);
            } else {
                mTypeInflateView = TypeInflateView.CenterPageType;
                view = LayoutInflater.from(container.getContext())
                        .inflate(onObtainLayoutR(mTypeInflateView, position), container, false);
            }
            rootViews.put(position, view);
        }

        container.addView(view);
        bind(position, view);

        View cardView =  view.findViewById(onObtainCardViewRAtLayout());

        if (mBaseElevation==0  && cardView!=null && cardView instanceof CardView) {

            mBaseElevation = ((CardView)cardView).getCardElevation();
            ((CardView)cardView).setMaxCardElevation(mBaseElevation * MAX_ELEVATION_FACTOR);
        }

        if (mViews.get(position) == null) {
            if (cardView != null)
                mViews.set(position, cardView);
            else
                mViews.set(position, view);
        }

        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
        mViews.set(position, null);
    }


    public View getRootView(int realPosition){
        return rootViews.get(realPosition);
    }

    /**
     * 此方法用于绑定数据到控件上面,以及设置事件监听等.
     * @param position
     * @param view
     */
    public abstract void bind(int position, View view) ;


    /**
     * 此方法返回一个布局xml的id,eg:R.layout.
     * @return
     */
    protected abstract int onObtainLayoutR(TypeInflateView mTypeInflateView, int position);

    /**
     * 此方法用于获取CardView,必须在onObtainLayoutR()的layout中定义过CardView的id
     * @return
     */
    protected abstract int onObtainCardViewRAtLayout();

}

3)ShadowTransformer的实现类:


public class ShadowTransformer implements ViewPager.OnPageChangeListener, ViewPager.PageTransformer {

    private ViewPager mViewPager;
    private ICardViewPagerAdapter mAdapter;
    private float mLastOffset;
    private boolean mScalingEnabled; // 是否使用缩放效果,默认使用

    private OnViewPageChangedListener mOnViewPageChangedListener;

    public void setOnViewPageChangedListener(OnViewPageChangedListener zOnViewPageChangedListener){
        this.mOnViewPageChangedListener = zOnViewPageChangedListener;
    }

    public ShadowTransformer(ViewPager viewPager, ICardViewPagerAdapter adapter) {
        mViewPager = viewPager;
        mViewPager.addOnPageChangeListener(this);
        mAdapter = adapter;
    }

    public void enableScaling(boolean enable) {
        if (mScalingEnabled && !enable) {
            // shrink main card
            View currentCard = mAdapter.getCardViewAt(mViewPager.getCurrentItem());
            if (currentCard != null) {
                currentCard.animate().scaleY(1);
                currentCard.animate().scaleX(1);
            }
        }else if(!mScalingEnabled && enable){
            // grow main card
            View currentCard = mAdapter.getCardViewAt(mViewPager.getCurrentItem());
            if (currentCard != null) {
                currentCard.animate().scaleY(1.1f);
                currentCard.animate().scaleX(1.1f);
            }
        }

        mScalingEnabled = enable;
    }

    @Override
    public void transformPage(View page, float position) {

    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        int realCurrentPosition;
        int nextPosition;
        float baseElevation = mAdapter.getBaseElevation();
        float realOffset;
        boolean goingLeft = mLastOffset > positionOffset;

        // If we're going backwards, onPageScrolled receives the last position
        // instead of the current one
        if (goingLeft) {
            realCurrentPosition = position + 1;
            nextPosition = position;
            realOffset = 1 - positionOffset;
        } else {
            nextPosition = position + 1;
            realCurrentPosition = position;
            realOffset = positionOffset;
        }

        // Avoid crash on overscroll
        if (nextPosition > mAdapter.getCount() - 1
                || realCurrentPosition > mAdapter.getCount() - 1) {
            return;
        }

//        ((CardPagerAdapter)mAdapter).bind(realCurrentPosition,
//                ((CardPagerAdapter)mAdapter).getRootView(realCurrentPosition));
//        ((CardPagerAdapter)mAdapter).bind(nextPosition,
//                ((CardPagerAdapter)mAdapter).getRootView(nextPosition));

        View currentCard = mAdapter.getCardViewAt(realCurrentPosition);

        // This might be null if a fragment is being used
        // and the views weren't created yet
        if (currentCard != null) {
            if (mScalingEnabled) {
                currentCard.setScaleX((float) (1 + 0.1 * (1 - realOffset)));
                currentCard.setScaleY((float) (1 + 0.1 * (1 - realOffset)));
            }
            if (currentCard instanceof CardView) {
                if (mAdapter.elevatieUsable()) {
                    ((CardView)currentCard).setCardElevation((baseElevation + baseElevation
                            * (ICardViewPagerAdapter.MAX_ELEVATION_FACTOR - 1) * (1 - realOffset)));
                } else {
                    ((CardView)currentCard).setCardElevation(0.0f);
                }
            }
        }

        View nextCard = mAdapter.getCardViewAt(nextPosition);

        // We might be scrolling fast enough so that the next (or previous) card
        // was already destroyed or a fragment might not have been created yet
        if (nextCard != null) {
            if (mScalingEnabled) {
                nextCard.setScaleX((float) (1 + 0.1 * (realOffset)));
                nextCard.setScaleY((float) (1 + 0.1 * (realOffset)));
            }
            if (currentCard instanceof CardView) {
                if (mAdapter.elevatieUsable()) {
                    ((CardView)nextCard).setCardElevation((baseElevation + baseElevation
                            * (ICardViewPagerAdapter.MAX_ELEVATION_FACTOR - 1) * (realOffset)));
                } else {
                    ((CardView)currentCard).setCardElevation(0.0f);
                }
            }
        }

        mLastOffset = positionOffset;

        if (mOnViewPageChangedListener != null)
            mOnViewPageChangedListener.onPageScrolled(position, positionOffset, positionOffsetPixels);

    }

    @Override
    public void onPageSelected(int position) {
        if (mOnViewPageChangedListener != null){
            mOnViewPageChangedListener.onPageSelected(position);
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {

        if (mOnViewPageChangedListener != null){
            mOnViewPageChangedListener.onPageScrollStateChanged(state);
        }
    }

    public interface OnViewPageChangedListener{
        void onPageSelected(int position);
        void onPageScrollStateChanged(int state);
        void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
    }
}

使用例子eg:

 mCardActShopAdapter = new CardActShopAdapter();
        mCardActShopAdapter.addCardItem("");
        mCardActShopAdapter.addCardItem("");
        mCardActShopAdapter.addCardItem("");
        mCardActShopAdapter.addCardItem("");
        mCardActShopAdapter.addCardItem("");
        mCardShadowTransformer = new ShadowTransformer(viewPager, mCardActShopAdapter);
        /**
         * 是否启用滑动动画
         */
        mCardShadowTransformer.enableScaling(true);
        viewPager.setPageTransformer(false, mCardShadowTransformer);
        /**
         * 页面之间的间距
         */
         viewPager.setPageMargin(getResources().getDimensionPixelOffset(R.dimen.dp_35));
        //viewPager.setAllowSlidingToLastPosition(true);
        viewPager.setOffscreenPageLimit(3);
        viewPager.setAdapter(mCardActShopAdapter);

CardActShopAdapter是抽象基类的子类.根据需求自行进行扩展:
上一个简单例子:

 public class CardActShopAdapter extends CardPagerAdapter {

        public SparseArray mCenterViewHolder = new SparseArray<>();

        private void bindDataForFirstView(View varView){
            TextView tvTitleActivityCard = (TextView) findWidgetViewById(varView, R.id.tv_title_activity_card);
            TextView tvDescActivityCard = (TextView) findWidgetViewById(varView, R.id.tv_desc_activity_card);
            RelativeLayout rlBuyCare = (RelativeLayout) findWidgetViewById(varView, R.id.rl_buy_care);

            tvDescActivityCard.setMovementMethod(ScrollingMovementMethod.getInstance());

            rlBuyCare.setOnClickListener(new OnForbidDoubleClick() {
                @Override
                public void onClickSuccess(View varView) {
                    final ShoppingIntroductionDialog mShoppingIntroductionDialog = new ShoppingIntroductionDialog
                            .IntroductionBuilder(CardActShopActivity.this)
                            .create()
                            .showDialog();
                    mShoppingIntroductionDialog.findWidgetByResId(R.id.btn_back_page)
                            .setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View v) {
                                    if (mShoppingIntroductionDialog.isShowing()){
                                        mShoppingIntroductionDialog.dismiss();
                                    }
                                }
                            });
                }

                @Override
                public void onClickForbid(View varView) {

                }
            });
        }


        private void bindDataForCenterView(int position, View varView){
            if (mCenterViewHolder.get(position) == null) {
                ViewHolder viewHolder = new ViewHolder();
                viewHolder.ivActivityCardHeader = (ImageView) findWidgetViewById(varView, R.id.iv_activity_card_header);
                viewHolder.tvTitleActivityCard = (TextView) findWidgetViewById(varView, R.id.tv_title_activity_card);
                viewHolder.tvDescActivityCard = (TextView) findWidgetViewById(varView, R.id.tv_desc_activity_card);
                viewHolder.rlBuyCare = (TextView) findWidgetViewById(varView, R.id.tv_right_now_buy);
                viewHolder.rlBuyCare.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ToastUtils.showLong("立即购买");
                    }
                });

                mCenterViewHolder.put(position, viewHolder);
            }
        }

        private void bindDataForLastView(View varView){
            TextView tvRightNowCall = (TextView) findWidgetViewById(varView, R.id.tv_right_now_call);
            tvRightNowCall.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ToastUtils.showLong("客服电话:0871-xxx-xXXX");
                }
            });
        }

        @Override
        public void bind(int position, View view) {
            if (position == 0){
                bindDataForFirstView(view);
            } else if (position == getCount()-1){
                bindDataForLastView(view);
            } else {
                bindDataForCenterView(position, view);
            }
        }



        @Override
        protected int onObtainLayoutR(TypeInflateView mTypeInflateView, int position) {
            if (mTypeInflateView == TypeInflateView.FirstPageType){
                return R.layout.pager_act_first;
            } else if (mTypeInflateView == TypeInflateView.LastPageType){
                return R.layout.pager_act_last;
            } else {
                return R.layout.pager_act_center;
            }
        }


        @Override
        protected int onObtainCardViewRAtLayout() {
            return 0;
        }
    }

你可能感兴趣的:(Android)