I'm new in android working on an app that gives the user info about all font's of Google.
For that, I need to make an app with a TextView Something like this
On click of the TextView, the font will change With text.
I'm thinking about using onclicklistener
you can put "your_font.ttf" file in asset folder then import it with
Typeface custom_font_1 = Typeface.createFromAsset(getAssets(), "your_font.ttf");
then assign it to your showCaseTextView with this
showCaseTextView.setTypeFace(custom_font_1);
then in your onClickListener of showCaseTextView to change your specifiedTextView font do like this
specifiedTextView.setTypeFace(custom_font_1);
and repeat it for other fonts.
You can implement your own custom font with TextView, EditText, Button etc.. by using android attributes.
How to
-Here are some steps to use:
1.Create attribute file (res->values->attrs.xml)
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<declare-styleable name="TextElement">
<attr name="font" format="string"/>
<attr name="underline" format="boolean"/>
</declare-styleable>
</resources>
2.Create Custom TextView class (anywhere in java folder)
3. Use attributes inside your layout file
4. and just run your code.
Here is the full example of your question, you can go through this exmaple:
Full Demonstration
Have 2 way to archive this
1st way
public class FontCache {
private static HashMap<String, Typeface> fontCache = new HashMap<>();
public static Typeface getTypeface(String fontname, Context context) {
Typeface typeface = fontCache.get(fontname);
if (typeface == null) {
try {
typeface = Typeface.createFromAsset(context.getAssets(), fontname);
} catch (Exception e) {
return null;
}
fontCache.put(fontname, typeface);
}
return typeface;
}
}
This caches the fonts while minimizing the number of accesses to the assets. Now, since we've a method to access our custom font, let's implement a class, which extends TextView.
Extending TextView
Next, we'll create a new Java class, which extends TextView. This allows us to use that class in all XML views. It inherits all functionality and properties of a regular TextView; but adds our custom font.
Once again, we're taking a peek at the source code of our eat foody project. The code might look complex for a second, but is straight-forward:
public class EatFoodyTextView extends TextView {
public EatFoodyTextView(Context context) {
super(context);
applyCustomFont(context);
}
public EatFoodyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
applyCustomFont(context);
}
public EatFoodyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
applyCustomFont(context);
}
private void applyCustomFont(Context context) {
Typeface customFont = FontCache.getTypeface("SourceSansPro-Regular.ttf", context);
setTypeface(customFont);
}
}
The first three methods are just constructors, which we override to call a single method applyCustomFont(). That method is the important piece of the puzzle. It simply gets the (hopefully cached) font from our FontCache class. Lastly, we've to call setTypeface() with the font and we're almost done. In case you're wondering, we can call the setTypeface() directly (and not on a TextView object), since we're extending the TextView class.
Using the Class
You might wonder, if so much preparation is worth the effort. In this section you'll see that it is indeed. Because all you've left to do is use the class in an XML view and it automatically has your custom font. There is no Java code necessary!
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.futurestudio.foody.views.EatFoodyTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/eat_foody_green_dark"
android:textSize="20sp"
android:text="Future Studio Blog"
android:layout_marginBottom="24dp"/>
</RelativeLayout>
As you can see, you can continue to use all niceties (e.g. textSize, textColor) of TextView. Now, just replace all elements with the class we just created, for example and you applied your custom font everywhere!
(Ref: https://futurestud.io/tutorials/custom-fonts-on-android-extending-textview)
2nd way
Follow Google guide support from API 26 (Android 8) https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml
Make change between textview to change font
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textview_normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/eat_foody_green_dark"
android:textSize="20sp"
android:text="Future Studio Blog"
android:layout_marginBottom="24dp"/>
<com.futurestudio.foody.views.EatFoodyTextView
android:id="#+id/textview_custom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/eat_foody_green_dark"
android:textSize="20sp"
android:text="Future Studio Blog"
android:visibility="gone"
android:layout_marginBottom="24dp"/>
</RelativeLayout>
attention at android:visibility="gone"
in Activity you use this code to toggle between 2 TextViews
final TextView normalTextView = findViewById(R.id.textview_normal);
final TextView customTextView = findViewById(R.id.textview_custom);
normalTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
normalTextView.setVisibility(View.GONE);
customTextView.setVisibility(View.VISIBLE);
}
});
customTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
normalTextView.setVisibility(View.VISIBLE);
customTextView.setVisibility(View.GONE);
}
});
I'm using Android SharedPreferences API to build a settings screen.
I've one setting which I need a long text to explain the user its meaning (I would like to have something like main title and smaller subtitle,but i think it would require to much customization)
the settings.xml is like:
<EditTextPreference
android:defaultValue="15"
android:inputType="number"
android:icon="#drawable/ic_timer"
android:key="#string/pref_comment_interval"
android:persistent="true"
android:lines="2"
android:title="#string/time_between_comments" />
but even setting lines=2 and breaking the line with \n at time_between_comments the text is getting wrapped.
<string name="time_between_comments">Time between comments (in seconds)\nLower is faster</string>
like:
how can i make the text to break the line?
By default, the title of EditTextPreference is singleLine="true"
So we should custom it as below
public class MultiLineTitleEditTextPreference extends EditTextPreference {
public MultiLineTitleEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MultiLineTitleEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MultiLineTitleEditTextPreference(Context context) {
super(context);
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
TextView textView = (TextView) view.findViewById(your_package.R.id.title);
if (textView != null) {
textView.setSingleLine(false);
}
}
}
This doesn't work for all Preference types, but it works for EditTextPreference.
Add <![CDATA[ \n]]> around the first line of your title like in this example:
<string name="pref_title_special_with_note"><![CDATA[Special Title\n]]><small><i> ** followed by second line note</i></small></string>
This will display the second line in smaller text size and italic, but that's just decoration.
I am trying to find a way to override a non-public attribute of an android style, more specifically an atttribute named itemColor of the Widget.FragmentBreadCrumbs style. This style affects the text color of the breadcumb in a PreferenceActivity when a preference fragment is being displayed on the right pane for large screens. It is used by the class FragmentBreadCrumbs.
My application uses a custom theme that extends Theme.Holo.Light and the theme breaks on API 23 so I am trying to find a workaround.
The aforementioned style sets a default value to itemColor of #null which is not overridden in the Holo theme while for example it is set to a valid value for the Material theme. As a result the title of the breadcrumb is not visible (see screenshot for API 19 and screenshot for API 23)
I guess what I am trying to do is to find a way that could change a private value of a theme similar to the way reflection can be used to modify the private field's value of a class. Alternatively the ContextThemeWrapper seems to be promising but I simple don't get how can I use it or even if it is applicable in my situtation.
What I need is that after FragmentBreadCrumbs class executes its constructor below the mTextColor attribute to not be #null (which I am guessing is 0) as is set by the Android theme configuration but to have a valid color value.
Do you think this is possible?
public FragmentBreadCrumbs(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
final TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.FragmentBreadCrumbs, defStyleAttr, defStyleRes);
mGravity = a.getInt(com.android.internal.R.styleable.FragmentBreadCrumbs_gravity,
DEFAULT_GRAVITY);
mLayoutResId = a.getResourceId(
com.android.internal.R.styleable.FragmentBreadCrumbs_itemLayout,
com.android.internal.R.layout.fragment_bread_crumb_item);
/* This is the value needed to be overridden */
mTextColor = a.getColor(
com.android.internal.R.styleable.FragmentBreadCrumbs_itemColor,
0);
a.recycle();
}
Unfortunately the toolchain will report an error if you try to use android:itemColor because this does not correspond to a public attribute name, so you cannot even make a style with this attribute.
The only thing I can think of is to change the text color via reflection just after the views have been constructed(/inflated). You would want to do this as early as possible, before the first time updateCrumbs() is run inside of FragmentBreadCrumbs. Perhaps you can override onCreate() of PreferenceActivity or onCreateView() of PreferenceFragment (whichever is applicable here) and do something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentBreadCrumbs fbc = (FragmentBreadCrumbs) findViewById(...);
int color = ...;
FragmentBreadCrumbsUtils.setTextColor(fbc, color);
}
public class FragmentBreadCrumbsUtils {
private static final Field FRAGMENT_BREAD_CRUMBS_TEXT_COLOR = findField();
private static Field findField() {
try {
Field f = FragmentBreadCrumbs.class.getDeclaredField("mTextColor");
f.setAccessible(true);
return f;
} catch (Throwable t) {
// don't fail for any reason, just log it
Log.e("FragmentBreadCrumbsUtils",
"Couldn't find mTextColor field in FragmentBreadCrumbs",
t);
}
return null;
}
public static void setTextColor(FragmentBreadCrumbs fbc, int color) {
if (FRAGMENT_BREAD_CRUMBS_TEXT_COLOR == null) {
return; // can't do anything, we don't have the field
}
try {
FRAGMENT_BREAD_CRUMBS_TEXT_COLOR.set(fbc, color);
} catch (Throwable t) {
// don't fail for any reason, just log it
Log.e("FragmentBreadCrumbsUtils",
"Couldn't set mTextColor field in FragmentBreadCrumbs",
t);
}
}
}
I've found several posts regarding this topic, but all of this topics either sets the font with setTypeFace() method on a TextView object, or creating a custom class which sets the font to Roboto and extends TextView. As far as I know from API-Level 11(?) or something, we are able to set the TypeFace as a xml attribute, some how. Like this:
<TextView
android:id="#+id/profileHeader"
android:layout_width="100dp"
android:layout_height="100dp"
android:typeface="roboto"
android:text="Hello, world">
</TextView>
What is the right way to do this? Is it possible to have a fallback if the application runs on a device lower than API level 11(?) something like:
android:typeface="roboto|monospace|serif"
Take a look at the RobotoTextView project. Works down to Android 1.5, and you can set the typeface using XML attributes. It also includes other views like RobotoButton, RobotoCheckbox, etc.
I don't see a way you can define an external typeface as a xml attribute. You should store the typeface in the assets and call:
tv.setTypeface( Typeface.createFromAsset( context.getAssets(), roboto.ttf ) );
You can not set font directly from assets like this you have to do as follow in onCreate. This will make same thing what you want to do.
TextView tvTextView = (TextView) findViewById(R.id.textView1);
Typeface typeface = Typeface.createFromAsset(getAssets(),"Roboto.ttf");
tvTextView.setTypeface(typeface);
Hope it will help you out.:D
The android:typeface attribute only has a few valid options (according to the Android docs)...
normal
sans
serif
monospace
If you need the Roboto font in your app for older devices, you need to include the Roboto TTF files into your project.
The most obvious way to use these fonts is to use the setTypeface() method of TextView, but if you want to specify it in XML instead, you must create a custom TextView and create your own styleable attribute for your custom TextView.
This topic is all over the Internet.
For JellyBean (4.1) onward you can use the method provided in this StackOverflow topic. It will fallback gracefully to sans in older devices.
If you must fallback to monospace or serif, declare a folder layout-v16 where you use the font you chose, i.e., "sans-serif-condensed", and in the default folder you use the "monospace" or "serif" font.
If you want to fallback to a non-default font, you can programatically check the android version and choose the appropriate action, i.e.:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
TextView textView = (TextView) findViewById(R.id.textView_id);
Typeface myFont = Typeface.createFromAsset(getAssets(),"RobotoCondensed.ttf");
textView.setTypeface(myFont);
}
This is for future people running in to the same issue as I have. Setting typeface tends to take up lot of memory when it comes to loading multiple rows. Using the following two codes together to actually make it work smoothly. I got the solution from stackoverflow but they answers were not listed together.
public class RobotoTextView extends TextView {
Context context;
public RobotoTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
}
public RobotoTextView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public RobotoTextView(Context context) {
super(context);
this.context = context;
}
public void setTypeface(Typeface tf, int style) {
if (!isInEditMode()) {
if (style == Typeface.NORMAL) {
super.setTypeface(TypeFaceProvider.getTypeFace(getContext(), "fonts/Roboto-Light.ttf"));
} else if (style == Typeface.ITALIC) {
super.setTypeface(TypeFaceProvider.getTypeFace(getContext(), "fonts/Roboto-LightItalic.ttf"));
} else if (style == Typeface.BOLD) {
super.setTypeface(TypeFaceProvider.getTypeFace(getContext(), "fonts/Roboto-Bold.ttf"));
} else if (style == Typeface.BOLD_ITALIC) {
super.setTypeface(TypeFaceProvider.getTypeFace(getContext(), "fonts/Roboto-BoldItalic.ttf"));
}
}
}
public class TypeFaceProvider {
private static Hashtable<String, Typeface> sTypeFaces = new Hashtable<String, Typeface>(
4);
public static Typeface getTypeFace(Context context, String fileName) {
Typeface tempTypeface = sTypeFaces.get(fileName);
if (tempTypeface == null) {
tempTypeface = Typeface.createFromAsset(context.getAssets(),
fileName);
sTypeFaces.put(fileName, tempTypeface);
}
return tempTypeface;
}
}
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!