1. 程式人生 > >Android--仿愛奇藝 首頁輪播圖

Android--仿愛奇藝 首頁輪播圖

前因

近期開啟愛奇藝的時候,突然發現它首頁的輪播圖跟以前不一樣了,左右兩個圖都能顯示一部分,且有滑動時縮放的效果,一直不知咋樣實現,然後在鴻洋的微信公眾號中看到了一篇仿魅族Banner效果的文章,最後在參考中放出了連結,然後就參考了這篇文章,就在此做個記錄。廢話不多說了,先上個效果圖
這裡寫圖片描述

後果

佈局檔案

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
android:layout_height="match_parent" android:clipChildren="false" android:orientation="vertical">
<com.ly.viewpagerdemo.LoopViewPager android:id="@+id/looviewpager" android:layout_width="match_parent" android:layout_height="200dp" android:layout_marginLeft
="20dp" android:layout_marginRight="20dp" />
</LinearLayout>

這個屬性android:clipChildren 很關鍵,是否裁剪子view
這裡的LoopViewPager,是參考開源框架 LoopingViewPager來的,使用Integer.MAX_VALUE 來實現左右迴圈滾動的,使用方式是一致的


package com.ly.viewpagerdemo;

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 java.lang.ref.WeakReference; import java.lang.reflect.Field; 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(); @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); 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); } } }; 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); 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.ly.viewpagerdemo;

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);
    }

}

MainActivity

package com.ly.viewpagerdemo;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;

public class MainActivity extends AppCompatActivity {

    private LoopViewPager looviewpager;

    Context context;

    int[] resIds = new int[]{R.mipmap.img1, R.mipmap.img2, R.mipmap.img3, R.mipmap.img4, R.mipmap.img5, R.mipmap.img6};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        looviewpager = (LoopViewPager) findViewById(R.id.looviewpager);
        looviewpager.setAdapter(new MyAdapter());
        looviewpager.setOffscreenPageLimit(3);
        looviewpager.setPageTransformer(true, new ViewPager.PageTransformer() {
            float scale = 0.9f;

            @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);
                }
            }
        });
        looviewpager.autoLoop(true);
    }


    class MyAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return resIds.length;
        }

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

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = View.inflate(context, R.layout.item_viewpager, null);
            RoundImageView itemImage = (RoundImageView) view.findViewById(R.id.item_image);
            itemImage.setImageResource(resIds[position]);
            container.addView(view);
            return view;
        }

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

}

ViewPager的setPageTransformer是用來控制view的切換動畫的

looviewpager.setPageTransformer(true, new ViewPager.PageTransformer() {
            float scale = 0.9f;

            @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);
                }
            }
        });

參考

原始碼下載