浏览代码

MULTI_PAGE_OVERLAP supported.

zhpanvip 5 年之前
父节点
当前提交
0cb61ecfde

+ 3 - 1
bannerview/build.gradle

@@ -1,6 +1,7 @@
 apply plugin: 'com.android.library'
 apply plugin: 'com.github.dcendents.android-maven'
-apply plugin: 'com.jfrog.bintray'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
 android {
     compileSdkVersion 28
 
@@ -32,4 +33,5 @@ dependencies {
     implementation 'androidx.appcompat:appcompat:1.1.0'
     api 'com.github.zhpanvip:viewpagerindicator:1.0.0'
     implementation 'androidx.viewpager2:viewpager2:1.0.0'
+    implementation 'androidx.core:core-ktx:1.1.0'
 }

+ 11 - 3
bannerview/src/main/java/com/zhpan/bannerview/BannerViewPager.java

@@ -24,6 +24,7 @@ import com.zhpan.bannerview.annotation.Visibility;
 import com.zhpan.bannerview.constants.PageStyle;
 import com.zhpan.bannerview.manager.BannerManager;
 import com.zhpan.bannerview.manager.BannerOptions;
+import com.zhpan.bannerview.transform.OverlapSliderTransformer;
 import com.zhpan.bannerview.transform.PageTransformerFactory;
 import com.zhpan.bannerview.transform.ScaleInTransformer;
 import com.zhpan.bannerview.utils.BannerUtils;
@@ -80,6 +81,8 @@ public class BannerViewPager<T, VH extends BaseViewHolder> extends RelativeLayou
 
     private MarginPageTransformer mMarginPageTransformer;
 
+    private ViewPager2.PageTransformer mPageTransformer;
+
     private ViewPager2.OnPageChangeCallback mOnPageChangeCallback = new ViewPager2.OnPageChangeCallback() {
         @Override
         public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
@@ -331,10 +334,15 @@ public class BannerViewPager<T, VH extends BaseViewHolder> extends RelativeLayou
         int padding = bannerOptions.getPageMargin() + bannerOptions.getRevealWidth();
         recyclerView.setPadding(padding, 0, padding, 0);
         recyclerView.setClipToPadding(false);
-        addPageTransformer(new ScaleInTransformer(scale));
-        if (overlap) {
-            // TODO MULTI_PAGE_OVERLAP style supported
+        if (mPageTransformer != null) {
+            mCompositePageTransformer.removeTransformer(mPageTransformer);
+        }
+        if (overlap && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            mPageTransformer = new OverlapSliderTransformer(ViewPager2.ORIENTATION_HORIZONTAL, scale, scale, 0, 0);
+        } else {
+            mPageTransformer = new ScaleInTransformer(scale);
         }
+        addPageTransformer(mPageTransformer);
     }
 
     private int getInterval() {

+ 12 - 0
bannerview/src/main/java/com/zhpan/bannerview/transform/Extensions.kt

@@ -0,0 +1,12 @@
+package com.zhpan.bannerview.transform
+
+import android.content.res.Resources
+
+fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()
+fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()
+
+fun Float.cube(): Float = this * this * this
+fun Int.cube(): Int = this * this * this
+
+fun Float.sqr(): Float = this * this
+fun Int.sqr(): Int = this * this

+ 85 - 0
bannerview/src/main/java/com/zhpan/bannerview/transform/OverlapSliderTransformer.kt

@@ -0,0 +1,85 @@
+package com.zhpan.bannerview.transform
+
+import android.os.Build
+import android.view.View
+import androidx.annotation.RequiresApi
+import androidx.viewpager2.widget.ViewPager2
+import kotlin.math.abs
+import kotlin.math.max
+
+/**
+ * @param: gives veiwpager2 orientation
+ * 来源:https://github.com/KoderLabs/finite-cover-flow/blob/dev/lib/src/main/java/com/saeed/finiteflow/lib/OverlapSliderTransformer.kt
+ */
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+class OverlapSliderTransformer(
+    private val orientation: Int,
+    private val minScale: Float = 0f,
+    private val unSelectedItemRotation: Float = 0f,
+    private val unSelectedItemAlpha: Float = 0f,
+    private val itemGap: Float = 0f
+) : ViewPager2.PageTransformer {
+
+    init {
+        require(minScale in 0f..1f) { "minScale value should be between 1.0 to 0.0" }
+        require(unSelectedItemAlpha in 0f..1f) { "unSelectedItemAlpha value should be between 1.0 to 0.0" }
+    }
+
+    private val scalingValue = 0.2f
+
+    override fun transformPage(page: View, position: Float) {
+        page.apply {
+            elevation = -abs(position)
+
+            val delta = max(1f - abs(position * (1 - 0.5f)), 0.5f)
+
+            if (unSelectedItemRotation != 0f) {
+                val rotation =
+                    (1 - delta) * if (position > 0) unSelectedItemRotation else -unSelectedItemRotation
+
+                rotationY = rotation
+            }
+
+            val scaleDelta = abs(position * scalingValue)
+            val scale = max(1f - scaleDelta, minScale)
+
+            scaleX = scale
+            scaleY = scale
+
+            when (orientation) {
+                ViewPager2.ORIENTATION_HORIZONTAL -> {
+                    translationX =
+                        position * (itemGap.toInt() / 2).toPx() +
+                                if (position > 0) {
+                                    (-width * (1f - scale))
+                                } else {
+                                    (width * (1f - scale))
+                                }
+                }
+                ViewPager2.ORIENTATION_VERTICAL -> {
+                    translationY = position * (itemGap.toInt()).toPx() +
+                            if (position > 0) {
+                                (-width * (1f - scale))
+                            } else {
+                                (width * (1f - scale))
+                            }
+                }
+                else -> throw IllegalArgumentException("Gives correct orientation value, ViewPager2.ORIENTATION_HORIZONTAL or ViewPager2.ORIENTATION_VERTICAL")
+            }
+
+            if (unSelectedItemAlpha != 1f) {
+                alpha = when {
+                    position >= -1f && position <= 1f -> { // (0, 1]
+                        // page move from right to center.
+                        0.5f + ((1 - abs(position)) * 0.5f)
+                    }
+                    else -> {
+                        0.5f / abs(position * position)
+
+                    }
+                }
+            }
+        }
+    }
+
+}