Android: frame for circle image

Viewed 63

I'm struggling with the following:

I want to achieve this:

I've come to something with the following:

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/drawable_gold_frame">

    <com.google.android.material.imageview.ShapeableImageView
         android:id="@+id/gold_photo"
         android:layout_width="@dimen/all_time_best_photo_size"
         android:layout_height="@dimen/all_time_best_photo_size"
         android:layout_margin="@dimen/all_time_best_frame_thickness"
         app:shapeAppearanceOverlay="@style/CircleImageView" />
</LinearLayout>

<style name="CircleImageView" parent="">
     <item name="cornerFamily">rounded</item>
     <item name="cornerSize">50%</item>
</style>

<dimen name="all_time_best_photo_size">70dp</dimen>
<dimen name="all_time_best_frame_thickness">5dp</dimen>

<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="ring"
    android:thickness="@dimen/all_time_best_frame_thickness"
    android:useLevel="false">
    <gradient
        android:startColor="@color/gold_gradient_start"
        android:centerColor="@color/gold_gradient_end"
        android:endColor="@color/gold_gradient_start"
        android:angle="180" />
</shape>

the image iteself is then loaded using Glide. this looks like this:

where's the ring shape? well if I increase the margin for the ImageView it becomes visible:

android:layout_margin="20dp"

and android:layout_margin="15dp" (don't mind the color)

So the last one is the closest I can get, I guess I could fiddle around with margins and make it better, but I think that it might break with different device etc...

What I don't understand is why using the same dimen for the ring thickness and the ImageView margin doesn't work. Is there a more "safe" way to achieve this?

note that the frame size is the same in all pictures, I just cropped the screenshots very badly

1 Answers

I couldn't get a clean result with a ring shape, so what I ended up doing is:

<FrameLayout
                    android:id="@+id/gold_frame"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content">

                    <com.google.android.material.imageview.ShapeableImageView
                        android:id="@+id/gold_photo"
                        android:layout_width="@dimen/all_time_best_photo_size"
                        android:layout_height="@dimen/all_time_best_photo_size"
                        android:layout_margin="@dimen/all_time_best_frame_thickness"
                        app:shapeAppearanceOverlay="@style/CircleImageView" />
                </FrameLayout>

and

val medal = GradientDrawable(
            GradientDrawable.Orientation.LEFT_RIGHT, intArrayOf(
                ContextCompat.getColor(requireContext(), R.color.gold_gradient_1),
                ContextCompat.getColor(requireContext(), R.color.gold_gradient_2),
                ContextCompat.getColor(requireContext(), R.color.gold_gradient_3),
                ContextCompat.getColor(requireContext(), R.color.gold_gradient_4),
                ContextCompat.getColor(requireContext(), R.color.gold_gradient_5)
            )
        )

            medal.shape = GradientDrawable.OVAL
            binding.goldFrame.background = medal

This way I create a circle with gradient inside and then set it as background as the ImageView's container. Is not perfect as it doesn't work if you have transparency in the images you want, but works in my case.

Also, it can be improved via removing the container and doing:

<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/gold_photo"
    android:layout_width="@dimen/all_time_best_photo_size"
    android:layout_height="@dimen/all_time_best_photo_size"
    android:padding="@dimen/all_time_best_frame_thickness"
    app:shapeAppearanceOverlay="@style/CircleImageView" />

and setting the background to the ImageView itself, unfortunately ShapeableImageView scales the background according to padding (standard ImageView doesn't do it).

A user created the issue on github and solved the problem via PR, which has been merged but not yet released, check out issue and pull request.

I'll post an update if I ever manage to do it using Ring shape.

Related