From f0465947164748a9616d68b205ffc9c6450a2c5d Mon Sep 17 00:00:00 2001 From: zhpanvip Date: Mon, 21 Jun 2021 12:49:43 +0800 Subject: [PATCH] Restore OutLineProvider. --- .../zhpan/banner/fragment/OthersFragment.java | 3 +- app/src/main/res/layout/fragment_others.xml | 2 +- .../com/zhpan/bannerview/BannerViewPager.java | 48 +++++++++++++-- .../bannerview/manager/BannerOptions.java | 36 +++++------ .../provider/OvalViewOutlineProvider.java | 60 +++++++++++++++++++ .../provider/RoundViewOutlineProvider.java | 33 ++++++++++ .../bannerview/provider/ViewStyleSetter.java | 56 +++++++++++++++++ 7 files changed, 214 insertions(+), 24 deletions(-) create mode 100644 bannerview/src/main/java/com/zhpan/bannerview/provider/OvalViewOutlineProvider.java create mode 100644 bannerview/src/main/java/com/zhpan/bannerview/provider/RoundViewOutlineProvider.java create mode 100644 bannerview/src/main/java/com/zhpan/bannerview/provider/ViewStyleSetter.java diff --git a/app/src/main/java/com/example/zhpan/banner/fragment/OthersFragment.java b/app/src/main/java/com/example/zhpan/banner/fragment/OthersFragment.java index 206a3eb..249188c 100644 --- a/app/src/main/java/com/example/zhpan/banner/fragment/OthersFragment.java +++ b/app/src/main/java/com/example/zhpan/banner/fragment/OthersFragment.java @@ -99,6 +99,7 @@ private void initRadioGroup() { } else if (checkedId == R.id.rb_vector_drawable) { setDrawableIndicator(getVectorDrawableIndicator()); } else if (checkedId == R.id.rb_round_corner) { + mViewPager.setRoundCorner(1); setRoundCorner(); } }); @@ -109,7 +110,7 @@ private void setRoundCorner() { int dp36 = getResources().getDimensionPixelOffset(R.dimen.dp_36); mViewPager .setRoundCorner(dp36, 0, 0, dp36) - .refreshData(getPicList(4)); + .create(getPicList(4)); } private void setDrawableIndicator(IIndicator indicator) { diff --git a/app/src/main/res/layout/fragment_others.xml b/app/src/main/res/layout/fragment_others.xml index 603f4e8..cf29b7f 100644 --- a/app/src/main/res/layout/fragment_others.xml +++ b/app/src/main/res/layout/fragment_others.xml @@ -92,7 +92,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="@dimen/dp_10" android:layout_marginEnd="15dp" - android:text="Round Corner" + android:text="Top Left Bottom Right Round Corner" android:textSize="@dimen/sp_16" /> diff --git a/bannerview/src/main/java/com/zhpan/bannerview/BannerViewPager.java b/bannerview/src/main/java/com/zhpan/bannerview/BannerViewPager.java index 0321a2f..2176ca3 100644 --- a/bannerview/src/main/java/com/zhpan/bannerview/BannerViewPager.java +++ b/bannerview/src/main/java/com/zhpan/bannerview/BannerViewPager.java @@ -2,8 +2,12 @@ import android.content.Context; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.RectF; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Parcelable; @@ -28,6 +32,7 @@ import com.zhpan.bannerview.manager.BannerManager; import com.zhpan.bannerview.manager.BannerOptions; import com.zhpan.bannerview.provider.ReflectLayoutManager; +import com.zhpan.bannerview.provider.ViewStyleSetter; import com.zhpan.bannerview.utils.BannerUtils; import com.zhpan.indicator.IndicatorView; import com.zhpan.indicator.annotation.AIndicatorSlideMode; @@ -83,8 +88,8 @@ public void run() { }; private RectF mRadiusRectF; - private Path mRadiusPath; + private Paint mPaint; private int startX, startY; @@ -298,6 +303,7 @@ private void initBannerData() { if (list != null) { setIndicatorValues(list); setupViewPager(list); + initRoundCorner(); } } @@ -360,13 +366,27 @@ protected void dispatchDraw(Canvas canvas) { if (mRadiusRectF != null && mRadiusPath != null) { mRadiusRectF.right = this.getWidth(); mRadiusRectF.bottom = this.getHeight(); - mRadiusPath.addRoundRect(mRadiusRectF, mBannerManager.getBannerOptions().getRoundRectRadius(), + mRadiusPath.addRoundRect(mRadiusRectF, + mBannerManager.getBannerOptions().getRoundRectRadiusArray(), Path.Direction.CW); - canvas.clipPath(mRadiusPath); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + canvas.clipPath(mRadiusPath); + } else { + if (mPaint != null) { + canvas.drawPath(mRadiusPath, mPaint); + } + } } super.dispatchDraw(canvas); } + private void initRoundCorner() { + int roundCorner = mBannerManager.getBannerOptions().getRoundRectRadius(); + if (roundCorner > 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + ViewStyleSetter.applyRoundCorner(this, roundCorner); + } + } + private void setupViewPager(List list) { if (mBannerPagerAdapter == null) { throw new NullPointerException("You must set adapter for BannerViewPager"); @@ -521,7 +541,8 @@ public BaseBannerAdapter getAdapter() { * @param radius round radius */ public BannerViewPager setRoundCorner(int radius) { - return setRoundCorner(radius, radius, radius, radius); + mBannerManager.getBannerOptions().setRoundRectRadius(radius); + return this; } /** @@ -537,6 +558,10 @@ public BannerViewPager setRoundCorner(int topLeftRadius, int topRightRadius, int bottomRightRadius) { mRadiusRectF = new RectF(); mRadiusPath = new Path(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + } mBannerManager.getBannerOptions() .setRoundRectRadius(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); return this; @@ -551,6 +576,20 @@ public BannerViewPager setRoundRect(int radius) { return setRoundCorner(radius); } + /** + * Set round rectangle effect for BannerViewPager. + * + * @param topLeftRadius top left round radius + * @param topRightRadius top right round radius + * @param bottomLeftRadius bottom left round radius + * @param bottomRightRadius bottom right round radius + */ + public BannerViewPager setRoundRect(int topLeftRadius, int topRightRadius, + int bottomLeftRadius, + int bottomRightRadius) { + return setRoundCorner(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); + } + /** * Enable/disable auto play * @@ -1105,7 +1144,6 @@ public BannerViewPager stopLoopWhenDetachedFromWindow(boolean stopLoopWhenDet } /** - * * @param showIndicatorWhenOneItem 只有一个item时是否显示指示器, * true:显示,false:不显示,默认值false */ diff --git a/bannerview/src/main/java/com/zhpan/bannerview/manager/BannerOptions.java b/bannerview/src/main/java/com/zhpan/bannerview/manager/BannerOptions.java index 2c31a87..2acf5ac 100644 --- a/bannerview/src/main/java/com/zhpan/bannerview/manager/BannerOptions.java +++ b/bannerview/src/main/java/com/zhpan/bannerview/manager/BannerOptions.java @@ -1,7 +1,5 @@ package com.zhpan.bannerview.manager; -import android.graphics.Path; -import android.graphics.RectF; import android.view.View; import androidx.viewpager2.widget.ViewPager2; @@ -11,8 +9,6 @@ import com.zhpan.indicator.enums.IndicatorOrientation; import com.zhpan.indicator.option.IndicatorOptions; -import java.util.Arrays; - import static com.zhpan.bannerview.transform.ScaleInTransformer.DEFAULT_MIN_SCALE; /** @@ -29,7 +25,6 @@ public BannerOptions() { pageMargin = BannerUtils.dp2px(20); rightRevealWidth = DEFAULT_REVEAL_WIDTH; leftRevealWidth = DEFAULT_REVEAL_WIDTH; - roundRadius = new float[8]; } public static final int DEFAULT_REVEAL_WIDTH = -1000; @@ -60,7 +55,9 @@ public BannerOptions() { private int scrollDuration; - private float[] roundRadius; + private float[] roundRadiusArray; + + private int roundRadius; private boolean userInputEnabled = true; @@ -126,7 +123,7 @@ public void setIndicatorSliderWidth(int normalWidth, int checkedWidth) { mIndicatorOptions.setSliderWidth(normalWidth, checkedWidth); } - public void showIndicatorWhenOnItem(boolean showIndicatorWhenOneItem){ + public void showIndicatorWhenOnItem(boolean showIndicatorWhenOneItem) { mIndicatorOptions.setShowIndicatorOneItem(showIndicatorWhenOneItem); } @@ -218,24 +215,29 @@ public void setIndicatorMargin(int left, int top, int right, int bottom) { mIndicatorMargin = new IndicatorMargin(left, top, right, bottom); } - public float[] getRoundRectRadius() { + public float[] getRoundRectRadiusArray() { + return roundRadiusArray; + } + + public int getRoundRectRadius() { return roundRadius; } public void setRoundRectRadius(int radius) { - setRoundRectRadius(radius, radius, radius, radius); + this.roundRadius = radius; } public void setRoundRectRadius(int topLeftRadius, int topRightRadius, int bottomLeftRadius, int bottomRightRadius) { - roundRadius[0] = topLeftRadius; - roundRadius[1] = topLeftRadius; - roundRadius[2] = topRightRadius; - roundRadius[3] = topRightRadius; - roundRadius[4] = bottomRightRadius; - roundRadius[5] = bottomRightRadius; - roundRadius[6] = bottomLeftRadius; - roundRadius[7] = bottomLeftRadius; + roundRadiusArray = new float[8]; + roundRadiusArray[0] = topLeftRadius; + roundRadiusArray[1] = topLeftRadius; + roundRadiusArray[2] = topRightRadius; + roundRadiusArray[3] = topRightRadius; + roundRadiusArray[4] = bottomRightRadius; + roundRadiusArray[5] = bottomRightRadius; + roundRadiusArray[6] = bottomLeftRadius; + roundRadiusArray[7] = bottomLeftRadius; } public int getScrollDuration() { diff --git a/bannerview/src/main/java/com/zhpan/bannerview/provider/OvalViewOutlineProvider.java b/bannerview/src/main/java/com/zhpan/bannerview/provider/OvalViewOutlineProvider.java new file mode 100644 index 0000000..9143d9f --- /dev/null +++ b/bannerview/src/main/java/com/zhpan/bannerview/provider/OvalViewOutlineProvider.java @@ -0,0 +1,60 @@ + +package com.zhpan.bannerview.provider; + +import android.annotation.TargetApi; +import android.graphics.Outline; +import android.graphics.Rect; +import android.os.Build; +import android.view.View; +import android.view.ViewOutlineProvider; + +/** + *
+ *   Created by zhangpan on 2018/12/26.
+ *   Description:圆形效果
+ * 
+ */ + +@TargetApi(Build.VERSION_CODES.LOLLIPOP) +public class OvalViewOutlineProvider extends ViewOutlineProvider { + + + public OvalViewOutlineProvider() {} + + @Override + public void getOutline(final View view, final Outline outline) { + Rect ovalRect = convertToCircleRect(new Rect(0, 0, view.getWidth(), view.getHeight())); + outline.setOval(ovalRect); + } + + /** + * 以矩形的中心点为圆心,较短的边为直径画圆 + * + * 注意, 由于整除省略了小数, (x/2)*2不一定等于x + * + * Currently, only Outlines that can be represented as a rectangle, circle, or round rect + * support clipping. + * + * @param rect + * @return + */ + private Rect convertToCircleRect(Rect rect) { + int left, top, right, bottom; + if(rect.width() > rect.height()) { + int dH = rect.height() / 2; + left = rect.centerX() - dH; + top = 0; + right = rect.centerX() + dH; + bottom = dH * 2; + } else { + int dW = rect.width() / 2; + left = 0; + top = rect.centerY() - dW; + right = dW * 2; + bottom = rect.centerY() + dW; + } + rect.set(left, top, right, bottom); + return rect; + } + +} diff --git a/bannerview/src/main/java/com/zhpan/bannerview/provider/RoundViewOutlineProvider.java b/bannerview/src/main/java/com/zhpan/bannerview/provider/RoundViewOutlineProvider.java new file mode 100644 index 0000000..63032a8 --- /dev/null +++ b/bannerview/src/main/java/com/zhpan/bannerview/provider/RoundViewOutlineProvider.java @@ -0,0 +1,33 @@ + + +package com.zhpan.bannerview.provider; + +import android.annotation.TargetApi; +import android.graphics.Outline; +import android.graphics.Rect; +import android.os.Build; +import android.view.View; +import android.view.ViewOutlineProvider; + +/** + *
+ *   Created by zhangpan on 2018/12/26.
+ *   Description:圆角效果
+ * 
+ */ + +@TargetApi(Build.VERSION_CODES.LOLLIPOP) +public class RoundViewOutlineProvider extends ViewOutlineProvider { + + private float mRadius;// 圆角弧度 + + public RoundViewOutlineProvider(float radius) { + this.mRadius = radius; + } + + @Override + public void getOutline(View view, Outline outline) { + Rect selfRect = new Rect(0, 0, view.getWidth(), view.getHeight());// 绘制区域 + outline.setRoundRect(selfRect, mRadius); + } +} diff --git a/bannerview/src/main/java/com/zhpan/bannerview/provider/ViewStyleSetter.java b/bannerview/src/main/java/com/zhpan/bannerview/provider/ViewStyleSetter.java new file mode 100644 index 0000000..077fe22 --- /dev/null +++ b/bannerview/src/main/java/com/zhpan/bannerview/provider/ViewStyleSetter.java @@ -0,0 +1,56 @@ + + +package com.zhpan.bannerview.provider; + +import android.os.Build; +import android.view.View; +import androidx.annotation.RequiresApi; + +/** + *
+ *   Created by zhangpan on 2018/12/26.
+ *   Description:为View设置圆角/圆形效果,支持View及ViewGroup,适用Android 5.1及以上系统。
+ * 
+ */ + +public class ViewStyleSetter { + + private ViewStyleSetter() {} + + /** + * 为View设置圆角效果 + * + * @param radius 圆角半径 + */ + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public static void applyRoundCorner(View target, float radius) { + if(target == null) { + return; + } + target.setClipToOutline(true);// 用outline裁剪内容区域 + target.setOutlineProvider(new RoundViewOutlineProvider(radius)); + } + + /** + * 设置View为圆形 + */ + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public static void applyCircle(View target) { + if(target == null) { + return; + } + target.setClipToOutline(true);// 用outline裁剪内容区域 + target.setOutlineProvider(new OvalViewOutlineProvider()); + } + + /** + * 清除View的圆角效果 + */ + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public static void clearShapeStyle(View target) { + if(target == null) { + return; + } + target.setClipToOutline(false); + } +}