0

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
enter image description here enter image description here
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 TextViews 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();
    }
}
Stefano Sansone
  • 2,377
  • 7
  • 20
  • 39
Kozmotronik
  • 2,080
  • 3
  • 10
  • 25
  • 1
    That looks like Android's elevation shadow glitch that you're seeing because of the translucent background when it's activated; i.e., the `android:alpha="0.4"`. You could probably test that by setting the elevation to zero, and/or removing the alpha, and see if it's still there. – Mike M. May 26 '22 at 14:27
  • I tested it with zero elevation, you nailed it, the band has gone. But why especially at that rectangle and not the all highlighted area? I need to elevate the cards for my design requirements. Is there a way to get rid of that band without setting the elevation of card to zero? – Kozmotronik May 26 '22 at 14:40
  • Btw, I'm not sure if I'm understanding the requirements correctly, but if the background _behind_ the `AygitMaterialCardView` is always going to be a solid color, then you could conceivably fix this without having to mess with the shadow stuff. If you calculate the solid color that would result from blending the "behind" background color and your `AygitMaterialCardView`'s activated color with its alpha, then you could just set `AygitMaterialCardView`'s activated state to that color, and hide the glitch. Make sense? It might have to be done programmatically, though, 'cause it's in a state list. – Mike M. May 28 '22 at 17:55
  • Yes, you're right. *No shadows at all* is **not my goal**. And yes I want the shadows. You mean that the glicth color is blending from behind the background color of `AygitMaterialCardView` aka `cardBackgroundColor`? – Kozmotronik May 28 '22 at 18:36
  • Right. When your card's background goes to the activated state, the alpha goes to 0.4 and you can see through it, and you're seeing the shadow glitch behind it blend with your alpha color. That's the dark margin around the center lighter rectangle, which is the right color. If you use a color without an alpha, it won't be translucent so you won't see the shadow glitch. That's why I wasn't sure about the requirements. Does that really need to be translucent, so you can see the parent `ViewGroup`'s background through it? Or do you actually just need the color change, basically? – Mike M. May 28 '22 at 18:49
  • I'm not sure if I'm explaining all of this clearly at all, but [this mock-up of your setup](https://i.stack.imgur.com/LB311.png) might help to visualize what's happening. The top item is a shadow all by itself, so you can see what that looks like. The middle one is a `CardView` of the same shape with your `him_selector` color background, in the default state. The bottom item is the same but in the activated state. Note that the shadows vary with their on-screen position, which is why the bottom one looks a little different than the top. – Mike M. May 28 '22 at 19:04
  • @MikeM. thank you very much. Now with the help of that illustration I get it totally. But what confused me is that this problem does not exist or occur in API levels like 27. Anyway, I will remove the alpha from selector color and see how it will look like after this weekend. And it's more likely that this to be the solution for my question. I will let you know the results, thank you so much again. – Kozmotronik May 28 '22 at 20:53
  • No problem. Yeah, at first I didn't realize that the two images in the question were different Android versions. I didn't look closely enough, and thought they were before/after images. I'm not sure how to explain that. I kind of assumed that you might have different themes/styles for a certain API level; e.g., you might have a `res/values-v??/` folder with different settings than those the default `res/values/` folder (or maybe even a versioned `/res/color-v??/` folder). Didn't mention it earlier 'cause I didn't want to cause any more confusion. :-) I am curious about that, though. Cheers! – Mike M. May 28 '22 at 21:03
  • I figured out the discrepancy between versions. It seems it's actually the device's screen that's the main factor there, and the metrics on that General Mobile just end up with the calculations rendering a barely noticeable shadow with your settings on that phone. [Here's a closer mock-up](https://i.stack.imgur.com/uQFpV.png), with heightened elevations of 20dp, and the same general progression as that first mock-up: the top one shows a completely transparent background so you can see the bare shadow, the middle shows the `him_selector` background in default state, and the last is activated. – Mike M. May 29 '22 at 04:55
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/245139/discussion-between-kozmotronik-and-mike-m). – Kozmotronik May 29 '22 at 07:29
  • Hi @MikeM. I need help on [this](https://stackoverflow.com/questions/73500009/selectiontracker-problem-after-restoration) issue, do you mind? – Kozmotronik Aug 26 '22 at 12:23
  • Sorry, I've never even seen `SelectionTracker` used before, so I wouldn't know what to suggest. That sounds crazy, though! – Mike M. Aug 26 '22 at 13:25
  • Oh I see, never mind, I think the selection tracker is a hard and rare topic. Thank you for your time though. – Kozmotronik Aug 26 '22 at 13:47

1 Answers1

0

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:

  1. Is to set to elevation of the card to zero and trade-off the shadow.
  2. 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.

Kozmotronik
  • 2,080
  • 3
  • 10
  • 25