Skip to content

Commit 071afd2

Browse files
authored
Merge pull request #96 from mtotschnig/ColorPickerA11y
A11y: Allow to provide color names as content descriptions
2 parents 09a642b + d1e6d27 commit 071afd2

File tree

8 files changed

+117
-18
lines changed

8 files changed

+117
-18
lines changed

simpledialogfragments/src/main/java/eltos/simpledialogfragment/color/ColorView.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import android.widget.FrameLayout;
4747
import android.widget.ImageView;
4848

49+
import java.util.Locale;
50+
4951
import eltos.simpledialogfragment.R;
5052

5153

@@ -108,12 +110,17 @@ public void setStyle(Style style){
108110
return mColor;
109111
}
110112

113+
/**
114+
* Will implicitly set content description. Thus custom content description must be set after this
115+
* method is called
116+
*/
111117
public void setColor(@ColorInt int color) {
112118
if ((color & 0xFF000000) == 0 && color != 0){ // if alpha value omitted, set now
113119
color = color | 0xFF000000;
114120
}
115121
if (mColor != color) {
116122
mColor = color;
123+
setContentDescription(colorToRGBString(mColor));
117124
update();
118125
}
119126
}
@@ -289,6 +296,12 @@ public static boolean isColorDark(@ColorInt int color) {
289296
return Color.HSVToColor(hsv);
290297
}
291298

299+
public static String colorToRGBString(int color) {
300+
int red = Color.red(color);
301+
int green = Color.green(color);
302+
int blue = Color.blue(color);
303+
return String.format(Locale.ROOT, "RGB(%d, %d, %d)", red, green, blue);
304+
}
292305

293306
}
294307

simpledialogfragments/src/main/java/eltos/simpledialogfragment/color/SimpleColorDialog.java

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import androidx.annotation.ArrayRes;
2424
import androidx.annotation.ColorInt;
2525
import androidx.annotation.NonNull;
26+
import androidx.core.util.Pair;
2627

2728
import android.util.TypedValue;
2829
import android.view.View;
@@ -95,6 +96,28 @@ public SimpleColorDialog colors(Context context, @ArrayRes int colorArrayRes){
9596
return colors(context.getResources().getIntArray(colorArrayRes));
9697
}
9798

99+
/**
100+
* Sets the color names for accessibility purpose
101+
*
102+
* @param colorNames array of names that match the colors defined via {@link #colors(int[])}
103+
* @return this instance
104+
*/
105+
public SimpleColorDialog colorNames(String[] colorNames){
106+
getArgs().putStringArray(COLOR_NAMES, colorNames);
107+
return this;
108+
}
109+
110+
/**
111+
* Sets the color names for accessibility purpose
112+
*
113+
* @param context a context to resolve the resource
114+
* @param colorNameArrayRes String array resource id
115+
* @return this instance
116+
*/
117+
public SimpleColorDialog colorNames(Context context, @ArrayRes int colorNameArrayRes){
118+
return colorNames(context.getResources().getStringArray(colorNameArrayRes));
119+
}
120+
98121
/**
99122
* Sets the initially selected color
100123
*
@@ -183,9 +206,6 @@ public SimpleColorDialog showOutline(@ColorInt int color){
183206
return setArg(OUTLINE, color);
184207
}
185208

186-
187-
188-
189209
public static final @ColorInt int[] DEFAULT_COLORS = new int[]{
190210
0xfff44336, 0xffe91e63, 0xff9c27b0, 0xff673ab7,
191211
0xff3f51b5, 0xff2196f3, 0xff03a9f4, 0xff00bcd4,
@@ -206,6 +226,8 @@ public SimpleColorDialog showOutline(@ColorInt int color){
206226
private static final String SELECTED = TAG + "selected";
207227
private static final String OUTLINE = TAG + "outline";
208228

229+
private static final String COLOR_NAMES = TAG + "color_names";
230+
209231
private @ColorInt int mCustomColor = NONE;
210232
private @ColorInt int mSelectedColor = NONE;
211233

@@ -256,7 +278,7 @@ protected AdvancedAdapter onCreateAdapter() {
256278
// Selector provided by ColorView
257279
getListView().setSelector(new ColorDrawable(Color.TRANSPARENT));
258280

259-
return new ColorAdapter(colors, custom);
281+
return new ColorAdapter(colors, getArgs().getStringArray(COLOR_NAMES), custom);
260282
}
261283

262284
private int indexOf(int[] array, int item){
@@ -349,19 +371,19 @@ protected Bundle onResult(int which) {
349371
}
350372

351373

352-
protected class ColorAdapter extends AdvancedAdapter<Integer>{
374+
protected class ColorAdapter extends AdvancedAdapter<Pair<Integer, String>>{
353375

354-
public ColorAdapter(int[] colors, boolean addCustomField){
376+
public ColorAdapter(int[] colors, String[] contentDescriptions, boolean addCustomField){
355377
if (colors == null) colors = new int[0];
356378

357-
Integer[] cs = new Integer[colors.length + (addCustomField ? 1 : 0)];
379+
Pair<Integer, String>[] cs = new Pair[colors.length + (addCustomField ? 1 : 0)];
358380
for (int i = 0; i < colors.length; i++) {
359-
cs[i] = colors[i];
381+
cs[i] = Pair.create(colors[i], contentDescriptions != null && contentDescriptions.length > i ? contentDescriptions[i] : null);
360382
}
361383
if (addCustomField){
362-
cs[cs.length-1] = PICKER;
384+
cs[cs.length-1] = Pair.create(PICKER, getString(R.string.color_picker));
363385
}
364-
setData(cs, Long::valueOf);
386+
setData(cs, pair -> pair.first.longValue());
365387
}
366388

367389
@Override
@@ -374,14 +396,18 @@ public View getView(int position, View convertView, ViewGroup parent) {
374396
item = new ColorView(getContext());
375397
}
376398

377-
int color = getItem(position);
399+
Pair<Integer, String> pair = getItem(position);
378400

379-
if ( color == PICKER){
401+
if (pair.first == PICKER){
380402
item.setColor(mCustomColor);
381403
item.setStyle(ColorView.Style.PALETTE);
404+
item.setContentDescription(getString(R.string.color_picker) + (mCustomColor == NONE ? "" : ": " + ColorView.colorToRGBString(mCustomColor)));
382405
} else {
383-
item.setColor(getItem(position));
406+
item.setColor(pair.first);
384407
item.setStyle(ColorView.Style.CHECK);
408+
if (pair.second != null) {
409+
item.setContentDescription(pair.second);
410+
}
385411
}
386412

387413
@ColorInt int outline = getArgs().getInt(OUTLINE, ColorView.NONE);

simpledialogfragments/src/main/java/eltos/simpledialogfragment/form/ColorField.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public class ColorField extends FormElement<ColorField, ColorViewHolder> {
4444
private @ColorInt int preset = NONE;
4545
private int presetId = NO_ID;
4646
protected int[] colors = SimpleColorDialog.DEFAULT_COLORS;
47+
protected String[] colorNames = null;
4748
protected boolean allowCustom = true;
4849
protected int outline = NONE;
4950

@@ -100,6 +101,28 @@ public ColorField colors(@ColorInt int[] colors){
100101
return this;
101102
}
102103

104+
/**
105+
* Sets the color names for accessibility purpose
106+
*
107+
* @param colorNames array of names that match the colors defined via {@link #colors(int[])}
108+
* @return this instance
109+
*/
110+
public ColorField colorNames(String[] colorNames) {
111+
this.colorNames = colorNames;
112+
return this;
113+
}
114+
115+
/**
116+
* Sets the color names for accessibility purpose
117+
*
118+
* @param context a context to resolve the resource
119+
* @param colorNameArrayRes String array resource id
120+
* @return this instance
121+
*/
122+
public ColorField colorNames(Context context, @ArrayRes int colorNameArrayRes){
123+
return colorNames(context.getResources().getStringArray(colorNameArrayRes));
124+
}
125+
103126
/**
104127
* Sets the color pallet to choose from
105128
* May be one of {@link SimpleColorDialog#MATERIAL_COLOR_PALLET},

simpledialogfragments/src/main/java/eltos/simpledialogfragment/form/ColorViewHolder.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ protected void setUpView(View view, final Context context, Bundle savedInstanceS
8888
colorView.setOnClickListener(v -> actions.showDialog(SimpleColorDialog.build()
8989
.title(field.getText(context))
9090
.colors(field.colors)
91+
.colorNames(field.colorNames)
9192
.allowCustom(field.allowCustom)
9293
.colorPreset(colorView.getColor())
9394
.neut(),
@@ -99,6 +100,14 @@ protected void setUpView(View view, final Context context, Bundle savedInstanceS
99100

100101
private void setColor(@ColorInt int color){
101102
colorView.setColor(color);
103+
if (field.colorNames != null && field.colorNames.length >= field.colors.length) {
104+
for (int i = 0; i < field.colors.length; i++) {
105+
if (field.colors[i] == color) {
106+
colorView.setContentDescription(field.colorNames[i]);
107+
break;
108+
}
109+
}
110+
}
102111
clearButton.setVisibility(field.required || colorView.getColor() == ColorView.NONE ? View.GONE : View.VISIBLE);
103112
}
104113

simpledialogfragments/src/main/res/layout/simpledialogfragment_form_item_color.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
android:layout_gravity="center"
3636
android:scaleType="fitCenter"
3737
android:visibility="gone"
38+
android:contentDescription="@string/clear_color"
3839
android:src="@drawable/ic_clear_search" />
3940

4041

simpledialogfragments/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@
2020
<string name="date">Date</string>
2121
<string name="time">Time</string>
2222
<string name="clear">Clear</string>
23+
<string name="color_picker">Color picker</string>
24+
<string name="clear_color">Clear color</string>
2325
</resources>

testApp/src/main/java/eltos/simpledialogfragments/MainActivity.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,13 +393,16 @@ public void showColorPicker(View view){
393393
pallet == SimpleColorDialog.BEIGE_COLOR_PALLET ? SimpleColorDialog.AUTO :
394394
SimpleColorDialog.NONE;
395395

396-
SimpleColorDialog.build()
396+
SimpleColorDialog dialog = SimpleColorDialog.build()
397397
.title(R.string.pick_a_color)
398398
.colors(this, pallet)
399399
.colorPreset(color)
400400
.allowCustom(true)
401-
.showOutline(outline)
402-
.show(this, COLOR_DIALOG);
401+
.showOutline(outline);
402+
if (pallet == SimpleColorDialog.MATERIAL_COLOR_PALLET) {
403+
dialog.colorNames(this, R.array.material_color_names);
404+
}
405+
dialog.show(this, COLOR_DIALOG);
403406

404407
/** Results: {@link MainActivity#onResult} **/
405408

@@ -551,7 +554,9 @@ public void showForm(View view){
551554
Input.plain(COUNTRY).hint(R.string.country)
552555
.inputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES)
553556
.suggest(R.array.countries_locale).forceSuggestion(),
554-
ColorField.picker(COLOR).label(R.string.favourite_color),
557+
ColorField.picker(COLOR).colors(SimpleColorDialog.DEFAULT_COLORS)
558+
.colorNames(this,R.array.material_color_names)
559+
.label(R.string.favourite_color),
555560
Input.email(EMAIL).required(),
556561
Check.box(NEWSLETTER).label(R.string.receive_newsletter).check(true),
557562
Input.password(PASSWORD).max(20).required().validatePatternStrongPassword(),

testApp/src/main/res/values/arrays.xml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,25 @@
7373
<item>Intersex</item>
7474
<item>Dyadic</item>
7575
</string-array>
76-
76+
<string-array name="material_color_names">
77+
<item>red</item>
78+
<item>magenta</item>
79+
<item>purple</item>
80+
<item>deep purple</item>
81+
<item>indigo</item>
82+
<item>blue</item>
83+
<item>light blue</item>
84+
<item>cyan</item>
85+
<item>teal</item>
86+
<item>green</item>
87+
<item>light green</item>
88+
<item>lime</item>
89+
<item>yellow</item>
90+
<item>amber</item>
91+
<item>orange</item>
92+
<item>deep orange</item>
93+
<item>brown</item>
94+
<item>gray</item>
95+
<item>blue gray</item>
96+
</string-array>
7797
</resources>

0 commit comments

Comments
 (0)