/* * 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.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.preference.Preference; import androidx.preference.PreferenceViewHolder; import com.android.settings.R; 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.stream.Collectors; /** Preference that easier preview by matching name to color. */ public final class PaletteListPreference extends Preference { private final List mGradientColors = new ArrayList<>(); private final List 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 paletteColors = getPaletteColors(context); final List paletteData = getPaletteData(context); 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.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); } } private GradientDrawable createGradientDrawable(ViewGroup rootView, @ColorInt int color) { mGradientColors.set(Position.END, color); final GradientDrawable gradientDrawable = new GradientDrawable(); final Orientation orientation = rootView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? Orientation.RIGHT_LEFT : Orientation.LEFT_RIGHT; gradientDrawable.setOrientation(orientation); gradientDrawable.setColors(Ints.toArray(mGradientColors), Floats.toArray(mGradientOffsets)); return gradientDrawable; } private List getPaletteColors(Context context) { final int[] paletteResources = context.getResources().getIntArray(R.array.setting_palette_colors); return Arrays.stream(paletteResources).boxed().collect(Collectors.toList()); } private List 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); } }