Search code examples
androidlayoutandroid-viewpagerimageviewandroid-glide

How to clip ImageView's corner's (rounded corners) off-screen


I have images loaded into a view pager with the corners rounded. However, for design reasons, I only want the top corners rounded when the viewpager is settled, but to have all the corners appear rounded when pages are being changed. I've achieved this by rounding all the corners and pushing the image down about 8dp.

The problem I'm having is that even though I've rounded all the corners using glide's .transform(new RoundedCorners(8)), when the viewpager is swiped it only shows the top corners as rounded. I've posted some screenshots:

ViewPager settled:
ViewPager settled

ViewPager moving:
ViewPager moving

I should mention that I'm using a PageTransformer to animate the transition between pages which is why the pages are shrinked in the second screenshot. Here's the full Glide code:

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

I've also tried defining an outline for the ImageView and setting setClipToOutline(true) like below:

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

However this results in the following which is not what I want: All corners rounded when ViewPager settled:
All corners rounded when ViewPager settled

I tried changing the layout_margins on the ImageView in XML as well as the ImageView's container fragment however this always leaves all corners rounded and visible when the ViewPager is settled.

What I'd like to happen is for all the corners to be rounded, but when the ViewPager is settled for the bottom corners to be "pushed" off screen, so that you only see the top corners as rounded. When the ViewPager is being swiped I'd like for all the corners to be visible and rounded.

Here is the full class and XML:

Class:

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

}

Should mention that the layout is nested inside a viewpager fragment layout which is nested inside a bottomsheet layout.

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>

Solution

  • I was able to solve this by playing with the translate and scale properties of the layout!