【问题标题】:How to clip ImageView's corner's (rounded corners) off-screen如何在屏幕外剪辑 ImageView 的角(圆角)
【发布时间】:2019-04-20 00:04:40
【问题描述】:

我已将图像加载到四角圆角的视图寻呼机中。但是,出于设计原因,我只希望在解决 viewpager 时将顶角变圆,但在更改页面时让所有角都变圆。我通过将所有角都弄圆并将图像向下推约 8dp 来实现这一点。

我遇到的问题是,即使我已经使用 glide 的.transform(new RoundedCorners(8)) 将所有角落都弄圆了,但当滑动查看器时,它只会将顶角显示为圆形。我已经发布了一些截图:

ViewPager 入驻:

ViewPager 移动:

我应该提一下,我正在使用 PageTransformer 为页面之间的过渡设置动画,这就是第二个屏幕截图中页面缩小的原因。 这是完整的 Glide 代码:

    Glide.with(albumArt)
            .load(trackModel.getAlbumCoverArtUrl())
            .apply(new RequestOptions()
                    .fitCenter()
                    .transform(new RoundedCorners(8)))
            .into(albumArt);

我还尝试为 ImageView 定义轮廓并设置setClipToOutline(true),如下所示:

    albumArt.setClipToOutline(true);
    albumArt.setOutlineProvider(new ViewOutlineProvider() {
        @Override
        public void getOutline(View view, Outline outline) {
            outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 16);
        }
    });

但是,这会导致以下结果,这不是我想要的:ViewPager 解决时所有角都变圆:

我尝试在 XML 中更改 ImageView 上的 layout_margins 以及 ImageView 的容器片段,但是在解决 ViewPager 时,这总是使所有角都变圆并且可见。

我希望所有的角都变圆,但是当 ViewPager 确定底角被“推”出屏幕时,你只会看到顶角是圆角的。当 ViewPager 被滑动时,我希望所有的角都可见并变圆。

这是完整的类和 XML:

类:

public class NowPlayingPageFragment extends Fragment {
    private static final String TAG = "NowPlayingPageFragment";


    public static NowPlayingPageFragment newInstance(TrackModel trackModel) {
        NowPlayingPageFragment fragment = new NowPlayingPageFragment();
        Bundle argument = new Bundle();
        argument.putSerializable(TrackModel.class.getSimpleName(), trackModel);
        fragment.setArguments(argument);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             Bundle savedInstanceState) {
        ViewGroup rootView = (ViewGroup) inflater.inflate(
                R.layout.now_playing_page, container, false);

        Bundle arguments = getArguments();
        TrackModel trackModel = (TrackModel) arguments.getSerializable(TrackModel.class.getSimpleName());
        Log.d(TAG, "NowPlayingPage: " + trackModel.getAlbumCoverArtUrl());
        ImageView albumArt = rootView.findViewById(R.id.nowPlayingAlbumArtPage);

//          Alternate method to round corners

//        albumArt.setClipToOutline(true);
//        albumArt.setOutlineProvider(new ViewOutlineProvider() {
//            @Override
//            public void getOutline(View view, Outline outline) {
//                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 16);
//            }
//        });

        Log.d(TAG, "NowPlayingPage: setClipToOutline" + albumArt.getClipToOutline());

        Glide.with(albumArt)
                .load(trackModel.getAlbumCoverArtUrl())
                .apply(new RequestOptions()
                        .fitCenter()
                        .transform(new RoundedCorners(8))
                )
                .into(albumArt);

        return rootView;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

}

应该提到该布局嵌套在 viewpager 片段布局内,该布局嵌套在底页布局内。

XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"

    android:layout_height="match_parent"
    android:layout_marginTop="0dp"
    android:background="@drawable/round_corner_dialog"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/nowPlayingAlbumArtPage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:contentDescription="@string/album_art_large"
        android:cropToPadding="false"
        android:scaleType="centerCrop"
        android:visibility="visible" />
</LinearLayout>

【问题讨论】:

  • 请分享您的整个班级和 xml 布局。

标签: android layout android-viewpager imageview android-glide


【解决方案1】:

我可以通过使用布局的平移和缩放属性来解决这个问题!

【讨论】:

    【解决方案2】:

    对于任何想知道如何做到这一点的人,请看看这个项目。 ViewPager2Demo

    诀窍是在 transformPage 之间交替的 2 个视图始终具有相同的值

    cap 保证在提供一致性的任一视图中具有 0 到 0.5 之间的值

    val cap = min(abs(position), abs(1 - position)).toDouble()
    

    ExponentialPlateau定义

    private fun expPlateau(ym: Double, y0: Double, k: Double, x: Double): Double {
           return ym - (ym - y0) * exp(-k * x)
    }
    

    适合已经熟悉 ViewPager2 的人的课程。

    class ZoomOutPageTransformer : ViewPager2.PageTransformer {
    
        /**
         *  The position is fed to this function with an alternating order between the 2 views showing on the screen
         */
        override fun transformPage(view: View, position: Float) {
            view.apply {
                when {
                    position < -1 -> { // [-Infinity,-1)
                        // This page is way off-screen to the left.
                        alpha = 0f
                    }
                    position <= 1 -> { // [-1,1]
                        val scaleFactor = max(MIN_SCALE, 1 - abs(position))
                        // to always get the same value - this will essentially cap it at 0.5
                        val cap = min(abs(position), abs(1 - position)).toDouble()
                        // Exponential plateau function
                        val radius = expPlateau(YM,Y0, K, cap).toFloat()
    
                        // Scale the page down (between MIN_SCALE and 1)
                        scaleX = scaleFactor
                        scaleY = scaleFactor
    
                        setCornerRadius(view, radius)
                    }
                    else -> { // (1,+Infinity]
                        // This page is way off-screen to the right.
                        alpha = 0f
                    }
                }
            }
        }
    
    
        private fun setCornerRadius(view: View, radius: Float) {
            val drawable = (((view as FrameLayout).children.first() as ConstraintLayout).children.first().background as GradientDrawable)
            drawable.cornerRadius = radius
            (view.children.first() as ConstraintLayout).children.first().background = drawable
        }
    
        /**
         * y0 is the starting population (same units as y)
         * ym is the maximum population (same units as y)
         * k determines is the rate constant (inverse of x units)
         */
        private fun expPlateau(ym: Double, y0: Double, k: Double, x: Double): Double {
           return ym - (ym - y0) * exp(-k * x)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-26
      • 1970-01-01
      • 2017-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-24
      相关资源
      最近更新 更多