I have a weird issue when the selection is highlighted in a recycler view. This problem occurs as of API level 30 and above as per my tests. I did not observed any problem like this within the lower API levels, at least APIs below 28.
A screenshot of API 30 | A screenshot of API 27 |
---|---|
This screenshot is taken from a Motorola G5S Plus which running Android 11 | This one is taken from General Mobile 6 which is running Android 8.1.0 |
Both phones was running the same version of the application. As you can see in the left picture there is a band within the highlighted area. In this area there are 2 discrete TextView
s and some gap between them.
Let's take a look at the highlighting color xml named him_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="0.4" android:color="?attr/colorSecondaryVariant" android:state_activated="true"/>
<item android:color="?attr/colorSurface"/>
</selector>
The following xml is the list item design.
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<import type="android.view.View"/>
<import type="com.himtec.himtec_kontrol.ui.viewmodel.AygitListelemeVM"/>
<variable name="kipSurukle" type="boolean"/>
<variable name="gozde" type="boolean"/>
</data>
<com.himtec.himtec_kontrol.ui.AygitMaterialCardView
android:id="@ id/amcv_aygit"
style="@style/Widget.Himtec.MaterialCardView.Elevated.RoundCorners.Large"
android:layout_width="match_parent"
android:layout_height="@dimen/him_card_device_height"
android:layout_margin="@dimen/him_card_device_margin"
android:checkable="false"
android:clickable="true"
android:clipChildren="true"
android:clipToPadding="false"
android:focusable="true"
app:cardBackgroundColor="@color/him_selector" <!-- I use that color selector as card's background color to highlight it when it is selected -->
app:cardMaxElevation="@dimen/him_card_drag_elevation"
app:cardPreventCornerOverlap="false">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@ id/cl_aygit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:duplicateParentState="true">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:background="?attr/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/gl_aygit_model_icerik_hiza"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@ id/iv_nokta_simge"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@string/cd_aygitSimgesi"
android:duplicateParentState="true"
android:scaleType="center"
android:tint="?attr/colorSurface"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@ id/gl_aygit_model_icerik_hiza"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/him_aygit_simge_selector"
tools:srcCompat="@drawable/him_aygit_simge_selector" />
<com.google.android.material.textview.MaterialTextView
android:id="@ id/tv_nokta_ad"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:gravity="center_vertical"
android:padding="2dp"
android:singleLine="true"
android:textAlignment="gravity"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintBottom_toTopOf="@ id/mtv_eklenme"
app:layout_constraintEnd_toStartOf="@ id/tus_sirala"
app:layout_constraintStart_toStartOf="@ id/gl_aygit_model_icerik_hiza"
app:layout_constraintTop_toTopOf="parent"
app:layout_goneMarginEnd="@dimen/him_card_content_padding_8dp" />
<com.google.android.material.textview.MaterialTextView
android:id="@ id/mtv_eklenme"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:gravity="center_vertical"
android:padding="2dp"
android:singleLine="true"
android:text="@string/sc_eklendi"
android:textAlignment="gravity"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="@ id/mtv_son_baglanma"
app:layout_constraintStart_toStartOf="@ id/gl_aygit_model_icerik_hiza"
app:layout_constraintTop_toBottomOf="@ id/tv_nokta_ad"
app:layout_constraintVertical_chainStyle="packed" />
<com.google.android.material.textview.MaterialTextView
android:id="@ id/mtv_eklenme_deger"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:gravity="center_vertical"
android:padding="2dp"
android:singleLine="true"
android:textAlignment="gravity"
android:textSize="12sp"
app:layout_constraintBaseline_toBaselineOf="@ id/mtv_eklenme"
app:layout_constraintEnd_toStartOf="@ id/tus_sirala"
app:layout_constraintStart_toEndOf="@id/br_aygit_model_alt_bilgi_baslik"
app:layout_goneMarginEnd="@dimen/him_card_content_padding_8dp" />
<com.google.android.material.textview.MaterialTextView
android:id="@ id/mtv_son_baglanma"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:gravity="center_vertical"
android:padding="2dp"
android:singleLine="true"
android:text="@string/sc_sonBaglanti"
android:textAlignment="gravity"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@ id/gl_aygit_model_icerik_hiza"
app:layout_constraintTop_toBottomOf="@ id/mtv_eklenme" />
<com.google.android.material.textview.MaterialTextView
android:id="@ id/mtv_son_baglanma_deger"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:gravity="center_vertical"
android:padding="2dp"
android:singleLine="true"
android:textAlignment="gravity"
android:textSize="12sp"
app:layout_constraintBaseline_toBaselineOf="@ id/mtv_son_baglanma"
app:layout_constraintEnd_toStartOf="@ id/tus_sirala"
app:layout_constraintStart_toEndOf="@id/br_aygit_model_alt_bilgi_baslik"
app:layout_goneMarginEnd="@dimen/him_card_content_padding_8dp" />
<Button
android:id="@ id/tus_sirala"
style="@style/Widget.Himtec.Button.TextButton"
android:layout_width="36dp"
android:layout_height="0dp"
android:visibility="@{kipSurukle ? View.VISIBLE : View.GONE}"
app:icon="@drawable/him_surukle_24"
app:iconPadding="0dp"
app:iconSize="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Barrier
android:id="@ id/br_aygit_model_alt_bilgi_baslik"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="mtv_eklenme,mtv_son_baglanma"
tools:layout_editor_absoluteX="169dp" />
<androidx.constraintlayout.widget.Guideline
android:id="@ id/gl_aygit_model_icerik_hiza"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="82dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.himtec.himtec_kontrol.ui.AygitMaterialCardView>
</layout>
In both phones the same item xml and color exist. The highlighting is made by activating the AygitMaterialcardView
which is a custom class that extends MaterialCardView
. The activation is made by setting the View.setActivated()
method to true.
The custom card implementation:
public class AygitMaterialCardView extends MaterialCardView {
private static final String E = AygitMaterialCardView.class.getSimpleName();
/* Uygulamaya özel tanımlanan durumlar */
private static final int DURUM_HICBIRI = 0;
private static final int DURUM_GOZDE = 1;
private static final int DURUM_SURUKLE = 2;
private static final int[] HIM_AYGIT_DURUMLAR = {
R.attr.durum_hicbiri,
R.attr.durum_gozde,
R.attr.durum_surukleme
};
private boolean gozde;
private boolean surukleme;
private int durum;
public AygitMaterialCardView(Context context) {
super(context);
}
/* XML kaynaktan ilklenirken bu oluşturucu çağrılıyor */
public AygitMaterialCardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableStates = super.onCreateDrawableState(extraSpace 1);
// Fazladan gözde durumunu ekleyeceğiz
if(gozde) {
int[] d = { HIM_AYGIT_DURUMLAR[DURUM_GOZDE] };
mergeDrawableStates(drawableStates, d);
}
if(surukleme) {
int[] d = { HIM_AYGIT_DURUMLAR[DURUM_SURUKLE] };
mergeDrawableStates(drawableStates, d);
}
return drawableStates;
}
public boolean isGozde() {
return gozde;
}
public void setGozde(boolean gozde) {
if(gozde == this.gozde) return;
this.gozde = gozde;
refreshDrawableState();
invalidate();
requestLayout();
}
public boolean isSurukleme() {
return surukleme;
}
public void setSurukleme(boolean surukleme) {
if(surukleme == this.surukleme) return;
this.surukleme = surukleme;
refreshDrawableState();
invalidate();
requestLayout();
}
}
CodePudding user response:
Attributes to Mike M. for the solution for this matter. Thanks to his guidance that I could see that the cause of the issue was the translucent background color which caused by alpha settings of the selector.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="0.4" android:color="?attr/colorSecondaryVariant" android:state_activated="true"/>
<item android:color="?attr/colorSurface"/>
</selector>
There are two solutions to get rid of that glitch:
- Is to set to elevation of the card to zero and trade-off the shadow.
- Is to remove the alpha from the selection color.
Since I didn't want to trade-off the shadow for my design requirements, I decided to get rid of the alpha and make the selection color totally solid.