所选项目表面上的奇怪带颜色
Weird Band Color on the Selected Item's Surface
当在回收站视图中突出显示选择时,我遇到了一个奇怪的问题。根据我的测试,此问题发生在 API 级别 30 及以上。我没有在较低的 API 水平内观察到任何此类问题,至少 APIs 在 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
两部手机 运行 应用程序的版本相同。正如您在左图中看到的那样,在突出显示的区域内有一条带。在这个区域有 2 个离散的 TextView
s 和它们之间的一些间隙。
我们来看看名为him_selector.xml:
的高亮颜色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>
以下xml为列表项设计
<?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>
两部手机中存在相同的项目 xml 和颜色。突出显示是通过激活 AygitMaterialcardView
实现的,它是扩展 MaterialCardView
的自定义 class。通过将 View.setActivated()
方法设置为 true 来进行激活。
自定义卡片实现:
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();
}
}
感谢 Mike M. 解决此问题。感谢他的指导,我可以看出问题的原因是由选择器的 alpha 设置引起的半透明背景色。
<?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>
有两种解决方案可以消除该故障:
- 就是把卡片的仰角设置为零,trade-off阴影。
- 就是去掉选区颜色的alpha。
由于我不想 trade-off 我的设计要求的阴影,我决定摆脱 alpha 并使选择颜色完全纯色。
当在回收站视图中突出显示选择时,我遇到了一个奇怪的问题。根据我的测试,此问题发生在 API 级别 30 及以上。我没有在较低的 API 水平内观察到任何此类问题,至少 APIs 在 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 |
两部手机 运行 应用程序的版本相同。正如您在左图中看到的那样,在突出显示的区域内有一条带。在这个区域有 2 个离散的 TextView
s 和它们之间的一些间隙。
我们来看看名为him_selector.xml:
的高亮颜色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>
以下xml为列表项设计
<?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>
两部手机中存在相同的项目 xml 和颜色。突出显示是通过激活 AygitMaterialcardView
实现的,它是扩展 MaterialCardView
的自定义 class。通过将 View.setActivated()
方法设置为 true 来进行激活。
自定义卡片实现:
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();
}
}
感谢 Mike M. 解决此问题。感谢他的指导,我可以看出问题的原因是由选择器的 alpha 设置引起的半透明背景色。
<?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>
有两种解决方案可以消除该故障:
- 就是把卡片的仰角设置为零,trade-off阴影。
- 就是去掉选区颜色的alpha。
由于我不想 trade-off 我的设计要求的阴影,我决定摆脱 alpha 并使选择颜色完全纯色。