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
/
MaterialFormsTextInputLayoutBase.cs
155 lines (131 loc) · 5.09 KB
/
MaterialFormsTextInputLayoutBase.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
using System;
using Android.Content;
using Android.Runtime;
using Android.Util;
#if __ANDROID_29__
using AndroidX.Core.View;
using Google.Android.Material.TextField;
#else
using Android.Support.V4.View;
using Android.Support.Design.Widget;
using Xamarin.Forms.Platform.Android.AppCompat;
#endif
using Android.Content.Res;
using AView = Android.Views.View;
using Xamarin.Forms.Platform.Android;
using Android.Widget;
namespace Xamarin.Forms.Material.Android
{
public class MaterialFormsTextInputLayoutBase : TextInputLayout
{
Color _formsTextColor;
Color _formsPlaceholderColor;
bool _isSetup = false;
ColorStateList _focusedFilledColorList;
ColorStateList _unfocusedEmptyColorList;
private ColorStateList _unfocusedUnderlineColorsList;
private ColorStateList _focusedUnderlineColorsList;
static readonly int[][] s_colorStates = { new[] { global::Android.Resource.Attribute.StateEnabled }, new[] { -global::Android.Resource.Attribute.StateEnabled } };
bool _disposed = false;
public MaterialFormsTextInputLayoutBase(Context context) : base(context)
{
}
public MaterialFormsTextInputLayoutBase(Context context, IAttributeSet attrs) : base(context, attrs)
{
}
public MaterialFormsTextInputLayoutBase(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
}
protected MaterialFormsTextInputLayoutBase(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
void ResetTextColors(Color formsTextColor, Color formsPlaceHolderColor)
{
_formsPlaceholderColor = formsPlaceHolderColor;
_formsTextColor = formsTextColor;
var underlineColors = MaterialColors.GetUnderlineColor(_formsPlaceholderColor);
var placeHolderColors = MaterialColors.GetPlaceHolderColor(_formsPlaceholderColor, _formsTextColor);
// I realize these are the same but I have to set it to a difference instance
// otherwise when focused it won't change to the color I want it to and it'll just think
// I'm not actually changing anything
_unfocusedUnderlineColorsList = MaterialColors.CreateEntryUnderlineColors(underlineColors.FocusedColor, underlineColors.UnFocusedColor);
_focusedUnderlineColorsList = MaterialColors.CreateEntryUnderlineColors(underlineColors.FocusedColor, underlineColors.UnFocusedColor);
_focusedFilledColorList = MaterialColors.CreateEntryFilledPlaceholderColors(placeHolderColors.FloatingColor, placeHolderColors.FloatingColor);
_unfocusedEmptyColorList = MaterialColors.CreateEntryFilledPlaceholderColors(placeHolderColors.InlineColor, placeHolderColors.FloatingColor);
var textColor = MaterialColors.GetEntryTextColor(formsTextColor).ToArgb();
EditText.SetTextColor(new ColorStateList(s_colorStates, new[] { textColor, textColor }));
}
public virtual void ApplyTheme(Color formsTextColor, Color formsPlaceHolderColor)
{
if (_disposed)
return;
if(!_isSetup)
{
_isSetup = true;
EditText.FocusChange += OnFocusChange;
ResetTextColors(formsTextColor, formsPlaceHolderColor);
}
else if(formsTextColor != _formsTextColor || _formsPlaceholderColor != formsPlaceHolderColor)
{
ResetTextColors(formsTextColor, formsPlaceHolderColor);
}
if(HasFocus)
ViewCompat.SetBackgroundTintList(EditText, _focusedUnderlineColorsList);
else
ViewCompat.SetBackgroundTintList(EditText, _unfocusedUnderlineColorsList);
if (HasFocus || !string.IsNullOrWhiteSpace(EditText.Text))
this.DefaultHintTextColor = _focusedFilledColorList;
else
this.DefaultHintTextColor = _unfocusedEmptyColorList;
}
void ApplyTheme() => ApplyTheme(_formsTextColor, _formsPlaceholderColor);
/*
* This currently does two things
* 1) It's a hacky way of keeping the underline color matching the TextColor.
* when the entry gets focused the underline gets changed to the themes active color
* and this is the only way to set it away from that and to whatever the user specified
* 2) The HintTextColor has a different alpha when focused vs not focused
* */
void OnFocusChange(object sender, FocusChangeEventArgs e)
{
if (EditText == null)
return;
Device.BeginInvokeOnMainThread(() => ApplyTheme());
// propagate the focus changed event to the View Renderer base class
if (Parent is AView.IOnFocusChangeListener focusChangeListener)
focusChangeListener.OnFocusChange(EditText, e.HasFocus);
}
public virtual void SetHint(string hint, VisualElement element)
{
HintEnabled = !string.IsNullOrWhiteSpace(hint);
if (HintEnabled)
{
element?.InvalidateMeasureNonVirtual(Internals.InvalidationTrigger.VerticalOptionsChanged);
Hint = hint;
// EditText.Hint => Hint
// It is impossible to reset it but you can make it invisible.
EditText.SetHintTextColor(global::Android.Graphics.Color.Transparent);
}
}
public override EditText EditText
{
get
{
if (this.IsDisposed())
return null;
return base.EditText;
}
}
protected override void Dispose(bool disposing)
{
if (!_disposed)
{
_disposed = true;
if (EditText != null)
EditText.FocusChange -= OnFocusChange;
}
base.Dispose(disposing);
}
}
}