Little add: I need a way of doing it when the TextInputLayout/EditText is not focused, not between focused-not focused states
I'm looking for a way to change the textColorHint property of TextInputLayout only when the text is present in the TextInputEditText (directly from XML).
If I use that property android:textColorHint="#color/black", it changes the hint color also if the TextInputEditText is empty.
Is there a way to set two different colors for the hint in the two states?
I add a couple of images to explain better
What I want:
when text is empty
when text is filled
What I don't want:
hint has "with text" color
post scriptum: yeah, I could've used two more different colors for this example, but it should be understandable anyway :P
Suppose you take two color, lets say color1 when text is empty and color2 when text is filled, try below approach.
When Text Filled
<style name="TextAppearance.App.TextInputLayout_filled" parent="#android:style/TextAppearance">
<item name="android:textColor">#color/color2</item>
<item name="android:textSize">#dimen/text_size_12</item>
</style>
When Text Empty
<style name="TextAppearance.App.TextInputLayout_empty" parent="#android:style/TextAppearance">
<item name="android:textColor">#color/color1</item>
<item name="android:textSize">#dimen/text_size_12</item>
</style>
Theme
<style name="TextLabel" parent="TextAppearance.AppCompat">
<!-- Hint color and label color in FALSE state -->
<item name="android:textColorHint">#color/color1</item>
<item name="android:textSize">#dimen/text_size_16</item>
</style>
XML for TextInputLayout
<android.support.design.widget.TextInputLayout
android:id="#+id/til_first_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/TextLabel"
app:hintTextAppearance="#style/TextAppearance.App.TextInputLayout_filled">
<android.support.design.widget.TextInputEditText
android:id="#+id/edt_first_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/first_name_caps"
android:imeOptions="actionNext"
android:maxLines="1"
android:nextFocusForward="#+id/til_last_name"
android:singleLine="true"
android:textColor="#android:color/black"/>
</android.support.design.widget.TextInputLayout>
and code
edt_first_name.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
if (edt_first_name.getText().toString().length() > 0){
til_first_name.setHintTextAppearance(R.style.TextAppearance_App_TextInputLayout_filled);
}else {
til_first_name.setHintTextAppearance(R.style.TextAppearance_App_TextInputLayout_empty);
}
}
});
Use style
<style name="TextInputLayout" parent="#android:style/TextAppearance">
<!-- Hint color and label color in FALSE state -->
<item name="android:textColorHint">#color/color_hint</item>
<item name="android:textColor">#color/color_black</item>
<item name="android:fontFamily">#font/helveticaneue</item>
<!-- Label color in TRUE state and bar color FALSE and TRUE State -->
<item name="colorAccent">#color/color_hint</item>
<item name="colorControlNormal">#color/color_hint</item>
<item name="colorControlActivated">#color/color_hint</item>
<item name="colorControlHighlight">#color/color_hint</item>
</style>
use this style in xml
<android.support.design.widget.TextInputLayout
android:id="#+id/layoutFirstName"
style="#style/TextInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_8sdp"
app:hintTextAppearance="#style/TextInputStyle.Hint">
<android.support.design.widget.TextInputEditText
android:id="#+id/editFirstName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/first_name"
android:imeOptions="actionDone"
android:inputType="text"
android:importantForAutofill="noExcludeDescendants"
android:theme="#style/InputTextEditTextNew" />
</android.support.design.widget.TextInputLayout>
For the TextInputEditText set the color of the hint when it is empty with this attribute:
android:textColorHint="#color/yourcolor"
when it is not empty you have to set the color of the floating hint with this style:
<style name="TextInputLayoutStyle" parent="TextAppearance.AppCompat">
<item name="colorControlNormal">#color/colornormalcolor</item>
<item name="colorControlActivated">#color/anothercolor</item>
</style>
and use it in the TextInputLayout xml:
android:theme="#style/TextInputLayoutStyle"
After some research looks like we can not achieve what we are looking for from xml layout only. To do that we definitely need to customize TextInputLayout. Then can simply use that in xml layout file wherever is required.
Here is the customized TextInputLayout
public class CustomTextInputLayout extends TextInputLayout {
public CustomTextInputLayout(Context context) {
this(context, null);
}
public CustomTextInputLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTextInputLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
registerFocusChangeListener();
}
private void registerFocusChangeListener() {
getEditText().setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
String text = getEditText().getText().toString();
boolean isEmpty = TextUtils.isEmpty(text);
if (!isEmpty) { // EditText is not empty, doesn't matter whether it is focused or unfocused
setHintTextAppearance(R.style.TextAppearance_Dark);
} else { // EditText is empty
setHintTextAppearance(R.style.TextAppearance_Light);
}
}
});
}
}
Related
I am using TextInputLayout in which i want to change the color of hinttext when i enter text then the color of hint text should be blue other wise color should be gray and when edittext contains some value then the color of hintText should blue for more information please check my image.
Ultimate i want this after edit text containing some value.
This is my current result after using this code
<style name="labelcolor" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Hint color and label color in FALSE state -->
<item name="android:textColorHint">#868686</item>
<item name="android:textSize">16sp</item>
<item name="android:paddingTop">5sp</item>
<!-- Label color in TRUE state and bar color FALSE and TRUE State -->
<item name="colorAccent">#0ea3ff</item>
<item name="colorControlNormal">#0ea3ffr</item>
<item name="colorControlActivated">#0ea3ff</item>
</style>
please help me how can i solve this issues.
Change TextInputLayout Lebel Color Dynamicaly in on Focus change of edittext and pass color according work for me.
public static void textInoutLayoutColor(TextInputLayout textInputLayout, #ColorInt int color) {
try {
Field fDefaultTextColor = TextInputLayout.class.getDeclaredField("mDefaultTextColor");
fDefaultTextColor.setAccessible(true);
fDefaultTextColor.set(textInputLayout, new ColorStateList(new int[][]{{0}}, new int[]{ color }));
Field fFocusedTextColor = TextInputLayout.class.getDeclaredField("mFocusedTextColor");
fFocusedTextColor.setAccessible(true);
fFocusedTextColor.set(textInputLayout, new ColorStateList(new int[][]{{0}}, new int[]{ color }));
} catch (Exception e) {
e.printStackTrace();
}
}
and change the color like this.
input_layout= (TextInputLayout) findViewById(R.id.input_layout);
etuser_name.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasfocus) {
if(hasfocus){
textInoutLayoutColor(input_layout,getResources().getColor(R.color.bullet_color));
}
else
{
if(etuser_name.getText().toString().trim().length()>0) {
textInoutLayoutColor(input_layout,getResources().getColor(R.color.bullet_color));;
}
else
{
textInoutLayoutColor(input_layout,getResources().getColor(R.color.hint_grey));
}
}
}
});
Create your as bellow and try
<style name="EditTextHint" parent="TextAppearance.AppCompat">
<item name="colorAccent">#android:color/white</item>
<item name="android:textColorHint">#color/BackgroundtWhiteColor</item>
<item name="colorControlNormal">#color/BackgroundtWhiteColor</item>
<item name="colorControlActivated">#color/your color</item>
<item name="colorControlHighlight">#color/BackgroundtWhiteColor</item>
</style>
Use it as bellow
<android.support.design.widget.TextInputLayout
android:theme="#style/EditTextHint"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.TextInputLayout>
Firstly you need to set your TextInputLayout
android.support.design.widget.TextInputLayout textInputLayout = (TextInputLayout) view.findViewById(R.id.textInputLayout);
textInputLayout.setHintTextAppearance(R.style.Instyle);
and then in styles.xml file you can create your styles with the color for the hint color.
<style name="Instyle" parent="AppThemeLight">
<itemname="android:textColorPrimary">#android:color/darker_gray</item>
<item name="android:textColor">#android:color/darker_gray</item>
</style>
TextInputLayout takes colorAccent to hintTextColor when you start entering values in edittext.
So if you want it to be blue then set your colorAccent to blue colour in your theme. And when edittext has no value then set hintTextColor to grey. Do like this
<android.support.design.widget.TextInputLayout
android:id="#+id/userNameTIL"
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="#color/spinnerBg"
android:clipToPadding="false"
android:gravity="bottom"
android:paddingTop="4dp"
android:textColorHint="#color/grey"> /*Here it sets color to hintText when edittext has no value */
<EditText
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom"
android:background="#null"
android:hint="Username"
android:inputType="text"
android:maxLength="30"
android:paddingEnd="3dp"
android:paddingStart="25dp"
android:paddingTop="3dp"
android:singleLine="true"
android:textColor="#color/black"
android:textColorHint="#color/black"
android:textSize="20sp"/>
</android.support.design.widget.TextInputLayout>
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
<!--EditText hint color-->
<item name="android:textColorHint">#color/default_app_white</item> <!-- TextInputLayout text color-->
<item name="colorControlActivated">#color/default_app_green</item>
<!-- EditText line color when EditText on-focus-->
<item name="colorControlHighlight">#color/default_app_green</item>
<!-- EditText line color when EditText in un-focus-->
<item name="colorControlNormal">#color/default_app_white</item>
</style>
<!-- In your style.xml file -->
try this one but it affects your whole application
I have an Android application which uses Material design theme with backward compatibility through AppCompat.
There are multiple Textview's and EditText's in my application. I would like the same properties to be applied to all these TextView's and EditText's across the application. In order to achieve this, i have defined a custom style as shown below:
<!-- Base application theme. -->
<style name="ParentTheme" 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>
</style>
<style name="ArabicTheme" parent="ParentTheme">
<item name="android:editTextStyle">#style/arabicEditText</item>
<item name="android:textViewStyle">#style/arabicTextView</item>
</style>
<style name="arabicEditText" parent="#android:style/Widget.EditText">
<item name="android:gravity">right</item>
<item name="android:ellipsize">end</item>
</style>
<style name="arabicTextView" parent="#android:style/Widget.TextView">
<item name="android:gravity">right</item>
</style>
In my AndroidManifest.xml file under the <Application> tag, i have set android:theme="#style/ArabicTheme".
Below is the output of the activity:
As seen in the above output, the Style is being applied to TextView only. However, The same is not being applied to EditText.
Incase, if i explicitly specify these properties to the EditText in the corresponding Actitivy's xml as shown below:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:hint="Name"
android:ellipsize="end"
android:gravity="right"
android:ems="10"
android:layout_below="#+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="16dp"
android:id="#+id/editText" />
i.e I have explicitly added android:ellipsize="end" and android:gravity="right" to the <EditText>, and only then the output is as expected:
Like i said, i have multiple TextView's and EditText's and i cannot explicitly add these properties to all of them. So, is there a way i can achieve this using Styles or any other approach? Am i doing something wrong here?
Your approach is correct. Just remove android: from the editText's attribute name:
<item name="editTextStyle">#style/arabicEditText</item>
I cannot explain this though. I guess appCompat things don't reuse android attributes, but add another ones with similiar names. Same goes with colorPrimary, srcCompat and others.
I have been doing this
public class LightEditText extends android.widget.EditText{
public LightEditText(Context context) {
super(context);
setFont();
}
public LightEditText(Context context, AttributeSet attrs) {
super(context, attrs);
setFont();
}
public LightEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setFont();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LightEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setFont();
}
/**
* This method is used to set the given font to the TextView.
*/
private void setFont() {
Typeface typeface = TypefaceCache.get(getContext().getAssets(), "fonts/Roboto-Light.ttf");
setTypeface(typeface);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
Then inside your xml file
<com.packagename.LightEditText
android:id="#+id/edtTaskName"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
Do the above method for setting common properties(fontType,style..etc) to editext
What I want to do:
When using an EditText embedded in a TextInputLayout I want to ...
Set the Color of the label to GREEN when it's de-focused and floating above the EditText because the user has already entered some value
Set the Color of the label to RED when it's de-focused and located inside the EditText, because the user has not yet entered a value
I do not want to change the hint text color of all my EditTexts to RED, but only when they're wrapped in a TextInputLayout (I don't need a general approach - a specific approach like setting a theme/style for each TextInputLayout in the layout XML would be fine)
Preserve (i.e. don't change) the accent color (YELLOW) used to color the floating label when the user has focused the field.
What I have tried:
Setting the below as a theme/style on the TextInputLayout does satisfy 1. but not 2.
<style name="FloatingLabel" parent="Widget.Design.TextInputLayout">
<item name="android:textColorHint">#color/red</item>
</style>
Setting a specific color on my embedded EditText that changes the hint text to another color:
android:textColorHint="#color/text_placeholder_gray"
actually causes an overlap of hint texts when the label is moved from it's floating position back into the Edittext as a hint (i.e. no text).
Setting this:
<style name="TextAppearence.App.TextInputLayout" parent="#android:style/TextAppearance">
<item name="android:textColor">#color/main_color</item>
on the TextInputLayout:
<android.support.design.widget.TextInputLayout
...
app:hintTextAppearance="#style/TextAppearence.App.TextInputLayout" >
Changes the hint label color but it also does so for the focused state - which means 4 is not satisfied.
And since a picture says more than a tousand words (all fields are in non-focused state):
How to achieve a setup that satisfies criteria 1-4 ?
I had a similar problem: I needed to implement a text input layout in which the label has different colours for empty (when there is no text entered in the edit text), "filled" and focused state. My main problem was how to differentiate between the empty and the filled state as setting a different colour for the focused state was already easy using selectors. In the end I decided to define a custom "empty text" state and implement my custom text input layout (which extends the normal text input layout).
Here is some code:
In res/values/attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
...
<!-- Custom state for the text input layout to determine whether the label is shown above some text or not -->
<declare-styleable name="EmptyTextState">
<attr name="state_empty_text" format="boolean"/>
</declare-styleable>
</resources>
The custom text input layout:
public class EmptyStateTextInputLayout extends TextInputLayout {
private boolean emptyText = true;
private static final int[] EMPTY_TEXT_STATE = new int[]{R.attr.state_empty_text};
public EmptyStateTextInputLayout(Context context) {
super(context);
}
public EmptyStateTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EmptyStateTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
int[] state = super.onCreateDrawableState(extraSpace + 1);
if (emptyText) {
mergeDrawableStates(state, EMPTY_TEXT_STATE);
}
return state;
}
public void setEmptyTextState(boolean emptyTextState) {
this.emptyText = emptyTextState;
refreshDrawableState();
}
#Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (child instanceof EditText) {
EditText editText = (EditText) child;
if (!TextUtils.isEmpty(editText.getText())) {
setEmptyTextState(false);
}
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
if (!TextUtils.isEmpty(editable)) {
setEmptyTextState(false);
} else {
setEmptyTextState(true);
}
}
});
}
super.addView(child, index, params);
}
}
XML selector to set the colour of label in different states (res/color/input_field_floating_label.xml):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:color="#color/focused_text_color" android:state_focused="true" />
<item android:color="#color/placeholder_color" app:state_empty_text="true"/>
<item android:color="#color/primary_text_color"/> <!-- default color -->
</selector>
Style for the input text layout (in res/values/styles.xml):
<style name="EditTextLayout">
...
<item name="android:textColorHint">#color/input_field_floating_label</item>
</style>
Theme and style for the edit text (still in res/values/styles.xml):
<style name="EditTextTheme">
...
<item name="android:textColorHint">#color/input_field_floating_label</item>
</style>
<style name="EditText">
<item name="android:theme">#style/EditTextTheme</item>
...
</style>
Usage:
<com.package.path.widget.EmptyStateTextInputLayout
style="#style/DarkEditTextLayout"
android:layout_height="wrap_content"
android:layout_width="match_parent"
...
>
<EditText
style="#style/EditText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.package.path.widget.EmptyStateTextInputLayout>
I recommend this blog post to get an idea of working with custom states: http://code.neenbedankt.com/example-of-custom-states-in-android-components/
I'm using TextInputLayout with floating label hints. But In the normal state I am unable to change the hint color from white to other color. Is there a way to do this ?
<android.support.design.widget.TextInputLayout
android:id="#+id/fullNameTextLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_weight="0.75">
<EditText
android:id="#+id/etFullName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginEnd="15dp"
android:layout_marginRight="15dp"
android:singleLine="true"
android:hint="Full Name"
android:textColor="#color/gray_dark"
android:textColorHint="#color/green"
android:textColorHighlight="#color/green" />
</android.support.design.widget.TextInputLayout>
Attaching two screen shots with the background changed.
Please add this in TextInputLayout,
app:hintTextAppearance="#style/mytext
So your layout will be like :
<android.support.design.widget.TextInputLayout
android:id="#+id/aeal_input_layout_zipcode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="#color/green"
app:hintTextAppearance="#style/mytext">
<EditText
android:id="#+id/aeal_etZipCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Zipcode"
android:singleLine="true"
android:inputType="number"
android:textColor="#color/primaryTextColor" />
</android.support.design.widget.TextInputLayout>
style.xml:
<style name="mytext" parent="#android:style/TextAppearance">
<item name="android:textColor">#color/green</item>
<item name="android:textColorHint">#color/green</item>
<item name="colorAccent">#color/green</item>
<item name="android:textSize">14sp</item>
</style>
Edited : You need to add textColorHint in TextInputLayout, and it will work properly as you needed.
It worked for me, so might help you too.
Got the same probleme and solved this with the setHintTextAppearance(int) method of TextInputLayout.
Example:
First find your TextInputLayout
android.support.design.widget.TextInputLayout textInputLayout = (TextInputLayout) view.findViewById(R.id.textInputLayout);
now do the following:
textInputLayout.setHintTextAppearance(R.style.Inactive);
in your styles.xml file you create your styles with the color for the hint color. For example
<style name="Inactive" parent="AppThemeLight">
<item name="android:textColorPrimary">#android:color/darker_gray</item>
<item name="android:textColor">#android:color/darker_gray</item>
</style>
<style name="Active" parent="AppThemeLight">
<item name="android:textColorPrimary">#android:color/black</item>
<item name="android:textColor">#android:color/black</item>
</style>
now, when you change things for example onButtonClick, you simply change your style.
final Button button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
textInputLayout.setHintTextAppearance(R.style.Active);
}
});
Keep in mind, that you also have to handle the Colors for your EditText inside your TextInputLayout.
Use this to change the hint color. -
editText.setHintTextColor(getResources().getColor(R.color.xyz));
Solution for your problem -
editText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,int arg3){
//do something
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
//do something
}
#Override
public void afterTextChanged(Editable arg0) {
if(arg0.toString().length() <= 0) //check if length is equal to zero
editText.setHintTextColor(getResources().getColor(R.color.xyz));
}
});
In your Style.xml you can change the color of hint
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorAccent">#3498db</item>
</style>
For more see this
try this
<android.support.design.widget.TextInputLayout
........
android:textColorHint="requiredColor"
....> to change the floating hint color and
<EditText
android:textColor="requiredColor" to change the hint color in edittxt
Someone tried to change the font of the floating label? I changed the source of EditText but the font of the floating label did not change, I am very grateful to those who help me
Code:
<android.support.design.widget.TextInputLayout
android:id="#+id/tilTextoDescricao"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/tilValorUnidade"
android:layout_marginTop="10dp">
<EditText
android:id="#+id/etTextoDescricao"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:hint="Descrição"
android:textSize="15dp"
android:inputType="text" />
</android.support.design.widget.TextInputLayout>
-----------------
etTextoDescricao= (EditText) findViewById(R.id.etTextoDescricao);
etTextoDescricao.setTypeface(CustomTypeface.getTypefaceMediumDefault(this));
As of Design Library v23, you can use TextInputLayout#setTypeface().
This will set the typeface on both the expanded and floating hint.
Here is the feature request where it was discussed on b.android.com.
EDIT: The error view typeface was not being set, but is now fixed in v25.1.0.
Unfortunately, you'll have to use reflection to handle this.
The floating label is drawn by CollapsingTextHelper, which is an internal, package-private class and isn't setup to handle spans. So, using something like a custom TypefaceSpan won't work in this case.
Because this uses reflection, it isn't guaranteed to work in the future.
Implementation
final Typeface tf = Typeface.createFromAsset(getAssets(), "your_custom_font.ttf");
final TextInputLayout til = (TextInputLayout) findViewById(R.id.yourTextInputLayout);
til.getEditText().setTypeface(tf);
try {
// Retrieve the CollapsingTextHelper Field
final Field cthf = til.getClass().getDeclaredField("mCollapsingTextHelper");
cthf.setAccessible(true);
// Retrieve an instance of CollapsingTextHelper and its TextPaint
final Object cth = cthf.get(til);
final Field tpf = cth.getClass().getDeclaredField("mTextPaint");
tpf.setAccessible(true);
// Apply your Typeface to the CollapsingTextHelper TextPaint
((TextPaint) tpf.get(cth)).setTypeface(tf);
} catch (Exception ignored) {
// Nothing to do
}
Error view
If you needed to change the font of the error, you could do one of two things:
Use Reflection grab the error TextView and apply the Typeface much like before
Use a custom span. Unlike the floating label, the error view used by TextInputLayout is just a TextView, so it's able to handle spans.
Using reflection
final Field errorField = til.getClass().getDeclaredField("mErrorView");
errorField.setAccessible(true);
((TextView) errorField.get(til)).setTypeface(tf);
Using a custom span
final SpannableString ss = new SpannableString("Error");
ss.setSpan(new FontSpan(tf), 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
til.setError(ss);
private static final class FontSpan extends MetricAffectingSpan {
private final Typeface mNewFont;
private FontSpan(Typeface newFont) {
mNewFont = newFont;
}
#Override
public void updateDrawState(TextPaint ds) {
ds.setTypeface(mNewFont);
}
#Override
public void updateMeasureState(TextPaint paint) {
paint.setTypeface(mNewFont);
}
}
Results
The font I'm using is Smoothie Shoppe.
I'm using new MaterialComponents theme and none of the answers helped me.
Had to play with styles and themes on my own. Will post a chunk of styles here in case somebody faces the same issue.
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
...
<item name="textInputStyle">#style/CustomFontTextInputLayout</item>
</style>
<!-- region TextInputLayout & TextInputEditText styles -->
<style name="TextInputLayout.OutlineBox.CustomFont" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<item name="android:theme">#style/ThemeOverlay.TextInputEditText.OutlinedBox.CustomFont</item>
</style>
<style name="ThemeOverlay.TextInputEditText.OutlinedBox.CustomFont" parent="ThemeOverlay.MaterialComponents.TextInputEditText.OutlinedBox">
<item name="editTextStyle">#style/TextInputEditText.OutlinedBox.CustomFont</item>
</style>
<style name="TextInputEditText.OutlinedBox.CustomFont" parent="Widget.MaterialComponents.TextInputEditText.OutlinedBox">
<item name="android:fontFamily">#font/my_font</item>
</style>
<style name="CustomFontTextInputLayout" parent="Widget.Design.TextInputLayout">
<item name="hintTextAppearance">#style/TextInputLayoutHintText</item>
<item name="helperTextTextAppearance">#style/TextInputLayoutHelperText</item>
<item name="errorTextAppearance">#style/TextInputLayoutErrorText</item>
</style>
<style name="TextInputLayoutHintText" parent="TextAppearance.Design.Hint">
<item name="android:fontFamily">#font/my_font</item>
</style>
<style name="TextInputLayoutHelperText" parent="TextAppearance.Design.HelperText">
<item name="android:fontFamily">#font/my_font</item>
</style>
<style name="TextInputLayoutErrorText" parent="TextAppearance.Design.Error">
<item name="android:fontFamily">#font/my_font</item>
</style>
<!-- endregion -->
Then in xml layout:
<android.support.design.widget.TextInputLayout
style="#style/TextInputLayout.OutlineBox.CustomFont"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/first_name"/>
</android.support.design.widget.TextInputLayout>
Here's the result:
i just found a simple solution and it's worked for me:
in this way you can set the typeface to hint of any edit text:
in layout.xml :
<android.support.design.widget.TextInputLayout
android:id="#+id/text_input1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/edt_user"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/username"/>
</android.support.design.widget.TextInputLayout>
and in java class :
public class MainActivity extends AppCompatActivity {
EditText editText;
TextInputLayout textInputLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Typeface font_yekan= Typeface.createFromAsset(getAssets(), "fonts/byekan.ttf");
textInputLayout= (TextInputLayout) findViewById(R.id.text_input1);
textInputLayout.setTypeface(font_yekan);
}
}
Here is a custom class implementation for adneal's answer.
public class CustomTextInputLayout extends TextInputLayout {
public CustomTextInputLayout(Context context) {
super(context);
initFont(context);
}
public CustomTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initFont(context);
}
private void initFont(Context context) {
final Typeface typeface = Typeface.createFromAsset(
context.getAssets(), "fonts/YOUR_CUSTOM_FONT.ttf");
EditText editText = getEditText();
if (editText != null) {
editText.setTypeface(typeface);
}
try {
// Retrieve the CollapsingTextHelper Field
final Field cthf = TextInputLayout.class.getDeclaredField("mCollapsingTextHelper");
cthf.setAccessible(true);
// Retrieve an instance of CollapsingTextHelper and its TextPaint
final Object cth = cthf.get(this);
final Field tpf = cth.getClass().getDeclaredField("mTextPaint");
tpf.setAccessible(true);
// Apply your Typeface to the CollapsingTextHelper TextPaint
((TextPaint) tpf.get(cth)).setTypeface(typeface);
} catch (Exception ignored) {
// Nothing to do
}
}
}
In your XML files now you need to use CustomTextInputLayout instead of TextInputLayout and it will work out of the box.
<your.package.CustomTextInputLayout
android:id="#+id/textInputLayout_email"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<AutoCompleteTextView
android:id="#+id/editText_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/hint_email"
android:inputType="textEmailAddress" />
Thanks adneal for the answer.
final Typeface tf = Typeface.createFromAsset(getAssets(), "your_custom_font.ttf");
final TextInputLayout til = (TextInputLayout) findViewById(R.id.yourTextInputLayout);
til.getEditText().setTypeface(tf);
til.setTypeface(tf);
There is a simpler way,
Create a new directory in your 'res' folder named 'font' and put a font in there. Then open your 'styles' file and create a new style :
<style name="customfontstyle" parent="#android:style/TextAppearance.Small">
<item name="android:fontFamily">#font/poppins_regular</item>
</style>
You can add more properties as well, such as textColor, textSize etc..
Then in your XML:
<android.support.design.widget.TextInputLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:hintTextAppearance="#style/customfontstyle"
>
<android.support.design.widget.TextInputEditText
android:layout_width="220dp"
android:layout_height="wrap_content"
android:id="#+id/edit_phone_number"
android:hint="#string/phone_number_label"
android:inputType="number"
/>
</android.support.design.widget.TextInputLayout>
I checked it and it works.
Use can use style.xml like below:
Style file:
<style name="TextInputLayoutErrorStyle" parent="TextAppearance.Design.Error">
<item name="fontFamily">#font/iran_sans_medium</item>
<item name="android:fontFamily">#font/iran_sans_medium</item>
</style>
<style name="TextInputLayoutHintStyle" parent="TextAppearance.Design.Hint">
<item name="fontFamily">#font/iran_sans_medium</item>
<item name="android:fontFamily">#font/iran_sans_medium</item>
</style>
<style name="TextInputLayoutHelperStyle" parent="TextAppearance.Design.HelperText">
<item name="fontFamily">#font/iran_sans_medium</item>
<item name="android:fontFamily">#font/iran_sans_medium</item>
</style>
<style name="TextInputLayoutOutlinedBoxStyle" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<item name="helperTextTextAppearance">#style/TextInputLayoutHelperStyle</item>
<item name="errorTextAppearance">#style/TextInputLayoutErrorStyle</item>
<item name="hintTextAppearance">#style/TextInputLayoutHintStyle</item>
</style>
Layout file:
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_centerInParent="true"
android:hint="#string/cardname_hint"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
card_view:helperText="#string/cardname_helper"
style="#style/TextInputLayoutOutlinedBoxStyle"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:fontFamily="#font/iran_sans_medium"
android:textColor="#color/colorTextPrimary"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
I was looking for this, I found this way, using the support library:
Typeface typeface = ResourcesCompat.getFont(context, R.font.myfont);
and set this typeface to yout TextInpuLayout.
For me works like charm, I hope it helps others =]
Source: Documentation
fixing a problem in #adneal answer:
if setErrorEnabled is not set true, mErrorView would be null and if you set it false at any point the font would change back to default.
so to fix it:
in you custom TextInputLayout override setErrorEnabled
#Override
public void setErrorEnabled(boolean enabled) {
super.setErrorEnabled(enabled);
if (enabled) {
try {
Field cthf = TextInputLayout.class.getDeclaredField("mErrorView");
cthf.setAccessible(true);
TextView error = (TextView) cthf.get(this);
if (error != null)
error.setTypeface(tf);
} catch (Exception e) {
}
}
}
This is how i achieve this
edit_login_emailOrPhone.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
{
textInputLayout_login_emailOrPhone.setTypeface(APSApplication.getInstance().getFonts().getTypefaceSemiBold());
}else
{
textInputLayout_login_emailOrPhone.setTypeface(APSApplication.getInstance().getFonts().getTypefaceRegular());
}
}
});
In case you too met an exotic requirement to set custom font ONLY to the floating label, and anything else didn't work for you as well, try this. This worked for me, at least for material lib ver. 1.3.0-alpha03.
#SuppressLint("RestrictedApi")
fun setHintFontFamily(view: TextInputLayout, fontRes: Int) {
val font = ResourcesCompat.getFont(view.context, fontRes)!!
try {
val collapsingTextHelperField =
view::class.java.getDeclaredField("collapsingTextHelper").apply {
isAccessible = true
}
val collapsingTextHelper = collapsingTextHelperField.get(view) as CollapsingTextHelper
collapsingTextHelper.collapsedTypeface = font
} catch (e: Exception) {
}
}
First we get the CollapsingTextHelper as in some other answers, but then we use its property collapsedTypeface that seems to do exactly what we need -- apply a font only to the floating label. Please note that this property's visibility is restricted to library group (that's why I used #SuppressLint). So the implementation details might change in the future.