I've made a custom popupBackground with a corner radius of 16dp. The problem is, the items inside that popup may have a background color that doesn't go round following its parent popup, and I'm lost about how to do it since I don't see any "ClipToBounds" kind of property. The same happens with the ripple effect when tapping an item. An image representing what I have right now and the code used to generate it:
Spinner definition:
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/ItemOptionsSpinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:dropDownWidth="wrap_content"
android:popupBackground="@drawable/spinner_background"
android:paddingRight="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="1"
android:spinnerMode="dropdown"
android:visibility="invisible" />
spinner_background.xml inside drawable folder:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="16dp" />
<solid android:color="?android:colorBackground" />
</shape>
SpinnerItemLineDropLayout.xml, the view used to display each item:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/MainLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:paddingHorizontal="@dimen/activityHorizontalPadding"
android:paddingVertical="@dimen/activityVerticalPadding"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/ItemText"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/CheckImage"
style="@style/DefaultTextAppearance.Medium.Big" />
<ImageView
android:id="@+id/CheckImage"
android:paddingLeft="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/HelpText"
app:layout_constraintRight_toRightOf="parent"
android:src="@drawable/ic_check_black_18dp"
android:tint="@color/colorPrimaryDark"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
The code I'm using inside the adapter to populate the items, just to showcase how I'm setting the background color of the item itself, depending on if the item is selected or not by the spinner:
public override View GetDropDownView(Int32 position, View convertView, ViewGroup parent)
{
var view = convertView ?? (parent?.Context == null ? null : LayoutInflater.FromContext(parent.Context)?.Inflate(Resource.Layout.SpinnerItemLineDropLayout, null));
var mainLayout = view.FindViewById<ConstraintLayout>(Resource.Id.MainLayout);
var itemTextView = view.FindViewById<TextView>(Resource.Id.ItemText);
var checkImageView = view.FindViewById<ImageView>(Resource.Id.CheckImage);
itemTextView.Text = this._items[position].Text.GetText();
checkImageView.SetImageResource(this.SelectedPosition == position ? Resource.Drawable.ic_check_black_18dp : 0);
if (this.SelectedPosition == position)
mainLayout.SetBackgroundColor(Color.ParseColor(view.Context.GetString(Resource.Color.colorControlHighlight)));
return view;
}
This reason is BackgroundColor
of SelectedItem will affect the style of spinner DropDownView. If you not set selected color for item, you will not see this phenomenon.
If you need to set BackgroundColor
for SelectedItem, there is a way to reduce the effect for DropDownView. But this is not a workaround, because it can not fully solve this phenomenon.
Sample code as follows:
if (this.SelectedPosition == position)
GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.SetShape(ShapeType.Rectangle);//shape
gradientDrawable.SetCornerRadius(16f);//set circle Radius
gradientDrawable.SetColor(Resource.Color.ripple_material_dark);//background color
mainLayout.SetBackgroundDrawable(gradientDrawable);//set backgroundcolor
Here we use SetBackgroundDrawable
to set color, becasue this can set with a shape.
In addition, you could modify the spinner_background.xml
code to reduce their difference:
<?xml version="1.0" encoding="utf-8" ?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp" />
<solid android:color="?android:colorBackground" />
</shape>
The effect:
============================Update==================================
As dbalboa's comment, there is another possible solution for this, and also can use SetBackgroundColor
method to set color.That is putting <padding android:top="15dip" android:bottom="15dip" />
inside the shape tag of the spinner_background.xml
.
The full code as follows:
<?xml version="1.0" encoding="utf-8" ?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp" />
<padding android:top="5dip" android:bottom="5dip"/>
<solid android:color="?android:colorBackground" />
</shape>
Then the effect as follows: