I'm working on an app that has full UI customization. If you look at a EditText wrapped in an TextInputLayout, the EditText's default text hint color and line color are the same as the color textPrimaryColor defined in styles. When the EditText receives focus however, the line becomes the color of the accent defined in styles, the hint goes through the floating hint animation and changes to the accent color. It's pretty easy to do with styles.xml and themes.xml, however, I can't quite get it programmatically.
The current method I have set up is this:
public static void setInputTextLayoutColor(final int accent, final int text, TextInputLayout textInputLayout, AppCompatEditText edit) {
edit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
AppCompatEditText editText = (AppCompatEditText) v;
editText.getBackground().clearColorFilter();
if(hasFocus) editText.getBackground().setColorFilter(accent, PorterDuff.Mode.SRC_IN);
else editText.getBackground().setColorFilter(text, PorterDuff.Mode.SRC_IN);
}
});
setCursorColor(edit, accent);
try {
Field field = textInputLayout.getClass().getDeclaredField("mFocusedTextColor");
field.setAccessible(true);
int[][] states = new int[][]{
new int[]{}
};
int[] colors = new int[]{
accent
};
ColorStateList myList = new ColorStateList(states, colors);
field.set(textInputLayout, myList);
Field fDefaultTextColor = TextInputLayout.class.getDeclaredField("mDefaultTextColor");
fDefaultTextColor.setAccessible(true);
fDefaultTextColor.set(textInputLayout, myList);
Method method = textInputLayout.getClass().getDeclaredMethod("updateLabelState", boolean.class);
method.setAccessible(true);
method.invoke(textInputLayout, true);
} catch (Exception e) {
e.printStackTrace();
}
}
The problem with this method is that A) the hint text is colored immediately to the accent color, it doesn't color to the accent when focus is received B) The EditText line starts off with the right color, but when it receives focus, it colorizes to accent defined in styles, not the programatically set color.
This is the non-focused picture (in reference to the "Event name" field). Here, the color of "event name" should be gray / white (like the text"):
This is the focused picture, here, everything is right except the color of the line, which should be green as well.
Wasn't able to figure out dynamically changing the hint color, but I got the line color to change with a listener:
AppCompatEditText edit = (AppCompatEditText)findViewById(R.id.event_create_name_edit);
edit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
AppCompatEditText edit2 = (AppCompatEditText)v;
if(hasFocus) edit2.setSupportBackgroundTintList(ColorStateList.valueOf(rui.getAccent()));
else edit2.setSupportBackgroundTintList(ColorStateList.valueOf(rui.getText()));
}
});
Related
I'm trying to build a renderer for Xamarin Forms. The renderer needs to set the EditText underline color to "Active Color" when selected and "Hint Color" when deselected. My initial setup looks something like this.
note: here's the path to the full source file
https://github.com/XamFormsExtended/Xfx.Controls/blob/issue-%236/src/Xfx.Controls.Droid/Renderers/XfxEntryRendererDroid.cs
// called when control is created or when Colors are changed.
protected virtual void SetLabelAndUnderlineColor()
{
var defaultColor = GetPlaceholderColor();
var activeColor = GetActivePlaceholderColor();
SetHintLabelDefaultColor(defaultColor);
SetHintLabelActiveColor(activeColor);
SetUnderlineColor(_hasFocus ? activeColor : defaultColor);
}
private void SetUnderlineColor(AColor color)
{
var bg = ColorStateList.ValueOf(color);
ViewCompat.SetBackgroundTintList(EditText,bg);
}
private void SetHintLabelActiveColor(AColor color)
{
var hintText = Control.Class.GetDeclaredField("mFocusedTextColor");
hintText.Accessible = true;
hintText.Set(Control, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { color }));
}
private void SetHintLabelDefaultColor(AColor color)
{
var hint = Control.Class.GetDeclaredField("mDefaultTextColor");
hint.Accessible = true;
hint.Set(Control, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { color }));
}
Outside of this, I also have an OnClickListener that updates the underline only when the state changes
private void ControlOnFocusChange(object sender, FocusChangeEventArgs args)
{
_hasFocus = args.HasFocus;
SetUnderlineColor(args.HasFocus ? GetPlaceholderColor() : GetActivePlaceholderColor());
}
The problem is that when I tap into the EditText, it's hit or miss as to what I'm going to see for an underline color.
I can pretty much guarantee that it'll be the default android:colorAccent the very first time. Then after that it switches between the "Hint Color" and the "Placeholder Color".
note: if I change the SetUnderlineColor method to this (below), it no longer uses the "Hint Color" in the mix, but I still get the android:colorAccent color as the initial underline color, after that it behaves as expected.
private void SetUnderlineColor(AColor color)
{
var bg = EditText.Background;
DrawableCompat.SetTint(bg,color);
EditText.SetBackground(bg);
}
What do I need to do to set the INITIAL selected color of the EditText to my chosen activeColor / 'focused color' (purple)?
In this animation I am simply selecting and deselecting the EditText
So the solution for me was to go pure AppCompat
So I'm adding an AppCompatEditText to the TextInputLayout
protected EditText EditText => Control.EditText;
protected override TextInputLayout CreateNativeControl()
{
var textInputLayout = new TextInputLayout(Context);
var editText = new AppCompatEditText(Context)
{
SupportBackgroundTintList = ColorStateList.ValueOf(GetPlaceholderColor())
};
textInputLayout.AddView(editText);
return textInputLayout;
}
Then from there I was able to set the underline consistently with this.
private void ControlOnFocusChange(object sender, FocusChangeEventArgs args)
{
_hasFocus = args.HasFocus;
SetUnderlineColor(_hasFocus ? GetActivePlaceholderColor(): GetPlaceholderColor());
}
private void SetUnderlineColor(AColor color)
{
var element = (ITintableBackgroundView)EditText;
element.SupportBackgroundTintList = ColorStateList.ValueOf(color);
}
full source code here.
Modify your code in XfxEntryRendererDroid ControlOnFocusChange method like this :
private void ControlOnFocusChange(object sender, FocusChangeEventArgs args)
{
_hasFocus = args.HasFocus;
if (_hasFocus)
{
...
EditText.PostDelayed(() =>
{
//Add the following code
SetUnderlineColor(GetActivePlaceholderColor());
EditText.RequestFocus();
manager.ShowSoftInput(EditText, 0);
},
0);//Change it to 0
}
...
}
Effect.
Why don't you change the tint colour at runtime using this (May be in your text changed event):
ViewCompat.SetBackgroundTintList(_YourView , ColorStateList.ValueOf(Color.ParseColor(Resources.GetString(Resource.Color.blueLine))));
Anyways Goodluck!
You need to set the backgroundTintList or supportBackgroundTintList on the EditText to an instance of ColorStateList
ColorStateList colorStateList = ColorStateList.valueOf(color)
editText.setSupportBackgroundTintList(colorStateList)
OR
I think that if you want to change a bottom line color, then you can change using this below line
editText.getBackground().mutate().setColorFilter(getResources().getColor(R.color.your_color), PorterDuff.Mode.SRC_ATOP);
And Application theame like this:-
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="colorControlNormal">#color/colorAccent</item>
<item name="colorControlActivated">#color/colorAccent</item>
<item name="colorControlHighlight">#color/colorAccent</item>
</style>
Please check this Example
Hope this Link1 Link2 helps you.
To change color you can use below code
editText.getBackground().mutate().setColorFilter(your_color), PorterDuff.Mode.SRC_ATOP);
And to set different color underline for EditText view on focus change
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
editText.getBackground().mutate().setColorFilter(getResources().getColor(android.R.color.holo_purple), PorterDuff.Mode.SRC_ATOP);
}else {
editText.getBackground().mutate().setColorFilter(getResources().getColor(android.R.color.holo_red_dark), PorterDuff.Mode.SRC_ATOP);
}
}
});
Good day. I have an issue. I change the color of EditText drawable when it's in focus and change it back to default color when focus changes. And everything was good until support library updated(that's my assumption)now the color of a drawable doesn't switch back to normal. Thank's everyone in advance =)
This is my code:
#Override
public Drawable setTint(Drawable d, int color) {
Drawable wrappedDrawable = DrawableCompat.wrap(d);
DrawableCompat.setTint(wrappedDrawable, color);
return wrappedDrawable;
}
#Override
public void setEditTextDrawables(final EditText editText, final int drawable) {
editText.setCompoundDrawablesWithIntrinsicBounds(drawable, 0, 0, 0);
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
if (b){
Drawable icon = getResources().getDrawable(drawable);
editText.setCompoundDrawablesWithIntrinsicBounds(setTint(icon,
getResources().getColor(R.color.colorAccent)), null, null, null);
}else if (!b){
Drawable icon = getResources().getDrawable(drawable);
editText.setCompoundDrawablesWithIntrinsicBounds(setTint(icon,
getResources().getColor(R.color.colorGreyIcon)), null, null, null);
}
}
});
}
and this is screens from the app:
According to the Android documentation on Drawable#setTint(int):
To clear the tint, pass null to setTintList(ColorStateList).
Note: Just calling getDrawable(int) to create a new Drawable is not sufficient to clear the tint, if you've previously set the tint on the same Drawable Id in an activity.
Note that setTintList( null ) will only work on API's above 21 (Android 5.0, Lollipop). Therefore the use of ImageViewCompat is recommended:
ImageViewCompat.setImageTintList( iv,null);
I've got a simple TextInputLayout containing an EditText View.
Now I wonder how to change the accent color (underline, hintTextColor when highlighted) programmatically.
I can't seem to find a suitable method inside TextInputLayout.
Any suggestions? Thanks in advance.
IMHO InputTextLayout can not change label color programmatically, because it is set by style. I examined source code of InputTextLayout and wrote this hack helper method which create access to private color member:
public static void setInputTextLayoutColor(EditText editText, #ColorInt int color) {
TextInputLayout til = (TextInputLayout) editText.getParent();
try {
Field fDefaultTextColor = TextInputLayout.class.getDeclaredField("mDefaultTextColor");
fDefaultTextColor.setAccessible(true);
fDefaultTextColor.set(til, new ColorStateList(new int[][]{{0}}, new int[]{ color }));
Field fFocusedTextColor = TextInputLayout.class.getDeclaredField("mFocusedTextColor");
fFocusedTextColor.setAccessible(true);
fFocusedTextColor.set(til, new ColorStateList(new int[][]{{0}}, new int[]{ color }));
} catch (Exception e) {
e.printStackTrace();
}
}
mFocusedTextColor is used for set internal CollapsingTextHelper.mCollapsedTextColor which sets color of label.
You can try this for the text,
InputTextLayout.getEditText().setHighlightColor(yourColor);
InputTextLayout.getEditText().setHintTextColor(yourColor);
and this for the line at the bottom of the EditText
Drawable background = InputTextLayout.getEditText().getBackground();
DrawableCompat.setTint(background, yourColor);
InputTextLayout.getEditText().setBackground(background);
Hope it works!
How can I make an EditText (both the underline and android:hint) have a 50% transparency when there is no text inputted and it isn't clicked on, then change to 100% when it is either clicked on or has inputted text?
In addition, how can I change the color of the underline (not hint) to orange when the transparency is 100% (when it is clicked or text has been inputted)?
Use the following code
mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// If has focus then change the alpha to 1
mEditText.setAlpha(1);
// Set orange color filter
mEditText.getBackground().setColorFilter(Color.argb(255, 255, 165, 0), PorterDuff
.Mode.SRC_IN);
} else {
// When focus is lost, check if some text has been entered.
// If not then set the alpha to 0.5f (50% transparent)
if (TextUtils.isEmpty(mEditText.getText().toString())) {
mEditText.setAlpha(0.5f);
// Clear the color filter
mEditText.getBackground().clearColorFilter();
}
}
mEditText.invalidate();
}
});
I have a edit text field. I want it to have a transparent background. But when the user tries to edit it, it should be with a different background say white color and text color as black. And when he is done with the edit of the edit text and moves to the next control to enter other values i want the background to be transparent again. Please let me know how this is possible in android. Thank you for the help and time.
EditText editText = (EditText)findViewById(R.id.edit1);
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
EditText editText = (EditText)findViewById(R.id.edit1);
editText.setBackgroundColor(hasFocus ? Color.WHITE : Color.TRANSPARENT);
editText.setTextColor(hasFocus ? Color.BLACK : Color.GRAY);
}
});
implement method onFocusChabgeListener() like below.
textView.setOnFocusChangeListener(new OnFocusChangeListener(){
if(textView.hasFocuss){
//set textColor and background color
}
else
{
//reset it
}
});