This repository has been archived by the owner on May 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
MaterialColors.cs
469 lines (411 loc) · 16.8 KB
/
MaterialColors.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
// once we implement material configurations on core elements this can all be moved up to that
// for now just leaving this as an internal class to make matching colors between two platforms easier
#if __ANDROID__
using Android.Content.Res;
using Android.Graphics;
using AProgressBar = Android.Widget.ProgressBar;
using ASeekBar = Android.Widget.AbsSeekBar;
using PlatformColor = Android.Graphics.Color;
using Xamarin.Forms.Platform.Android;
using System;
using AGradientDrawable = Android.Graphics.Drawables.GradientDrawable;
using AScaleDrawable = Android.Graphics.Drawables.ScaleDrawable;
using ALayerDrawable = Android.Graphics.Drawables.LayerDrawable;
#elif __IOS__
using MaterialComponents;
using Xamarin.Forms.Platform.iOS;
using PlatformColor = UIKit.UIColor;
#elif __TIZEN__
using System;
using Tizen.NET.MaterialComponents;
using Xamarin.Forms.Platform.Tizen;
using PlatformColor = ElmSharp.Color;
#endif
#if __ANDROID__
namespace Xamarin.Forms.Material.Android
#elif __IOS__
namespace Xamarin.Forms.Material.iOS
#elif __TIZEN__
namespace Xamarin.Forms.Material.Tizen
#endif
{
// Colors from material-components-android
// https://github.com/material-components/material-components-android/blob/3637c23078afc909e42833fd1c5fd47bb3271b5f/lib/java/com/google/android/material/color/res/values/colors.xml
internal static class MaterialColors
{
// https://github.com/material-components/material-components-ios/blob/v76.0.0/components/Slider/src/ColorThemer/MDCSliderColorThemer.m#L21
const float kSliderBaselineDisabledFillAlpha = 0.32f;
const float kSliderBaselineEnabledBackgroundAlpha = 0.24f;
const float kSliderBaselineDisabledBackgroundAlpha = 0.12f;
const float kSliderBaselineEnabledTicksAlpha = 0.54f;
const float kSliderBaselineDisabledTicksAlpha = 0.12f;
public const float SliderTrackAlpha = kSliderBaselineEnabledBackgroundAlpha;
public const double kFrameCornerRadiusDefault = 4;
// values based on
// copying to match iOS
// TODO generalize into xplat classes
// https://github.com/material-components/material-components-ios/blob/develop/components/TextFields/src/ColorThemer/MDCFilledTextFieldColorThemer.m
const float kFilledTextFieldActiveAlpha = 0.87f;
const float kFilledTextFieldOnSurfaceAlpha = 0.6f;
const float kFilledTextFieldDisabledAlpha = 0.38f;
const float kFilledTextFieldSurfaceOverlayAlpha = 0.04f;
const float kFilledTextFieldIndicatorLineAlpha = 0.42f;
const float kFilledTextFieldIconAlpha = 0.54f;
// the idea of this value is that I want Active to be the exact color the user specified
// and then all the other colors decrease according to the Material theme setup
static float kFilledPlaceHolderOffset = 1f - kFilledTextFieldActiveAlpha;
// State list from material-components-android
// https://github.com/material-components/material-components-android/blob/71694616056012fe1162adb9144be903d1e510d5/lib/java/com/google/android/material/textfield/res/values/colors.xml#L28
public static PlatformColor CreateEntryFilledInputBackgroundColor(Color backgroundColor, Color textColor)
{
var platformTextColor = GetEntryTextColor(textColor);
if (backgroundColor == Color.Default)
{
if (textColor != Color.Default)
return WithAlpha(platformTextColor, 0.0392f);
else
return WithAlpha(MaterialColors.Light.PrimaryColorVariant, 0.0392f);
}
return ToPlatformColor(backgroundColor);
}
public static (PlatformColor InlineColor, PlatformColor FloatingColor) GetPlaceHolderColor(Color placeholderColor, Color textColor)
{
PlatformColor color;
if (placeholderColor == Color.Default)
{
if (textColor == Color.Default)
color = MaterialColors.Light.OnSurfaceColor;
else
color = ToPlatformColor(textColor);
}
else
color = ToPlatformColor(placeholderColor);
var inlineColor = WithAlpha(color, kFilledTextFieldOnSurfaceAlpha + kFilledPlaceHolderOffset);
var floatingColor = WithAlpha(color, kFilledTextFieldActiveAlpha + kFilledPlaceHolderOffset);
return (inlineColor, floatingColor);
}
public static (PlatformColor FocusedColor, PlatformColor UnFocusedColor) GetUnderlineColor(Color textColor)
{
PlatformColor color = GetEntryTextColor(textColor);
return (color, WithAlpha(color, kFilledTextFieldIndicatorLineAlpha));
}
public static PlatformColor GetEntryTextColor(Color textColor)
{
return textColor != Color.Default ? ToPlatformColor(textColor) : MaterialColors.Light.PrimaryColor;
}
public static PlatformColor GetCheckBoxColor(bool isChecked, bool isEnabled)
{
if (isChecked && isEnabled)
{
return ToPlatformColor(new Color(0.129411771893501, 0.129411771893501, 0.129411771893501));
}
else if (!isChecked && isEnabled)
{
return ToPlatformColor(new Color(0, 0, 0, 0.54));
}
else if (isChecked && !isEnabled)
{
return ToPlatformColor(new Color(0, 0, 0, 0.38));
}
else
{
return ToPlatformColor(new Color(0, 0, 0, 0.38));
}
}
#if __ANDROID__
public static readonly int[][] ButtonStates =
{
new int[] { global::Android.Resource.Attribute.StateEnabled },
new int[] { }
};
public static readonly int[][] ButtonTextStates =
{
new int[] { global::Android.Resource.Attribute.StateEnabled },
new int[] { ~global::Android.Resource.Attribute.StateEnabled },
new int[] { }
};
public static readonly int[][] EntryHintTextStates =
{
new []{ global::Android.Resource.Attribute.StateEnabled, global::Android.Resource.Attribute.StatePressed },
new int[0] { }
};
public static readonly int[][] EntryUnderlineStates =
{
new []{ global::Android.Resource.Attribute.StateFocused },
new []{ -global::Android.Resource.Attribute.StateFocused },
};
// State list from material-components-android
// https://github.com/material-components/material-components-android/blob/3637c23078afc909e42833fd1c5fd47bb3271b5f/lib/java/com/google/android/material/button/res/color/mtrl_btn_bg_color_selector.xml
public static ColorStateList CreateButtonBackgroundColors(PlatformColor primary)
{
var colors = new int[] { primary, primary.WithAlpha(0.12) };
return new ColorStateList(ButtonStates, colors);
}
// State list from material-components-android
// https://github.com/material-components/material-components-android/blob/3637c23078afc909e42833fd1c5fd47bb3271b5f/lib/java/com/google/android/material/button/res/color/mtrl_btn_text_color_selector.xml
public static ColorStateList CreateButtonTextColors(PlatformColor primary, PlatformColor text, PlatformColor disabledText)
{
var colors = new int[] { text, disabledText, primary.WithAlpha(0.38) };
return new ColorStateList(ButtonTextStates, colors);
}
public static ColorStateList CreateEntryFilledPlaceholderColors(PlatformColor inlineColor, PlatformColor floatingColor)
{
int[][] States =
{
new []{ global::Android.Resource.Attribute.StateEnabled, global::Android.Resource.Attribute.StatePressed },
new int[0] { }
};
var colors = new int[] { floatingColor, inlineColor };
return new ColorStateList(States, colors);
}
public static ColorStateList CreateEntryUnderlineColors(PlatformColor focusedColor, PlatformColor unfocusedColor)
{
var colors = new int[] { focusedColor, unfocusedColor };
return new ColorStateList(EntryUnderlineStates, colors);
}
internal static PlatformColor WithAlpha(this PlatformColor color, double alpha) =>
new PlatformColor(color.R, color.G, color.B, (byte)(alpha * 255));
internal static void ApplySeekBarColors(this ASeekBar seekBar, Color progressColor, Color backgroundColor, Color thumbColor)
{
seekBar.ApplyProgressBarColors(progressColor, backgroundColor);
if (Forms.IsLollipopOrNewer)
{
if (thumbColor.IsDefault)
{
// reset everything to defaults
seekBar.ThumbTintList = seekBar.ProgressTintList;
}
else
{
// handle the case where the thumb is set
var thumb = thumbColor.ToAndroid();
seekBar.ThumbTintList = ColorStateList.ValueOf(thumb);
}
}
else
{
seekBar.Thumb.SetColorFilter(thumbColor.ToAndroid(), FilterMode.SrcIn);
}
}
internal static void ApplyProgressBarColors(this AProgressBar progressBar, PlatformColor progressColor, PlatformColor backgroundColor, PorterDuff.Mode mode)
{
if((int)Forms.SdkInt == 21 && progressBar.ProgressDrawable is ALayerDrawable progressDrawable)
{
progressBar.ProgressTintList = ColorStateList.ValueOf(progressColor);
progressBar.ProgressBackgroundTintList = ColorStateList.ValueOf(backgroundColor);
progressBar.ProgressBackgroundTintMode = mode;
if (progressDrawable.GetDrawable(0) is AGradientDrawable layer0)
layer0.SetColor(backgroundColor);
if (progressDrawable.GetDrawable(1) is AScaleDrawable layer1)
layer1.SetColorFilter(progressColor, FilterMode.SrcIn);
if (progressDrawable.GetDrawable(2) is AScaleDrawable layer2)
layer2.SetColorFilter(progressColor, FilterMode.SrcIn);
}
else if (Forms.IsLollipopOrNewer)
{
progressBar.ProgressTintList = ColorStateList.ValueOf(progressColor);
progressBar.ProgressBackgroundTintList = ColorStateList.ValueOf(backgroundColor);
progressBar.ProgressBackgroundTintMode = mode;
}
else
{
(progressBar.Indeterminate ? progressBar.IndeterminateDrawable :
progressBar.ProgressDrawable).SetColorFilter(progressColor, FilterMode.SrcIn);
}
}
internal static void ApplyProgressBarColors(this AProgressBar progressBar, Color progressColor, Color backgroundColor)
{
PlatformColor defaultProgress = Dark.PrimaryColor;
if (progressColor.IsDefault)
{
if (backgroundColor.IsDefault)
{
// reset everything to defaults
progressBar.ApplyProgressBarColors(defaultProgress, defaultProgress, PorterDuff.Mode.SrcIn);
}
else
{
// handle the case where only the background is set
var background = backgroundColor.ToAndroid();
progressBar.ApplyProgressBarColors(defaultProgress, background, PorterDuff.Mode.SrcOver);
}
}
else
{
if (backgroundColor.IsDefault)
{
// handle the case where only the progress is set
var progress = progressColor.ToAndroid();
progressBar.ApplyProgressBarColors(progress, progress, PorterDuff.Mode.SrcIn);
}
else
{
// handle the case where both are set
var background = backgroundColor.ToAndroid();
var progress = progressColor.ToAndroid();
progressBar.ApplyProgressBarColors(progress, background, PorterDuff.Mode.SrcOver);
}
}
}
#endif
public static class Light
{
// the Colors for "branding"
// - we selected the "black" theme from the default DarkActionBar theme
public static readonly PlatformColor PrimaryColor = FromRgb(33, 33, 33);
public static readonly PlatformColor PrimaryColorVariant = PlatformColor.Black;
public static readonly PlatformColor OnPrimaryColor = PlatformColor.White;
public static readonly PlatformColor SecondaryColor = FromRgb(33, 33, 33);
public static readonly PlatformColor OnSecondaryColor = PlatformColor.White;
public static readonly PlatformColor DisabledColor = WithAlpha(PlatformColor.Black, 0.38f);
// the Colors for "UI"
public static readonly PlatformColor BackgroundColor = PlatformColor.White;
public static readonly PlatformColor OnBackgroundColor = PlatformColor.Black;
public static readonly PlatformColor SurfaceColor = PlatformColor.White;
public static readonly PlatformColor OnSurfaceColor = PlatformColor.Black;
public static readonly PlatformColor ErrorColor = FromRgb(176, 0, 32);
public static readonly PlatformColor OnErrorColor = PlatformColor.White;
#if __IOS__
public static SemanticColorScheme CreateColorScheme()
{
return new SemanticColorScheme
{
PrimaryColor = PrimaryColor,
PrimaryColorVariant = PrimaryColorVariant,
SecondaryColor = SecondaryColor,
OnPrimaryColor = OnPrimaryColor,
OnSecondaryColor = OnSecondaryColor,
BackgroundColor = BackgroundColor,
ErrorColor = ErrorColor,
SurfaceColor = SurfaceColor,
OnBackgroundColor = OnBackgroundColor,
OnSurfaceColor = OnSurfaceColor,
};
}
#elif __TIZEN__
class FormsLightColors : MColors
{
public override PlatformColor PrimaryColor => MaterialColors.Light.PrimaryColor;
public override PlatformColor PrimaryColorVariant => MaterialColors.Light.PrimaryColorVariant;
public override PlatformColor OnPrimaryColor => MaterialColors.Light.OnPrimaryColor;
public override PlatformColor SecondaryColor => MaterialColors.Light.SecondaryColor;
public override PlatformColor OnSecondaryColor => MaterialColors.Light.OnSecondaryColor;
public override PlatformColor BackgroundColor => MaterialColors.Light.BackgroundColor;
public override PlatformColor ErrorColor => MaterialColors.Light.ErrorColor;
public override PlatformColor SurfaceColor => MaterialColors.Light.SurfaceColor;
public override PlatformColor OnBackgroundColor => MaterialColors.Light.OnBackgroundColor;
public override PlatformColor OnSurfaceColor => MaterialColors.Light.OnSurfaceColor;
};
public static MColors CreateColorScheme()
{
return new FormsLightColors();
}
#endif
}
public static class Dark
{
// the Colors for "branding"
// - we selected the "black" theme from the default DarkActionBar theme
public static readonly PlatformColor PrimaryColor = FromRgb(33, 33, 33);
public static readonly PlatformColor PrimaryColorVariant = PlatformColor.Black;
public static readonly PlatformColor OnPrimaryColor = PlatformColor.White;
public static readonly PlatformColor SecondaryColor = FromRgb(33, 33, 33);
public static readonly PlatformColor OnSecondaryColor = PlatformColor.White;
// the Colors for "UI"
public static readonly PlatformColor BackgroundColor = FromRgb(20, 20, 20);
public static readonly PlatformColor OnBackgroundColor = PlatformColor.White;
public static readonly PlatformColor SurfaceColor = FromRgb(40, 40, 40);
public static readonly PlatformColor OnSurfaceColor = PlatformColor.White;
public static readonly PlatformColor ErrorColor = FromRgb(194, 108, 122);
public static readonly PlatformColor OnErrorColor = PlatformColor.White;
#if __IOS__
public static SemanticColorScheme CreateColorScheme()
{
return new SemanticColorScheme
{
PrimaryColor = PrimaryColor,
PrimaryColorVariant = PrimaryColorVariant,
SecondaryColor = SecondaryColor,
OnPrimaryColor = OnPrimaryColor,
OnSecondaryColor = OnSecondaryColor,
BackgroundColor = BackgroundColor,
ErrorColor = ErrorColor,
SurfaceColor = SurfaceColor,
OnBackgroundColor = OnBackgroundColor,
OnSurfaceColor = OnSurfaceColor,
};
}
#elif __TIZEN__
class FormsDarkColors : MColors
{
public override PlatformColor PrimaryColor => MaterialColors.Dark.PrimaryColor;
public override PlatformColor PrimaryColorVariant => MaterialColors.Dark.PrimaryColorVariant;
public override PlatformColor OnPrimaryColor => MaterialColors.Dark.OnPrimaryColor;
public override PlatformColor SecondaryColor => MaterialColors.Dark.SecondaryColor;
public override PlatformColor OnSecondaryColor => MaterialColors.Dark.OnSecondaryColor;
public override PlatformColor BackgroundColor => MaterialColors.Dark.BackgroundColor;
public override PlatformColor ErrorColor => MaterialColors.Dark.ErrorColor;
public override PlatformColor SurfaceColor => MaterialColors.Dark.SurfaceColor;
public override PlatformColor OnBackgroundColor => MaterialColors.Dark.OnBackgroundColor;
public override PlatformColor OnSurfaceColor => MaterialColors.Dark.OnSurfaceColor;
};
public static MColors CreateColorScheme()
{
return new FormsDarkColors();
}
#endif
}
static PlatformColor ToPlatformColor(Color color)
{
#if __ANDROID__
return color.ToAndroid();
#elif __IOS__
return color.ToUIColor();
#elif __TIZEN__
return color.ToNative();
#endif
}
static PlatformColor WithMultipliedAlpha(PlatformColor color, float alpha)
{
#if __ANDROID__
return color.WithAlpha(color.A / 255f * alpha);
#elif __IOS__
return color.ColorWithAlpha(color.CGColor.Alpha / 255f * alpha);
#elif __TIZEN__
return color.WithAlpha(color.A / 255f * alpha);
#endif
}
static PlatformColor WithAlpha(PlatformColor color, float alpha)
{
#if __ANDROID__
return color.WithAlpha(alpha);
#elif __IOS__
return color.ColorWithAlpha(alpha);
#elif __TIZEN__
return color.WithAlpha(alpha);
#endif
}
static int GetAlpha(PlatformColor color)
{
#if __ANDROID__
return color.A;
#elif __IOS__
System.nfloat alpha;
color.GetRGBA(out _, out _, out _, out alpha);
return (int)alpha;
#elif __TIZEN__
return color.A;
#endif
}
static PlatformColor FromRgb(int red, int green, int blue)
{
#if __ANDROID__
return PlatformColor.Rgb(red, green, blue);
#elif __IOS__
return PlatformColor.FromRGB(red, green, blue);
#elif __TIZEN__
return PlatformColor.FromRgb(red, green, blue);
#endif
}
}
}