天天看點

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

android ViewPager 仿畫廊/圖書翻頁 與 palette 使用

  • 普通ViewPager實作
  • ViewPager.PageTransformer
  • 仿圖書效果
  • palette 調色闆

廢話不多說,先來看看完成的效果!

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

總結實作效果:

  • ViewPager 實作無限自動播放
  • ViewPager 實作中間大,兩邊小 [仿畫廊效果]
  • ViewPager 實作圖檔疊加[仿圖書翻頁效果]
  • palette 調色闆實作識别圖檔顔色,随着圖檔的變化來改變背景色的變化

普通ViewPager實作

先不管三七二十一,先吧最基本的ViewPager實作,之後在在基本的ViewPager上修改!

不用複制代碼,先看思路就行,底部會給出完整代碼!

activity_palette.xml布局:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

java代碼:

//設定擴充卡
viewPager.setAdapter(new BannerAdapter(this, mDrawables));

//Pager之間的間距
viewPager.setPageMargin(20);

//預加載
viewPager.setOffscreenPageLimit(3);

//預設第一張圖 左右都有圖
viewPager.setCurrentItem(1);
           

BannerAdapter 擴充卡:

public class BannerAdapter extends PagerAdapter {
    private int[] mData;
    private Context mContext;

    public BannerAdapter(Context ctx, int[] data) {
        this.mContext = ctx;
        this.mData = data;
    }

    @Override
    public int getCount() {
        return mData.length;// 傳回資料的個數
    }

    @Override
    public Object instantiateItem(final ViewGroup container, final int position) {//子View顯示
        View view = View.inflate(container.getContext(), R.layout.banner_item_layout, null);
        ImageView imageView = view.findViewById(R.id.iv_icon);
        imageView.setImageResource(mData[position]);

        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(mContext, "目前條目:" + position, Toast.LENGTH_SHORT).show();
            }
        });

        container.addView(view);//添加到父控件
        return view;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;// 過濾和緩存的作用
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);//從viewpager中移除掉
    }
}
           

先來看看目前的效果:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

就是一個很簡單的ViewPager沒什麼好說的!

思路分析:

要想完成畫廊的效果,那麼必須吧viewPager分為以下幾步驟:

  • 讓ViewPager顯示出左右兩側的View
  • 無限滑動
  • 自定義ViewPager 滑動動畫,滑動過程中中間大,兩邊小
  • 自動播放

那就來根據思路實作效果吧 :

讓ViewPager顯示出左右兩側的View
android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

來看看效果:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆
無限滑動
android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

這個也是真 的簡單,直接取%即可實作

來看看效果:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

中間大,兩邊小效果

要想實作這個效果,就要來介紹本篇重中之重! ViewPager.PageTransformer

ViewPager.PageTransformer

先來看使用:

  • 參數一: 是否逆轉,我沒看出有什麼效果,懂這個參數的記得在評論區留言哦!
  • 參數二: 用來控制ViewPager 動畫的
public class ScaleTransformer implements ViewPager.PageTransformer {
    private static final float MAX_SCALE = 1.0f;//0縮放
    private static final float MIN_SCALE = 0.80f;//0.85縮放


    @Override
    public void transformPage(@NonNull View view, float position) {
        
    }
}
           

實作implements ViewPager.PageTransformer重寫transformPage()方法,有2個參數

/**
     * A PageTransformer is invoked whenever a visible/attached page is scrolled.
     * This offers an opportunity for the application to apply a custom transformation
     * to the page views using animation properties.
     *
     * <p>As property animation is only supported as of Android 3.0 and forward,
     * setting a PageTransformer on a ViewPager on earlier platform versions will
     * be ignored.</p>
     */
    public interface PageTransformer {
        /**
         * Apply a property transformation to the given page.
         *
         * @param page Apply the transformation to this page
         * @param position Position of page relative to the current front-and-center
         *                 position of the pager. 0 is front and center. 1 is one full
         *                 page position to the right, and -1 is one page position to the left.
         */
        void transformPage(@NonNull View page, float position);
    }
           

這個方法在onPageScrolled頁面滑動的過程中回調

@CallSuper
    protected void onPageScrolled(int position, float offset, int offsetPixels) {
        
        ....省略.......

        if (mPageTransformer != null) {
        ....省略.......
        
                mPageTransformer.transformPage(child, transformPos);
            }
        }

        mCalledSuper = true;
    }
           

transformPage參數:

  • 參數一: 目前view
  • 參數二:目前view的位置

這裡比較抽象,畫張圖看看

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆
  • 紅色目前View
  • 藍色 左側View
  • 黃色 右側View

不滑動狀态position變化:

紅色 藍色 黃色
position = -1 position = 0 position = 1

滑動狀态position變化:

狀态 紅色 藍色 黃色
左滑動 position < -1 0 < position < -1 1 < position < 0
右滑動 -1 < position < 0 0 < position < 1 position > 1

先來列印一下看看position的值:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

還看不懂? 再來畫一張圖:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

好了,position就介紹到這裡!

先簡簡單單修改代碼,先看看效果:

public class ScaleTransformer implements ViewPager.PageTransformer {
    private static final float MAX_SCALE = 1.0f;//0縮放
    private static final float MIN_SCALE = 0.80f;//0.85縮放


    @Override
    public void transformPage(@NonNull View view, float position) {
      	//position != 0 表示左側和右側的view
        if (position != 0) {
            view.setScaleX(MIN_SCALE);
            view.setScaleY(MIN_SCALE);
        } else {
            view.setScaleX(MAX_SCALE);
            view.setScaleY(MAX_SCALE);
        }
    }
}
           

效果:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

可以看到,要實作的效果已經漸漸接近了!

在加上滑動時候放大縮小即可

public class ScaleTransformer implements ViewPager.PageTransformer {
    private static final float MAX_SCALE = 1.0f;//0縮放
    private static final float MIN_SCALE = 0.80f;//0.85縮放
    @Override
    public void transformPage(@NonNull View view, float position) {
      
        if (position < 1) {
            float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
	
            view.setScaleX(scaleFactor);

            view.setScaleY(scaleFactor);
        } else {
            view.setScaleX(MIN_SCALE);
            view.setScaleY(MIN_SCALE);
        }
    }
}
           

這裡涉及到一個小算法

指的就是變化過程中view的大小

這段代碼要細細的品味一下!!!很關鍵!!

來看看濕滑的效果:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆
無限自己滾動

這段代碼也是簡單的很:

直接上代碼不多貝貝:

//用來記錄是否按壓,如果按壓,則不滾動
boolean isDown ;

Timer timer = new Timer();

   //定時器播放ViewPager
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                if (!isDown) {
                    //擷取到目前的位置
                    int page = viewPager.getCurrentItem() + 1;
                    runOnUiThread(() -> viewPager.setCurrentItem(page));
                }
            }
        };
		// 每2.5秒執行一次
       timer.schedule(timerTask, 0, 2500);


 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
              //viewPager滑動的時候,設定不讓滾動
                isDown = true;
            }

            @Override
            public void onPageSelected(int position) {
               
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            //ViewPager不點選了讓滾動
                isDown = false;
            }
        });
           

這段代碼過于簡單,就不看效果了!

仿圖書效果

這個效果和仿畫廊流程一樣,也是對PageTransformer的操作,直接上代碼了!

public class StackPageTransformer implements ViewPager.PageTransformer {
    private final ViewPager viewPager;

    private final float SCALE_VALUE = 1f;

    //View 之間的偏移量
    private final float DEVIATION = 60f;

    //旋轉
    private final float ROTATION = 60f;

    //圖檔是否疊加【預設不疊加】
    private final boolean isStack = false;


    public StackPageTransformer(ViewPager viewPager) {
        this.viewPager = viewPager;
    }

    @Override
    public void transformPage(@NonNull View view, float position) {
        Log.i("szjPosition2", position + "");

        /*
         * 當不滑動狀态下:
         *      position = -1 左側View
         *      position = 0 目前View
         *      position = 1 右側View
         *
         * 當滑動狀态下:
         *  向左滑動: [ position < 0 && position > -1]
         *    左側View      position < -1
         *    目前View    0 ~ -1
         *    右側View   1 ~ 0
         *
         * 向右滑動:[position > 0 && position < 1 ]
         *   左側View  -1 < position < 0
         *   目前View  0 ~ 1
         *   右側View  position > 1
         */

        int pageWidth = viewPager.getWidth();

        //隐藏左側側的view
        if (position == -1) {
            view.setVisibility(View.GONE);
        } else {
            view.setVisibility(View.VISIBLE);
        }

        //目前View和右側的View [讓右側View和目前View疊加起來]
        if (position >= 0) {
            float translationX;
            //這裡不要暈! 改變isStack來看看效果吧!!
            if (isStack) {
                translationX = DEVIATION - (pageWidth) * position;
            } else {
                translationX = (DEVIATION - pageWidth) * position;
            }
            Log.i("szjTranslationX", translationX + "");
            view.setTranslationX(translationX);
        }

        //目前view
        if (position == 0) {
            view.setScaleX(SCALE_VALUE);
            view.setScaleY(SCALE_VALUE);
        } else {
            //左側已經隐藏了,是以這裡值的是右側View的偏移量
            float scaleFactor = Math.min(SCALE_VALUE - position * 0.1f, SCALE_VALUE);
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);
        }

        //向左滑動
        if (position < 0 && position > -1) {
            //旋轉
            view.setRotation(ROTATION * position);
            view.setAlpha(1 - Math.abs(position));
        } else {
            //透明度 其他狀态不設定透明度
            view.setAlpha(1);
        }

        //向右滑動
        if (position > 0 && position < 1) {
            view.setRotation(0);
        }
    }
}
           

看看效果:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

palette 調色闆

先添加依賴:

簡單介紹:

palette 傳入一張Bitmap,然後他會通過圖檔像素點來分析出顔色占比,提取出你需要的顔色!!

使用:

public void initPalette(Bitmap bitmap) {
        new Thread(() -> Palette.from(bitmap).generate(palette -> {
            //以RGB壓縮整數的形式從調色闆傳回靜音和深色。
            int darkMutedColor = palette.getDarkMutedColor(Color.TRANSPARENT);

            //暗 柔和 [以RGB壓縮整數的形式從調色闆傳回靜音和淺色。]
            int lightMutedColor = palette.getLightMutedColor(Color.TRANSPARENT);

            //暗 鮮豔 [以RGB壓縮整數的形式從調色闆傳回深色和鮮豔的顔色。]
            int darkVibrantColor = palette.getDarkVibrantColor(Color.TRANSPARENT);

            //量 鮮豔 [以RGB壓縮整數的形式從調色闆傳回明亮的顔色。]
            int lightVibrantColor = palette.getLightVibrantColor(Color.TRANSPARENT);

            //柔和 [将調色闆中的靜音顔色作為RGB壓縮整數傳回。]
            int mutedColor = palette.getMutedColor(Color.TRANSPARENT);

            //以RGB壓縮整數形式傳回調色闆中最鮮豔的顔色。
            int vibrantColor = palette.getVibrantColor(Color.TRANSPARENT);


            //從調色闆中傳回一個明亮且充滿活力的樣例。可能為空。
            Palette.Swatch lightVibrantSwatch = palette.getLightVibrantSwatch();

            int hotColor = Color.TRANSPARENT;
            if (lightVibrantSwatch != null) {
                //谷歌推薦的:圖檔的整體的顔色rgb的混合痔---主色調
                int rgb = lightVibrantSwatch.getRgb();
                hotColor = getTranslucentColor(0.7f, rgb);
            }
	
		// 拿到顔色 這裡就可以給View 設定顔色了 

        })).start();
    }
           

然後通過随機圖檔,設定不同的圖檔來測試一下管用不管用!

來看看效果:

android ViewPager 進階(仿畫廊/圖書翻頁) 與 palette 使用 (含完整Demo)普通ViewPager實作ViewPager.PageTransformer仿圖書效果palette 調色闆

這裡用到了動态代碼設定漸變,代碼很簡單,給大家看看吧

/**
     * TODO 設定漸變顔色
     *
     * @param view   需要設定的View
     * @param colors 漸變顔色
     * @param type   漸變位置  例如:GradientDrawable.Orientation.LEFT_RIGHT 從左到右
     * @param radius 圓角
     */
    public void setGradualChange(View view, int[] colors, GradientDrawable.Orientation type, int radius) {
        GradientDrawable drawable = new GradientDrawable(type, colors);
        drawable.setCornerRadius(radius);
        view.setBackground(drawable);
    }
           

完整項目

原創不易,您的點贊就是對我最大的支援!!