If there is NO Text typed into TextInputEditText, the Android Accessibility talkback will read the hint in TextInputLayout.
However, Android Talkback will NOT read the hint in TextInputLayout if there is text added into the TextInputEditText.
I Need the Accessibility Talkback to Always read the hint in TextInputLayout.
Does anyone know how to do it?
Thanks guys
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:labelFor="#+id/editText"
android:hint="username">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
The only way you can overwrite that it to:
Extend :
public class CustomTextInputLayoutAccessibilityDelegate extends TextInputLayout.AccessibilityDelegate {...}
Then Overwrite:
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
...
// And add the new logic in here:
if (showingText) {
if (hasHint) {
info.setText(String.format("%s, %s", hintText, text));
} else {
info.setText(text);
}
} else if (hasHint) {
info.setText(hintText);
}
}
And set it to your TextInputLayout as:
setTextInputAccessibilityDelegate(new CustomTextInputLayoutAccessibilityDelegate(this));
I want to create TextInputLayout with Widget.MaterialComponents.TextInputLayout.OutlinedBox style. I tried many ways but couldn't get the required result.
Here is my code.
TextInputLayout textInputLayout = new TextInputLayout(getActivity(),null,R.style.Widget_MaterialComponents_TextInputLayout_OutlinedBox);
textInputLayout.setHint("My Hint");
TextInputEditText editText = new TextInputEditText(textInputLayout.getContext());
textInputLayout.addView(editText);
parentView.addView(textInputLayout);
I also tried:
TextInputLayout textInputLayout = new TextInputLayout(getActivity(),null,TextInputLayout.BOX_BACKGROUND_OUTLINE);
I want to create view like this .
UPDATE
Thanks to #Mike M.
You need to use TextInputLayout.setBoxBackgroundMode() method to use OutlineBox style
setBoxBackgroundMode (int boxBackgroundMode)
Set the mode for the box's background (filled, outline, or none).
Then you need to use TextInputLayout.BOX_BACKGROUND_OUTLINE) Constants
NOTE: To get the corner in your OutlineBox of TextInputLayout you need to use setBoxCornerRadii() method
SAMPLE CODE
public class MainActivity extends AppCompatActivity {
LinearLayout parentView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
parentView = findViewById(R.id.parentView);
TextInputLayout emailTextInputLayout = new TextInputLayout(this, null, R.style.Widget_MaterialComponents_TextInputLayout_OutlinedBox);
emailTextInputLayout.setHint("Please Enter Email Address");
emailTextInputLayout.setBoxBackgroundMode(TextInputLayout.BOX_BACKGROUND_OUTLINE);
emailTextInputLayout.setBoxCornerRadii(5, 5, 5, 5);
TextInputEditText edtEmail = new TextInputEditText(emailTextInputLayout.getContext());
emailTextInputLayout.addView(edtEmail);
parentView.addView(emailTextInputLayout);
TextInputLayout passTextInputLayout = new TextInputLayout(this, null, R.style.Widget_MaterialComponents_TextInputLayout_OutlinedBox);
passTextInputLayout.setHint("Please Enter Password");
passTextInputLayout.setBoxBackgroundMode(TextInputLayout.BOX_BACKGROUND_OUTLINE);
passTextInputLayout.setBoxCornerRadii(5, 5, 5, 5);
TextInputEditText edtPass = new TextInputEditText(passTextInputLayout.getContext());
passTextInputLayout.addView(edtPass);
parentView.addView(passTextInputLayout);
}
}
OUTPUT
Based on this answer: https://stackoverflow.com/questions/3246447/how-to-set-the-style-attribute-programmatically-in-android
Dynamic style change is not currently supported. You must set the style before the view is created (in XML).
That's the reason that TextInputLayout does not programmatically accept setting the outline boxed style.
Here is the simple solution:
You can use LayoutInflater
Instantiates a layout XML file into its corresponding View objects.
DEMO
Create a new layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.TextInputLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/userIDTextInputLayout"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<android.support.design.widget.TextInputEditText
android:id="#+id/userIDTextInputEditText"
android:layout_width="match_parent"
android:hint="Enter User Name"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
AndroidX (+Material Components for Android):
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.textfield.TextInputLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/userIDTextInputLayout"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/userIDTextInputEditText"
android:layout_width="match_parent"
android:hint="Enter User Name"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
Now using LayoutInflater add that TextInputLayout in your required layout
public class MainActivity extends AppCompatActivity {
LinearLayout rootView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rootView = findViewById(R.id.rootView);
View view = LayoutInflater.from(this).inflate(R.layout.temp_layout, null);
TextInputLayout userNameIDTextInputLayout=view.findViewById(R.id.userIDTextInputLayout);
TextInputEditText userNameInputEditText = view.findViewById(R.id.userIDTextInputEditText);
userNameIDTextInputLayout.setHint("Please Enter User Name");
rootView.addView(view);
}
}
OUTPUT
Note
If you want to add a TextInputLayout from XML, then please check out the following answer:
Outlined Edit Text from Material Design
If you want to add more than 5 TextInputLayouts programmatically, then please consider using a RecyclerView. Check out the following answers:
Dynamic form with repeating form
How can I validate recyclerview adapter TextInputEditText from fragment?
Hope this helps!
You can use the method applyStyle defined on the Theme class. In Kotlin, you can access it with the theme property on a Context (or subclass) instance.
The applyStyle function allows you to add a style to the current theme, that defines theme attributes referencing styles. After calling this method, you can pass the attribute as the third parameter of a View, like TextInputLayout, which will apply the desired styles while respecting the theme.
I used this technique in Splitties (a library which I authored), and there's some documentation plus examples that should help you: https://github.com/LouisCAD/Splitties/blob/v3.0.0-alpha02/views-dsl/README.md#using-styles-defined-in-xml
I did not yet add first class support for themes from Material Components in Splitties Views DSL, but you can do it yourself, and you can even open an issue to discuss it, or contribute so it gets integrated sooner.
This is how i did it, notice that you have to pass the context of TextInputLayout to TextInputEditText so that the style is passed on correctly.
[ src: https://material.io/components/text-fields/android#filled-text-field ]
val lp = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
val etInputLayout = TextInputLayout(context)
lp.setMargins(16, 16, 16, 16)
etInputLayout.layoutParams = lp
etInputLayout.boxBackgroundMode = TextInputLayout.BOX_BACKGROUND_OUTLINE
etInputLayout.boxBackgroundColor = Color.WHITE
etInputLayout.setBoxCornerRadii(8f, 8f, 8f, 8f)
val etInput = TextInputEditText(etInputLayout.context)
etInput.layoutParams = lp
etInputLayout.addView(etInput, lp)
I am creating simple AppCompatEditText adding OnFocusChangeListener and putting it in the simple TextInputLayout.
When AppCompatEditText loosing focus it's content should be validate by isValidParam method.
It worked till yesterday, when I used rev.23.0.3
But now, when I used rev.24.0.2, it gives error as below on the 1st row of isValidParam method.
java.lang.ClassCastException: android.widget.FrameLayout cannot be
cast to android.support.design.widget.TextInputLayout
I checked in debugging mode. AppCompatEditText.getpParent() really returns Framelayout instead TextInputLayout.
LinearLayout llParams = new LinearLayout(context);
llParams.setOrientation(LinearLayout.VERTICAL);
// Create label for param
final TextInputLayout tilParam = new TextInputLayout(context);
// Add label into layout
llParams.addView(tilParam);
// Create Editor for param
final AppCompatEditText etParam = new AppCompatEditText(context);
edParam.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus)
if (isValidParam(etParam)) {
do some thing;
} else {
do other thing;
}
}
});
tilParam.addView(etParam);
// validation method
boolean isValidParam(AppCompatEditText editText) {
TextInputLayout til = (TextInputLayout) editText.getParent();
String text = editText.getText().toString().trim();
if (!text.equls("some criteria") {
till.setError("Error text")
return false;
}
return true;
}
Update:
Use the widget TextInputEditText instead of EditText inside a TextInputLayout.
old answer
TextInputLayout textInputLayout = (TextInputLayout) editText.getParent().getParent();
That seems to work as a quick fix. Far from ideal.
getParentForAccessibility() worked for me
You can check if EditText is inside TextInputLayout using following method:
public static <ParentClass> ParentClass getFirstParent(View view, Class<ParentClass> parentClass) {
if (view.getParent() instanceof View) {
if (parentClass.isInstance(view.getParent())) {
return (ParentClass) view.getParent();
} else {
return getFirstParent((View) view.getParent(), parentClass);
}
} else {
return null;
}
}
Example of use:
TextInputLayout textInputLayout = getFirstParent(editText, TextInputLayout.class)
Just extracts from Android official documents:
<android.support.design.widget.TextInputLayout
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/form_username"/>
</android.support.design.widget.TextInputLayout>
Note: The actual view hierarchy present under TextInputLayout is NOT
guaranteed to match the view hierarchy as written in XML. As a result,
calls to getParent() on children of the TextInputLayout -- such as an
TextInputEditText -- may not return the TextInputLayout itself, but
rather an intermediate View. If you need to access a View directly,
set an android:id and use findViewById(int).
Therefore, to resolve the issue you have to turn to findViewById instead of getParent due to an extra layout in between introduced in version 24.
You can check the code of the TextInputLayout v24.x.x.
Now it works with a FrameLayout.
#Override
public void addView(View child, int index, final ViewGroup.LayoutParams params) {
if (child instanceof EditText) {
mInputFrame.addView(child, new FrameLayout.LayoutParams(params));
//...
} else {
// Carry on adding the View...
super.addView(child, index, params);
}
}
where mInputFrame is a FrameLayout.
It is the reason of your issue (the parent is a FrameLayout).
Just pass the tilParam as parameter , instead of using getParent() if you need to use it.
TextInputLayout has a method called getEditText(). This may be an alternate way to solve your problem. Instead of starting from the EditText itself and getting the parent TextInputLayout, you can start with the TextInputLayout and simply get the EditText child view. For xml generated views, the following code is an example:
TextInputLayout someInputLayout = findViewById(R.id.some_input_layout);
EditText someEditText = someInputLayout.getEditText();
String text = someEditText.getText().toString();
This could possibly be a more desired solution as it does not require any external methods, though this would not solve your problem if it is required that you start from EditText for some reason. I know this has been answered a long time ago, but I was using #sylwano's solution, until I found for my particular problem it was better to do as above.
The border displays a default color (that's orange on my Nexus S) while scrolling a ListView to the limit. How to change that color?
I really don't know how to explain it. Just look at this picture:
So, how to change the highlight color when the ListView scrolling to the border? using themes or styles
The solution is to use setOverscrollFooter(null) and setOverscrollHeader(null).
The documentation is here !
You can also set it directly in the XML :
<ListView android:overScrollMode="never" />
Or specify the footer and the header :
<ListView
android:overscrollHeader="#null"
android:overscrollFooter="#null" />
N.B. : There is also a property fadingEdge that may interest you.
"Overscroll" methodes are supported starting API level 9
Finally I found the solution.
setOverscrollFooter(null) and setOverscrollHeader(null) does not work. At least on 2.3.*. Setting attributes from *.xml doesn't help too.
setOverScrollMode(View.OVER_SCROLL_NEVER) causes glitchy scrolling. At least on 2.3.*.
The only solution that really works involves the use of Java Reflection.
It works even with ugly custom Samsung listviews with bounce overscroll effect.
Here is a snippet:
#Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
//onOverScrolled method must be overrided, or we will see the background of the listview when overscroll fast.
}
private void removeOverscrollEffect() {
try {
Class<?> superClass = getClass().getSuperclass().getSuperclass();
Field field = superClass.getDeclaredField("mEdgeGlowTop");
field.setAccessible(true);
Object edgeGlowTop = field.get(this);
if (edgeGlowTop != null) {
Class<? extends Object> edgeClass = edgeGlowTop.getClass();
Field edgeDrawable = edgeClass.getDeclaredField("mEdge");
edgeDrawable.setAccessible(true);
edgeDrawable.set(edgeGlowTop, new ColorDrawable(Color.TRANSPARENT));
Field glowDrawable = edgeClass.getDeclaredField("mGlow");
glowDrawable.setAccessible(true);
glowDrawable.set(edgeGlowTop, new ColorDrawable(Color.TRANSPARENT));
field.set(this, edgeGlowTop);
}
Field fieldBottom = superClass.getDeclaredField("mEdgeGlowBottom");
fieldBottom.setAccessible(true);
Object edgeGlowBottom = fieldBottom.get(this);
if (edgeGlowBottom != null) {
Class<? extends Object> edgeClassBottom = edgeGlowBottom.getClass();
Field edgeDrawableBottom = edgeClassBottom.getDeclaredField("mEdge");
edgeDrawableBottom.setAccessible(true);
edgeDrawableBottom.set(edgeGlowBottom, new ColorDrawable(Color.TRANSPARENT));
Field glowDrawableBottom = edgeClassBottom.getDeclaredField("mGlow");
glowDrawableBottom.setAccessible(true);
glowDrawableBottom.set(edgeGlowBottom, new ColorDrawable(Color.TRANSPARENT));
fieldBottom.set(this, edgeGlowBottom);
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
I hope this helps.
Here is a nice article on ListView Backgrounds Optimization.
To fix this issue, all you have to do is either disable the cache color hint optimization, if you use a non-solid color background, or set the hint to the appropriate solid color value. You can do this from code (see setCacheColorHint(int)) or preferably from XML, by using the android:cacheColorHint attribute. To disable the optimization, simply use the transparent color #00000000. The following screenshot shows a list with android:cacheColorHint="#00000000"
Use it in XML file--
<ListView ---
android:fadingEdge="none"
---</ListView>
EDITED:
Using fading edges may introduce noticeable performance degradations and should be used only when required by the application's visual design. To request fading edges with API level 14 and above, use the android:requiresFadingEdge attribute instead.
Check this API link
I used kord's answer until it stopped working in Lollipop, so I changed into this:
try {
Class<?> superClass = getClass().getSuperclass().getSuperclass();
Field field = superClass.getDeclaredField("mEdgeGlowTop");
field.setAccessible(true);
field.set(this, new NoEdgeEffect(getContext()));
Field fieldBottom = superClass.getDeclaredField("mEdgeGlowBottom");
fieldBottom.setAccessible(true);
fieldBottom.set(this, new NoEdgeEffect(getContext()));
} catch (Exception e) {
}
class NoEdgeEffect extends EdgeEffect
{
public NoEdgeEffect(Context context) {
super(context);
}
public boolean draw(Canvas canvas) {
// Do nothing
return false;
}
}
you can use android:listSelector="#002234".
In above value can be any color code that you can find on internet easily.
When an EditText is in password mode, it seems that the hint is shown in a different font (courrier?). How can I avoid this? I would like the hint to appear in the same font that when the EditText is not in password mode.
My current xml:
<EditText
android:hint="#string/edt_password_hint"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:password="true"
android:singleLine="true" />
Changing the typeface in xml didn't work on the hint text for me either. I found two different solutions, the second of which has better behavior for me:
Remove android:inputType="textPassword" from your xml file and instead, in set it in java:
EditText password = (EditText) findViewById(R.id.password_text);
password.setTransformationMethod(new PasswordTransformationMethod());
With this approach, the hint font looks good but as you're typing in that edit field, you don't see each character in plain text before it turns into a password dot. Also when making input in fullscreen, the dots will not appear, but the password in clear text.
Leave android:inputType="textPassword" in your xml. In Java, ALSO set the typeface and passwordMethod:
EditText password = (EditText) findViewById(R.id.register_password_text);
password.setTypeface(Typeface.DEFAULT);
password.setTransformationMethod(new PasswordTransformationMethod());
This approach gave me the hint font I wanted AND gives me the behavior I want with the password dots.
I found this useful tip from Dialogs Guide
Tip: By default, when you set an EditText element to use the "textPassword" input type, the font family is set to monospace, so you should change its font family to "sans-serif" so that both text fields use a matching font style.
For example
android:fontFamily="sans-serif"
This is what I did to fix this problem. For some reason I didn't have to set the transformation method so this may be a better solution:
In my xml:
<EditText
android:id="#+id/password_edit_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Password"
android:inputType="textPassword" />
In my Activity:
EditText password = (EditText) findViewById( R.id.password_edit_field );
password.setTypeface( Typeface.DEFAULT );
The setTransformationMethod approach breaks android:imeOption for me, and allows carriage returns to be typed into the password field. Instead I'm doing this:
setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
setTypeface(Typeface.DEFAULT);
And am not setting android:password="true" in XML.
The answer manisha provided does work, but it leaves the password field in a nonstandard state compared to the default. That is, the default fontface then applies also to the password field, including both the dot replacements and the preview characters that appears before being replaced with the dots (as well as when it is a "visible password" field).
To fix this and make it 1) look and act exactly like the default textPassword input type, but also 2) allow the hint text to appear in a default (non-monospace) font, you need to have a TextWatcher on the field that can toggle the fontface properly back and forth between Typeface.DEFAULT and Typeface.MONOSPACE based on whether it is empty or not. I created a helper class that can be used to accomplish that:
import android.graphics.Typeface;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
/**
* This class watches the text input in a password field in order to toggle the field's font so that the hint text
* appears in a normal font and the password appears as monospace.
*
* <p />
* Works around an issue with the Hint typeface.
*
* #author jhansche
* #see <a
* href="http://stackoverflow.com/questions/3406534/password-hint-font-in-android">http://stackoverflow.com/questions/3406534/password-hint-font-in-android</a>
*/
public class PasswordFontfaceWatcher implements TextWatcher {
private static final int TEXT_VARIATION_PASSWORD =
(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
private TextView mView;
/**
* Register a new watcher for this {#code TextView} to alter the fontface based on the field's contents.
*
* <p />
* This is only necessary for a textPassword field that has a non-empty hint text. A view not meeting these
* conditions will incur no side effects.
*
* #param view
*/
public static void register(TextView view) {
final CharSequence hint = view.getHint();
final int inputType = view.getInputType();
final boolean isPassword = ((inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION))
== TEXT_VARIATION_PASSWORD);
if (isPassword && hint != null && !"".equals(hint)) {
PasswordFontfaceWatcher obj = new PasswordFontfaceWatcher(view);
view.addTextChangedListener(obj);
if (view.length() > 0) {
obj.setMonospaceFont();
} else {
obj.setDefaultFont();
}
}
}
public PasswordFontfaceWatcher(TextView view) {
mView = view;
}
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
// Not needed
}
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
if (s.length() == 0 && after > 0) {
// Input field went from empty to non-empty
setMonospaceFont();
}
}
public void afterTextChanged(final Editable s) {
if (s.length() == 0) {
// Input field went from non-empty to empty
setDefaultFont();
}
}
public void setDefaultFont() {
mView.setTypeface(Typeface.DEFAULT);
}
public void setMonospaceFont() {
mView.setTypeface(Typeface.MONOSPACE);
}
}
Then to make use of it, all you need to do is call the register(View) static method. Everything else is automatic (including skipping the workaround if the view does not require it!):
final EditText txtPassword = (EditText) view.findViewById(R.id.txt_password);
PasswordFontfaceWatcher.register(txtPassword);
There are many way for solving this problem but each way have pros and cons. Here is my testing
I only face this font problem in some device (list at the end of my answer) when enable input password by
edtPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
If I use android:inputType="textPassword", this problem don't happened
Something I have tried
1) Use setTransformationMethod instead inputType
edtPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
Font will working well
Keyboard display not very well (it only display text, don't display number on top of text)
2) Use Typeface.DEFAULT
setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
setTypeface(Typeface.DEFAULT);
Keyboard display well,
Font may working not well. Example sans-serif-light is a default font for all View in my application => after setTypeface(Typeface.DEFAULT), the EditText font still look different in some device
3) Use android:fontFamily="sans-serif"
For some device, it will CRASH, check my answer here https://stackoverflow.com/a/52421199/5381331. And also font still look different
MY SOLUTION
cache the typeface before setInputType then reuse it
Typeface cache = edtPassword.getTypeface();
edtPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
edtPassword.setTypeface(cache);
Testing
Some device face font problem
Xiaomi A2 (8.0.1)
Pixel XL (8.1.0)
Sony Xperia Z5 Au (SOV32) (6.0)
Arrow NX (F-04G) (6.0.1)
Kyocera (S2) (7.0)
Some device not face font problem
Samsung S4 (SC-04E) (5.0.1)
Samsung Galaxy Node 5 (5.1.1)
Samsung S7 Edge (SM-G935F) (7.0)
The other answers are the right solution for most cases.
However, if you're using a custom EditText subclass to, say, apply a custom font by default, there's a subtle issue. If you set the custom font in the constructor of your subclass, it will still be overwritten by the system if you set inputType="textPassword".
In this case, move your styling to onAttachedToWindow after your super.onAttachedToWindow call.
Example implementation:
package net.petosky.android.ui;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.EditText;
/**
* An EditText that applies a custom font.
*
* #author cory#petosky.net
*/
public class EditTextWithCustomFont extends EditText {
private static Typeface customTypeface;
public EditTextWithCustomFont(Context context) {
super(context);
}
public EditTextWithCustomFont(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextWithCustomFont(
Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* Load and store the custom typeface for this app.
*
* You should have a font file in: project-root/assets/fonts/
*/
private static Typeface getTypeface(Context context) {
if (customTypeface == null) {
customTypeface = Typeface.createFromAsset(
context.getAssets(), "fonts/my_font.ttf");
}
return customTypeface;
}
/**
* Set a custom font for our EditText.
*
* We do this in onAttachedToWindow instead of the constructor to support
* password input types. Internally in TextView, setting the password
* input type overwrites the specified typeface with the system default
* monospace.
*/
#Override protected void onAttachedToWindow() {
super.onAttachedToWindow();
// Our fonts aren't present in developer tools, like live UI
// preview in AndroidStudio.
if (!isInEditMode()) {
setTypeface(getTypeface(getContext()));
}
}
}
I know this may be the older one but I have humped into something related to this issue when I used InputTypeand app:passwordToggleEnabled="true"together.
So, writing this, as it may help someone over here.
I want to use a custom font to password field along with app:passwordToggleEnabled option for my password input field. But in 27.1.1 (while writing this) support library, it was crashing.
So the code was like below,
<android.support.design.widget.TextInputLayout
android:id="#+id/input_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/_10dp"
android:layout_marginTop="#dimen/_32dp"
android:hint="#string/current_password"
android:textColorHint="#color/hint_text_color"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:passwordToggleEnabled="true"
app:passwordToggleTint="#color/black">
<EditText
android:id="#+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|left"
android:maxLines="1"
android:textAlignment="viewStart"
android:textColor="#color/black"
android:textColorHint="#color/camel"
android:textSize="#dimen/txt_16sp"
app:font_style="regular"
app:drawableEnd="#drawable/ic_remove_eye" />
</android.support.design.widget.TextInputLayout>
Above code do not have inputType defined in XML
EditText password = (EditText) findViewById(R.id.password);
password.setTransformationMethod(new PasswordTransformationMethod());
And in Java, setTransformationMethod will help me acquire the properties of textPassword input type and also I'm happy my custom font style.
But the below-mentioned crash happened in all API levels with 27.1.1 support library.
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.support.design.widget.CheckableImageButton.setChecked(boolean)'
on a null object reference
This was crashing due to the onRestoreInstanceState inside TextInputLayout class.
Reproduce Steps: Toggle the password visibility and minimize the app and open from the recent apps. Uh,ho Crashed!
All I needed is default password toggle option (using support library) and custom font in the password input field.
After some time, figured out by doing as below,
<android.support.design.widget.TextInputLayout
android:id="#+id/input_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/_10dp"
android:layout_marginTop="#dimen/_32dp"
android:hint="#string/current_password"
android:textColorHint="#color/hint_text_color"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:passwordToggleEnabled="true"
app:passwordToggleTint="#color/black">
<EditText
android:id="#+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|left"
android:maxLines="1"
android:textAlignment="viewStart"
android:textColor="#color/black"
android:textColorHint="#color/camel"
android:textSize="#dimen/txt_16sp"
app:font_style="regular"
app:drawableEnd="#drawable/ic_remove_eye"
android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout>
In XML, added android:inputType="textPassword"
TextInputLayout inputPassword = findViewById(R.id.input_password);
EditText password = findViewById(R.id.password);
EditText userName = findViewById(R.id.user_name);
// Get the typeface of user name or other edit text
Typeface typeface = userName.getTypeface();
if (typeface != null)
inputLayout.setTypeface(typeface); // set to password text input layout
In above java code,
I acquired the custom typeface from username EditText and applied it to TextInputLayout of the password field. Now you don't need to set the typeface explicitly to the password EditText as it will acquire the TextInputLayout property.
Also, I removed password.setTransformationMethod(new PasswordTransformationMethod());
By doing this way, passwordToggleEnabled is working, the custom font is also applied and bye-bye to the crash. Hope this issue will be fixed in upcoming support releases.
You can also use a custom Widget. It's very simple and it doesn't clutter your Activity/Fragment code.
Here's the code:
public class PasswordEditText extends EditText {
public PasswordEditText(Context context) {
super(context);
init();
}
public PasswordEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PasswordEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setTypeface(Typeface.DEFAULT);
}
}
And your XML will look like this:
<com.sample.PasswordEditText
android:id="#+id/password_edit_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Password"
android:inputType="textPassword"
android:password="true" />
use the calligraphy library.
then it still wont update the password fields with the right font. so do this in code not in xml:
Typeface typeface_temp = editText.getTypeface();
editText.setInputType(inputType); /*whatever inputType you want like "TYPE_TEXT_FLAG_NO_SUGGESTIONS"*/
//font is now messed up ..set it back with the below call
editText.setTypeface(typeface_temp);
I recently added the ability to change toggle monospace on/off to a extension of EditText specifically for passwords it may help some people. It doesn't use android:fontFamily so is compatible <16.
You can also use the
<android.support.design.widget.TextInputLayout/>
together with
<android.support.v7.widget.AppCompatEditText/>
I use this solution to toggle the Typeface depending on hint visibility. It's similar to Joe's answer, but extending EditText instead:
public class PasswordEditText extends android.support.v7.widget.AppCompatEditText {
public PasswordEditText(Context context) {
super(context);
}
public PasswordEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
if (text.length() > 0) setTypeface(Typeface.MONOSPACE);
else setTypeface(Typeface.DEFAULT);
}
}
In case you are using the calligraphy library in combination with a TextInputLayout and an EditText, the following code works well.
EditText password = (EditText) findViewById(R.id.password);
TextInputLayout passwordLayout = (TextInputLayout) findViewById(R.id.passwordLayout);
Typeface typeface_temp = password.getTypeface();
password.setInputType(InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_VARIATION_PASSWORD);
password.setTypeface(typeface_temp);
passwordLayout.setTypeface(typeface_temp);
A weird case perhaps, but I have experimented with this and found out that:
password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
password.setTransformationMethod(new PasswordTransformationMethod());
changed the size of the font of the hint instead of the font itself! This is still an undesired effect. Strangely enough, the reverse operation:
password.setTransformationMethod(new PasswordTransformationMethod());
password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
Keeps the same font size.
I found a sure solution to this problem
Best way to Hello ,I found a sure solution to this problem
The best way is to create a custom editText and save value of typeface as a temp and then apply the method to the InputType changes , Finally, we set back the value of temp type face to the editText. like so :
public class AppCompatPasswordEditText extends AppCompatEditText {
public AppCompatPasswordEditText(Context context) {
super(context);
}
public AppCompatPasswordEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AppCompatPasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
// Our fonts aren't present in developer tools, like live UI
// preview in AndroidStudio.
Typeface cache = getTypeface();
if (!isInEditMode() && cache != null) {
setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
setTypeface(cache);
}
}
}
This how to make input password that has hint which not converted to * and default typeface !!.
On XML :
android:inputType="textPassword"
android:gravity="center"
android:ellipsize="start"
android:hint="Input Password !."
On Activity :
inputPassword.setTypeface(Typeface.DEFAULT);
thanks to : mango and rjrjr for the insight :D.
like the above but make sure the fields do not have the bold style in xml as they will never look the same even with the above fix!