简体   繁体   中英

Android: drawable ring shape multi-gradient

I'm trying to achieve something like the following:

the image inside is not too much of a problem, but the ring appears to be one. I was able to do this:

using:

<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>

as you can see, this only takes 3 colors. So I tried to do it programmatically:

val ring = 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)
            )
        )

            ring.shape = GradientDrawable.OVAL
            ring.thickness = resources.getDimension(R.dimen.all_time_best_frame_thickness).toInt()
            binding.goldFrame.background = ring

This doesn't draw anything, so I'm sure I'm missing something. Also ring.thickness is only available on API 29 and my min is 23. So I need to find some alternative.

Layout is:

<LinearLayout
                        android:id="@+id/gold_frame"
                        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_photo_margin"
                            app:shapeAppearanceOverlay="@style/CircleImageView" />
                    </LinearLayout>

Any idea on how to approach this?

I couldn't achieve it 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM