How to get the style attribute of a TextView - android

I am creating a Custom TextView class MTextView . Inside the constructor i want to know the value of style attrib of the textview so that I can set different typefaces depending on whether style is set to bold or not. But there is no getStyle() function ? What to do?
public class MTextView extends TextView{
public MTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if(style.equals(TypeFace.bold)) //how to get style?
setTypeface(Typeface.createFromAsset(getContext().getAssets(),"rc.ttf"));
}
}

You can get the textStyle from the TextView's getTypeface() instance method.
int style = getTypeface().getStyle();
If no textStyle has been specified (i.e. you want to support normal textStyle) then getTypeface() can return null.
In the case where it is not null it may be best to assume textStyle is implicitly set to normal.

Use this code:
if (attrs != null) {
try {
int style = attrs.getAttributeIntValue(
"http://schemas.android.com/apk/res/android",
"textStyle",
Typeface.NORMAL);
setTypeface(Typeface.createFromAsset(
getContext().getAssets(),
"rc.ttf"),
style);
}
catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}

Related

Can you set a fontFamily variable in Android? [duplicate]

This question already has answers here:
Android - Using Custom Font
(21 answers)
Closed 3 years ago.
I would like to know if it is possible to set a fontFamily variable in Android Studio like you can do with Strings.
I don't want to do anything fancy like custom fonts. I just want to have the convenience of being able to change the fontFamily of every textView at once.
So far I was not able to find a font tag. I hope that some of you can help me.
Best regards and thanks in advance :)
Make a Custom TextView Class and use it in textview
public class MetaFont extends TextView {
public MetaFont(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
a(attributeSet);
}
public MetaFont(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
a(attributeSet);
}
public MetaFont(Context context) {
super(context);
a(null);
}
private void a(AttributeSet attributeSet) {
if (attributeSet != null) {
TypedArray obtainStyledAttributes = getContext().obtainStyledAttributes(attributeSet, ATTRS);
setTypeface(Typeface.createFromAsset(getContext().getAssets(), "Comfortaa.ttf"));
obtainStyledAttributes.recycle();
}
}
}
Put the font otf file to /assets/fonts, create a utils for dealing with fonts like:
public class TypefaceUtils {
private static Typeface myFont1;
private static Typeface myFont2;
public static Typeface getMyFont1() {
return myFont1;
}
public static Typeface getMyFont2() {
return myFont2;
}
public static void initTypeface(Context context) {
if (context != null) {
myFont1 = Typeface.createFromAsset(context.getAssets(), "fonts/myfont1.otf");
myFont2 = Typeface.createFromAsset(context.getAssets(), "fonts/myfont2.otf");
}
}
}
Init fonts when onCreate your MainAcitivity
TypefaceUtils.initTypeface(this);
Set the font where you need, like:
textView.setTypeface(TypefaceUtils.getMyFont1());

Is it possible to have different font for floating text and hint text of InputTextLayout

Currently, I would like to have a bold effect on my floating text of InputTextLayout. Here's what I'm doing
this.usernameTextInputLayout.setTypeface(Utils.ROBOTO_BOLD_TYPE_FACE);
It works as expected. The floating text (Username) has became bold.
However, this will create another undesired effect for me. The hint text will become bold as well.
You can compare the above 2 images. Please take note, for comparison purpose, I just leave passwordTextInputLayout as it is.
Is it possible to have different fonts, for floating text and hint text of InputTextLayout?
As you know, TextInputLayout uses a private helper class to handle the hint text stylings and animations. This class - CollapsingTextHelper - maintains separate typefaces for its collapsed and expanded states. We just need to set the right one, which we'll do using reflection.
I usually package these kinds of functionalities into custom subclasses, so I'll do the same here. If you don't want to use a subclass, the reflection stuff could be easily pulled into some simple methods you can put in your Activity or utility class.
public class CustomTextInputLayout extends TextInputLayout {
private Object collapsingTextHelper;
private Method setCollapsedTypefaceMethod;
private Method setExpandedTypefaceMethod;
public CustomTextInputLayout(Context context) {
this(context, null);
}
public CustomTextInputLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
try {
Field cthField = TextInputLayout.class
.getDeclaredField("mCollapsingTextHelper");
cthField.setAccessible(true);
collapsingTextHelper = cthField.get(this);
setCollapsedTypefaceMethod = collapsingTextHelper
.getClass().getDeclaredMethod("setCollapsedTypeface", Typeface.class);
setCollapsedTypefaceMethod.setAccessible(true);
setExpandedTypefaceMethod = collapsingTextHelper
.getClass().getDeclaredMethod("setExpandedTypeface", Typeface.class);
setExpandedTypefaceMethod.setAccessible(true);
}
catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) {
collapsingTextHelper = null;
setCollapsedTypefaceMethod = null;
setExpandedTypefaceMethod = null;
e.printStackTrace();
}
}
public void setCollapsedTypeface(Typeface typeface) {
if (collapsingTextHelper == null) {
return;
}
try {
setCollapsedTypefaceMethod.invoke(collapsingTextHelper, typeface);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
public void setExpandedTypeface(Typeface typeface) {
if (collapsingTextHelper == null) {
return;
}
try {
setExpandedTypefaceMethod.invoke(collapsingTextHelper, typeface);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
Somewhat counterintuitively, TextInputLayout's collapsed state is when the hint is the floating label above the EditText. Its expanded state is when the hint is in the "normal" position, inside the EditText. Methods to set the typeface for both states are given above.
This is a drop-in replacement for TextInputLayout, and you can use it in your layouts just as you would that. For example:
<com.mycompany.myapp.CustomTextInputLayout
android:id="#+id/username_til"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintTextAppearance="#style/TextLabel">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:hint="Username" />
</com.mycompany.myapp.CustomTextInputLayout>
In your code, to set the typeface of the floating text hint:
CustomTextInputLayout usernameTextInputLayout =
(CustomTextInputLayout) findViewById(R.id.username_til);
usernameTextInputLayout.setCollapsedTypeface(Utils.ROBOTO_BOLD_TYPE_FACE);
The CollapsingTextHelper methods used above were added in version 23.1.0 of the support library. If you're using a previous version, or you're getting a NoSuchMethodException for some other reason, the original version of my answer that directly sets the typeface fields should work, no matter the version.

How to override an android style's private attribute

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);
}
}
}

How to apply an external font for a complete Android app?

I want to change the font of my complete app!
But I don't know how to access the complete application.
I have a way to access a text by Id, how can I change the code to access the whole App?
public class ExternalFont extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String fontPath = "fonts/FreeUniversal-Regular.ttf";
TextView txtUniversal = (TextView) findViewById(R.id.universal);
Typeface tf = Typeface.createFromAsset(getAssets(), fontPath);
txtUniversal.setTypeface(tf);
}
}
To change all typeface for all TextView in app you should create custom style then add it into AppTheme style.
`<style name="customTextVeiw" parent="Widget.MaterialComponents.TextView">
<item name"fontFamilt">#font/custom_free_universal_regular</item>`
then add this style inside style.xml file inside AppTheme style.
`<style name="AppTheme" parent="AppBaseTheme">
<item name="android:textViewStyle">#style/customTextVeiw</item>`
Unfortunately there is no direct way in which you can change the typeface of all the TextViews you are using in your app by just changing the default typeface.
What you can do is create your own custom TextView and set typeface on it as suggested by #josedlujan. But the flaw in that approach is that each time a TextView object will be created, a new Typeface object will be created which is extremely bad for RAM usage (A Typeface object typically varies from 8-13 kb for typefaces like Roboto). So it is better to cache your Typeface once it has got loaded.
Step 1: Create a Typeface cache for your app -
public enum Font {
// path to your font asset
Y("fonts/Roboto-Regular.ttf");
public final String name;
private Typeface typeface;
Font(String s) {
name = s;
}
public Typeface getTypeface(Context context) {
if (typeface != null) return typeface;
try {
return typeface = Typeface.createFromAsset(context.getAssets(), name);
} catch (Exception e) {
return null;
}
}
public static Font fromName(String fontName) {
return Font.valueOf(fontName.toUpperCase());
}
Step 2: Define your own custom attribute "customFont" in attrs.xml for your CustomTextView
attrs.xml -
<declare-styleable name="CustomFontTextView">
<attr name="customFont"/>
</declare-styleable>
<com.packagename.CustomFontTextView
android:id="#+id/some_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:customFont="rl"/>
Step 3: Create your own custom TextView
public class CustomFontTextView extends TextView {
public CustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
public CustomFontTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CustomFontTextView(Context context) {
super(context);
init(context, null);
}
private void init(Context context, AttributeSet attrs) {
if (attrs == null) {
return;
}
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomFontTextView, 0 ,0);
String fontName = a.getString(R.styleable.CustomFontTextView_customFont);
String textStyle = attrs.getAttributeValue(styleScheme, styleAttribute);
if (fontName != null) {
Typeface typeface = Font.fromName(fontName).getTypeface(context);
if (textStyle != null) {
int style = Integer.decode(textStyle);
setTypeface(typeface, style);
} else {
setTypeface(typeface);
}
}
a.recycle();
}
To use Font for all app text you should use the Fonts in XML feature on devices running Android 4.1 (API level 16) and higher.
To add fonts as resources, perform the following steps in the Android Studio:
Right-click the res folder and go to New > Android resource directory.
The New Resource Directory window appears.
In the Resource type list, select font, and then click OK.
Add your font files in the font folder like this free_universal_regular.ttf
you should start your font with lower and under score instead of -.
Creating a font family
Right-click the font folder and go to New > Font resource file. The New Resource File window appears.
Enter the file name e.g: custom_free_universal_regular.xml , and then click OK. The new font resource XML opens in the editor.
add this in custom_free_universal_regular.xml file.
<?xml version="1.0" encoding="utf-8"?> <font-family xmlns:android="http://schemas.android.com/apk/res/android"> <font android:fontStyle="normal" android:fontWeight="400" android:font="#font/free_universal_regular" /> </font-family>
Now we can use this font family anywhere in our app like this
For e.g for all app use it inside the style.xml
<style name="BaseTheme" parent=""> <item name="fontFamily">#font/custom_free_universal_regular</item>
or in a specific element use it like this
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="#font/custom_free_universal_regular"/>
I hope that could help.
Create your own Textview with custom style.
Example:
public class YourTextView extends TextView {
public YourTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public YourTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public YourTextView(Context context) {
super(context);
init();
}
private void init() {
Typeface tf = Typeface.createFromAsset(context.getAssets(),
"fonts/yourfont.ttf");
setTypeface(tf);
}
}
You can use in yours XML.

Android preferences summary default color?

I have installed my app in a real phone, and even though in the emulator all the texts of the
preferences summaries seem to be in the same color, in the real phone the color is different (some kind of blue... but I guess it depends on the phone's model).
How can I set this color to my custom preference component?
(I have implemented my own seek bar, and its summary text color is different from all the other components text color...).
Thanks!
Preference pUpdate = findPreference("sys_setting_update");
pUpdate.setSummary(Html.fromHtml("<font color=\"#B0C4DE\">This is content</font>"));
use Html.fromHtml("<font color=\"#B0C4DE\">This is content</font>") to setSummary
I found these: android:textAppearance="?android:attr/textAppearanceLarge"
and android:textAppearance="?android:attr/textAppearanceSmall"
seem to do the trick.
I have figured out a way to retrieve the default color used by the Android device your application is running in. It is a bit tricky and requieres that you retrieve the color being shown from another Preference Summary View of your activity and store it in runtime.
Then you can use the same color code in other Views of other preferences, assuring that you will allways get the same color code Android assigned to the standard preferences. Here is how I did it:
My preferences activity has a normal CheckBoxPreference that I use to activate or deactivate a service. I have extended CheckBoxPreference as follows, so my extension retrieves in rutime the default color Android finally gave to the summary of that CheckBoxPreference:
public class MyCheckBoxPreference extends android.preference.CheckBoxPreference {
private static int sSummaryColor = Color.WHITE;
private static boolean sInitialized = false;
public MyCheckBoxPreference(Context context) {
super(context);
}
public MyCheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onBindView(View view) {
super.onBindView(view);
if (!sInitialized) {
sSummaryColor = getSummaryColor(view);
sInitialized = true;
}
}
private int getSummaryColor(View view) {
int color = Color.WHITE;
// Gets the color android gave to the summary by default
TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
if (summaryView != null) {
ColorStateList list = summaryView.getTextColors();
if (list != null) {
color = list.getDefaultColor();
}
}
return color;
}
public static int getSummaryColor() {
return sSummaryColor;
}
}
In my preferences.xml I instantiate that preference as MyCheckBoxPreference instead of just CheckBoxPreference:
<org.yourpackage.MyCheckBoxPreference
android:title="#string/preference_title_activate"
android:defaultValue="false"
android:summary="#string/preference_summary_activate_off"
android:summaryOff="#string/preference_summary_activate_off"
android:key="preference_activate">
</org.yourpackage.MyCheckBoxPreference>
The MyCheckBoxPreference has to be instantiated once before retrieving the summary color with MyCheckBoxPreference.getSummaryColor().
Now you can set the color of other customized preferences from onBindView(View):
public class MyCustmizedPreference extends Preference {
public MyCustmizedPreference (Context context) {
super(context);
setLayoutResource(R.layout.my_customized_preference);
}
#Override
public void onBindView(View view) {
super.onBindView(view);
TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
if (summaryView != null) {
summaryView.setTextColor(MyCheckBoxPreference.getSummaryColor());
}
}
}
It actually works under Samsung Galaxy S. I have also tested that it doesn't break anything under the emulator.
The Samsung Galaxy S phones have their own Preference layout with the text color specified for the Summary line. Even though a TextAppearance.Small is specified the textColor attribute of the layout is overriding the text appearance.
I don't think this is possible. I am able to change the background color and the title text color, but not the summary color.
Background:
getListView().setBackgroundColor(Color.TRANSPARENT);
Title text:
Preference yourpreference = findPreference("yourpreference");
TextView tv = (TextView)yourpreference.getView(null, getListView());
tv.setTextColor(...);
Sorry I couldn't help more...
I had the same problem and I've been experimenting with my custom seekbar-preference's style. Finally these lines in onCreateView method of seekBarPreference.java show preference's summary with default text color:
TextView summaryText = new TextView(getContext());
summaryText.setText(getSummary());
summaryText.setTextAppearance(getContext(), android.R.style.TextAppearance_Small);
I use it on preference_screen.xml:
<com.asdasf.SeekBarPreferencias
android:key="#string/pref_seekBar_distance_key"
android:id="#+id/mySeekBarPreference"
android:title="#string/pref_seekBar_distance_title"
android:summary="#string/pref_seekBar_distance_summary"
android:max="50"
android:defaultValue="12"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
I hope it will be useful...(and that I have written well my first answer)
Regard!

Categories

Resources