Root Cause: The palette preview's text color inherits dynamic colors from the BC pattern, leading to insufficient contrast against some backgrounds. This wasn't a problem in the original design, as the BC pattern was introduced later. Solution: Set the palette preview text color to textColorPrimary to ensure the text remains legible against a wider range of background colors. Bug: 378775277 Flag: EXEMPT bugfix Test: atest PaletteListPreferenceTest Change-Id: I8efb9f9d916d618b450df169292202e499d8ac0d
213 lines
8.5 KiB
Java
213 lines
8.5 KiB
Java
/*
|
|
* Copyright (C) 2020 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings.accessibility;
|
|
|
|
import static android.graphics.drawable.GradientDrawable.Orientation;
|
|
|
|
import static com.android.settings.accessibility.AccessibilityUtil.getScreenHeightPixels;
|
|
import static com.android.settings.accessibility.AccessibilityUtil.getScreenWidthPixels;
|
|
|
|
import static com.google.common.primitives.Ints.max;
|
|
|
|
import android.content.Context;
|
|
import android.content.res.ColorStateList;
|
|
import android.graphics.Paint.FontMetrics;
|
|
import android.graphics.drawable.GradientDrawable;
|
|
import android.util.AttributeSet;
|
|
import android.view.Gravity;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.ColorInt;
|
|
import androidx.annotation.IntDef;
|
|
import androidx.core.text.TextUtilsCompat;
|
|
import androidx.preference.Preference;
|
|
import androidx.preference.PreferenceViewHolder;
|
|
|
|
import com.android.settings.R;
|
|
import com.android.settingslib.Utils;
|
|
|
|
import com.google.common.primitives.Floats;
|
|
import com.google.common.primitives.Ints;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.stream.Collectors;
|
|
|
|
/** Preference that easier preview by matching name to color. */
|
|
public final class PaletteListPreference extends Preference {
|
|
|
|
private final List<Integer> mGradientColors = new ArrayList<>();
|
|
private final List<Float> mGradientOffsets = new ArrayList<>();
|
|
|
|
@IntDef({
|
|
Position.START,
|
|
Position.CENTER,
|
|
Position.END,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@interface Position {
|
|
int START = 0;
|
|
int CENTER = 1;
|
|
int END = 2;
|
|
}
|
|
|
|
/**
|
|
* Constructs a new PaletteListPreference with the given context's theme and the supplied
|
|
* attribute set.
|
|
*
|
|
* @param context The Context this is associated with, through which it can access the current
|
|
* theme, resources, etc.
|
|
* @param attrs The attributes of the XML tag that is inflating the view.
|
|
*/
|
|
public PaletteListPreference(Context context, AttributeSet attrs) {
|
|
this(context, attrs, 0);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new PaletteListPreference with the given context's theme, the supplied
|
|
* attribute set, and default style attribute.
|
|
*
|
|
* @param context The Context this is associated with, through which it can access the
|
|
* current theme, resources, etc.
|
|
* @param attrs The attributes of the XML tag that is inflating the view.
|
|
* @param defStyleAttr An attribute in the current theme that contains a reference to a style
|
|
* resource that supplies default
|
|
* values for the view. Can be 0 to not look for
|
|
* defaults.
|
|
*/
|
|
public PaletteListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
setLayoutResource(R.layout.daltonizer_preview);
|
|
}
|
|
|
|
@Override
|
|
public void onBindViewHolder(PreferenceViewHolder holder) {
|
|
super.onBindViewHolder(holder);
|
|
|
|
final ViewGroup paletteView = holder.itemView.findViewById(R.id.palette_view);
|
|
initPaletteAttributes(getContext());
|
|
initPaletteView(getContext(), paletteView);
|
|
}
|
|
|
|
private void initPaletteAttributes(Context context) {
|
|
final int defaultColor = context.getColor(R.color.palette_list_gradient_background);
|
|
mGradientColors.add(Position.START, defaultColor);
|
|
mGradientColors.add(Position.CENTER, defaultColor);
|
|
mGradientColors.add(Position.END, defaultColor);
|
|
|
|
mGradientOffsets.add(Position.START, /* element= */ 0.0f);
|
|
mGradientOffsets.add(Position.CENTER, /* element= */ 0.5f);
|
|
mGradientOffsets.add(Position.END, /* element= */ 1.0f);
|
|
}
|
|
|
|
private void initPaletteView(Context context, ViewGroup rootView) {
|
|
if (rootView.getChildCount() > 0) {
|
|
rootView.removeAllViews();
|
|
}
|
|
|
|
final List<Integer> paletteColors = getPaletteColors(context);
|
|
final List<String> paletteData = getPaletteData(context);
|
|
|
|
final ColorStateList textColor =
|
|
Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary);
|
|
final float textPadding =
|
|
context.getResources().getDimension(R.dimen.accessibility_layout_margin_start_end);
|
|
final String maxLengthData =
|
|
Collections.max(paletteData, Comparator.comparing(String::length));
|
|
final int textWidth = getTextWidth(context, maxLengthData);
|
|
final float textBound = (textWidth + textPadding) / getScreenWidthPixels(context);
|
|
mGradientOffsets.set(Position.CENTER, textBound);
|
|
|
|
final int screenHalfHeight = getScreenHeightPixels(context) / 2;
|
|
final int paletteItemHeight =
|
|
max(screenHalfHeight / paletteData.size(), getTextLineHeight(context));
|
|
|
|
for (int i = 0; i < paletteData.size(); ++i) {
|
|
final TextView textView = new TextView(context);
|
|
textView.setText(paletteData.get(i));
|
|
textView.setTextColor(textColor);
|
|
textView.setHeight(paletteItemHeight);
|
|
textView.setPaddingRelative(Math.round(textPadding), 0, 0, 0);
|
|
textView.setGravity(Gravity.CENTER_VERTICAL);
|
|
textView.setBackground(createGradientDrawable(rootView, paletteColors.get(i)));
|
|
|
|
rootView.addView(textView);
|
|
}
|
|
|
|
updateFirstAndLastItemsBackground(context, rootView, paletteData.size());
|
|
}
|
|
|
|
private GradientDrawable createGradientDrawable(ViewGroup rootView, @ColorInt int color) {
|
|
mGradientColors.set(Position.END, color);
|
|
|
|
final GradientDrawable gradientDrawable = new GradientDrawable();
|
|
final Locale locale = Locale.getDefault();
|
|
final Orientation orientation =
|
|
TextUtilsCompat.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL
|
|
? Orientation.RIGHT_LEFT
|
|
: Orientation.LEFT_RIGHT;
|
|
gradientDrawable.setOrientation(orientation);
|
|
gradientDrawable.setColors(Ints.toArray(mGradientColors), Floats.toArray(mGradientOffsets));
|
|
|
|
return gradientDrawable;
|
|
}
|
|
|
|
private void updateFirstAndLastItemsBackground(Context context, ViewGroup rootView, int size) {
|
|
final int radius =
|
|
context.getResources().getDimensionPixelSize(
|
|
R.dimen.accessibility_illustration_view_radius);
|
|
final int lastIndex = size - 1;
|
|
final GradientDrawable firstItem =
|
|
(GradientDrawable) rootView.getChildAt(0).getBackground();
|
|
final GradientDrawable lastItem =
|
|
(GradientDrawable) rootView.getChildAt(lastIndex).getBackground();
|
|
firstItem.setCornerRadii(new float[]{radius, radius, radius, radius, 0, 0, 0, 0});
|
|
lastItem.setCornerRadii(new float[]{0, 0, 0, 0, radius, radius, radius, radius});
|
|
}
|
|
|
|
private List<Integer> getPaletteColors(Context context) {
|
|
final int[] paletteResources =
|
|
context.getResources().getIntArray(R.array.setting_palette_colors);
|
|
return Arrays.stream(paletteResources).boxed().collect(Collectors.toList());
|
|
}
|
|
|
|
private List<String> getPaletteData(Context context) {
|
|
final String[] paletteResources =
|
|
context.getResources().getStringArray(R.array.setting_palette_data);
|
|
return Arrays.asList(paletteResources);
|
|
}
|
|
|
|
private int getTextWidth(Context context, String text) {
|
|
final TextView tempView = new TextView(context);
|
|
return Math.round(tempView.getPaint().measureText(text));
|
|
}
|
|
|
|
private int getTextLineHeight(Context context) {
|
|
final TextView tempView = new TextView(context);
|
|
final FontMetrics fontMetrics = tempView.getPaint().getFontMetrics();
|
|
return Math.round(fontMetrics.bottom - fontMetrics.top);
|
|
}
|
|
}
|