I have created folder named fonts in my asset folder and put a .ttf file in it. And Assigning that fontfamily to my text like this
txtName.setTypeface(Typeface.createFromAsset(context.getAssets(),"fonts/segoeui.ttf"));
But I want to assign this font in xml file. May be something like this.
<TextView
android:id="#+id/txtName"
style="#style/My_Name"
android:fontFamily="#android:asset/fonts/segoeui"
/>
To include ttf file in your app is lead to increase your app size.
Downloadable Font is best solution to use other fonts.
Use following references:
document:
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts.html
sample:
https://github.com/googlesamples/android-DownloadableFonts
and still you want to include fontFile then use following answer:
https://stackoverflow.com/a/27588966/8240915
You can create a custom FontTextView :
-Add this custom FontTextView in src package:
package com.example.android.ui;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
import java.util.HashMap;
import java.util.Map;
public class FontTextView extends TextView {
private static Map<String, Typeface> mTypefaces;
public FontTextView(final Context context) {
this(context, null);
}
public FontTextView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public FontTextView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
if (mTypefaces == null) {
mTypefaces = new HashMap<String, Typeface>();
}
final TypedArray array = context.obtainStyledAttributes(attrs, styleable.FontTextView);
if (array != null) {
final String typefaceAssetPath = array.getString(
R.styleable.FontTextView_customTypeface);
if (typefaceAssetPath != null) {
Typeface typeface = null;
if (mTypefaces.containsKey(typefaceAssetPath)) {
typeface = mTypefaces.get(typefaceAssetPath);
} else {
AssetManager assets = context.getAssets();
typeface = Typeface.createFromAsset(assets, typefaceAssetPath);
mTypefaces.put(typefaceAssetPath, typeface);
}
setTypeface(typeface);
}
array.recycle();
}
}
}
-In res/values add the tt_attrs.xml
<resources>
<declare-styleable name="FontTextView">
<attr name="customTypeface" format="string" />
</declare-styleable>
</resources>
-In your layout which you want add font textview:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:geekui="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.android.ui.FontTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textSize="30sp"
geekui:customTypeface="fonts/segoeui.ttf" />
<com.entreprise.android.ui.FontTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="#string/app_name"
geekui:customTypeface="fonts/Times New Roman.ttf" />
<com.entreprise.android.ui.FontTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="#string/app_name"
geekui:customTypeface="fonts/arial unicode ms.ttf" />
</LinearLayout>
all this source code is inspired from https://github.com/ragunathjawahar/android-typeface-textview
Simply use this code. just simply add segoeui.ttf with the file name.
android:fontFamily="fonts/segoeui.ttf"
You can follow this.
In your Application class:
Typeface fontHelvetica = Typeface.createFromAsset(this.getResources().getAssets(), "font/helvetica_font.ttf");
injectTypeface("helvetica", fontHelvetica);
private boolean injectTypeface(String fontFamily, Typeface typeface) {
try {
Field field = Typeface.class.getDeclaredField("sSystemFontMap");
field.setAccessible(true);
Object fieldValue = field.get(null);
Map<String, Typeface> map = (Map<String, Typeface>) fieldValue;
map.put(fontFamily, typeface);
return true;
} catch (Exception e) {
Log.e("Font-Injection", "Failed to inject typeface.", e);
}
return false;
}
After that you can use in XML as per mentioned in your Question.
You can do that by making CustomTextView that extends TextView like this as shown below
public class MyTextView extends TextView {
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyTextView(Context context) {
super(context);
init();
}
private void init() {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"your_font.ttf");
setTypeface(tf);
}
}
But remember, there is serious memory concers in older android version. Refer this issue
https://code.google.com/p/android/issues/detail?id=9904
Related
I have a ttf font file in my assets folder. I know how to use it for textviews with:
Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
textview1.setTypeface(externalFont);
I have defined look for my spinner text in it's own xml file (as usuall in android):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:textColor="#ffffff"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee" />
I just can't reference this textview from code, i always get null pointer exceptions. E.g. i tried:
TextView spinner_text=(TextView)findViewById(R.id.text1);
spinner_text.setTypeface(externalFont);
Is it possible to select my external font even for my spinner text defined in it's own xml?
Thank you.
EDIT with answer:
This works:
String [] items = new String[2];
items[0]="Something1";
items[1]="Something2";
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.spinaca, items) {
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
((TextView) v).setTypeface(externalFont);
return v;
}
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View v =super.getDropDownView(position, convertView, parent);
Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
((TextView) v).setTypeface(externalFont);
v.setBackgroundColor(Color.GREEN);
return v;
}
};
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
It may be necessary to add
import android.view.ViewGroup;
To your list of imports at the top of your file. For some reason Eclipse doesn't make this suggestion when it doesn't recognize the ViewGroup class involved in the code.
This is what worked for me (using ideas both from CommonsWare's and gsanllorente's answers):
private static class MySpinnerAdapter extends ArrayAdapter<String> {
// Initialise custom font, for example:
Typeface font = Typeface.createFromAsset(getContext().getAssets(),
"fonts/Blambot.otf");
// (In reality I used a manager which caches the Typeface objects)
// Typeface font = FontManager.getInstance().getFont(getContext(), BLAMBOT);
private MySpinnerAdapter(Context context, int resource, List<String> items) {
super(context, resource, items);
}
// Affects default (closed) state of the spinner
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getView(position, convertView, parent);
view.setTypeface(font);
return view;
}
// Affects opened state of the spinner
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getDropDownView(position, convertView, parent);
view.setTypeface(font);
return view;
}
}
If you, like me, originally populated the Spinner using ArrayAdapter.createFromResource() and an array resource (as in Spinner documentation), then you'd use MySpinnerAdapter like this:
MySpinnerAdapter<String> adapter = new MySpinnerAdapter(
getContext(),
R.layout.view_spinner_item,
Arrays.asList(getResources().getStringArray(R.array.my_array))
);
spinner.setAdapter(adapter);
You would apply the font through your own custom SpinnerAdapter, in getView() and getDropDownView().
If you implement your Adapter in another file, you can access the "getAssets()" function from the constructor of the Adapter, as you have the Context as a parameter.
public class YourItemAdapter extends ArrayAdapter<String> {
int recurso;
Typeface tf;
public YourItemAdapter(Context _context, int _resource,
List<String> _items) {
super(_context, _resource, _items);
recurso=_resource;
tf=Typeface.createFromAsset(_context.getAssets(),"font/digital-7.ttf");
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//You can use the new tf here.
TextView spinner_text=(TextView)findViewById(R.id.text1);
spinner_text.setTypeface(tf);
}
}
Try this create custom custom_spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<com.xxxx.xxxx.CheckedTextViewC
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textAlignment="center"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:textSize="18sp"
/>
Create custom CheckedtextView like this
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.CheckedTextView;
public class CheckedTextViewC extends CheckedTextView {
public CheckedTextViewC(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public CheckedTextViewC(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public CheckedTextViewC(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public void setTypeface(Typeface tf, int style) {
if(!this.isInEditMode()){
Typeface normalTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");
Typeface boldTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");
if (style == Typeface.BOLD) {
super.setTypeface(boldTypeface/*, -1*/);
} else {
super.setTypeface(normalTypeface/*, -1*/);
}
}
}
}
implemente the new layout
adapter= new ArrayAdapter <String>(Menu.this,R.layout.custom_spinner, list);
This is the continuation of my previous answer: https://stackoverflow.com/a/51100507/787399
For the compatibility reasons, you can use the styles and customized
classes against the widgets in Android. Although above Android level
15, new /res/font resource folders were introduced:
Font Resources in Android
Step 1: declare item_spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<com.my_package.custom_views.FontTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tv_spinner"
style="#style/App_TextViewStyleSmall"
android:layout_gravity="start|bottom"
android:layout_marginLeft="#dimen/dp_5"
android:layout_marginStart="#dimen/dp_5"
android:ellipsize="marquee"
android:gravity="start|bottom"
android:padding="#dimen/dp_10"
android:singleLine="true"
android:textAlignment="inherit" />
<!--declared in layout: item_spinner.xml-->
<!-- removed attributes: android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/text_grey_light"
android:textSize="#dimen/sp_14" -->
<!--style="?android:attr/spinnerItemStyle"-->
step 2: declare item_spinner_dropdown.xml:
<?xml version="1.0" encoding="utf-8"?>
<com.my_package.custom_views.FontTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tv_spinner"
style="#style/App_TextViewStyleSmall"
android:layout_gravity="start|bottom"
android:layout_marginLeft="#dimen/dp_5"
android:layout_marginStart="#dimen/dp_5"
android:ellipsize="marquee"
android:gravity="start|bottom"
android:padding="#dimen/dp_10"
android:singleLine="true" />
<!--declared in layout: item_spinner_dropdown.xml -->
<!--removed: ?android:attr/dropdownListPreferredItemHeight-->
<!--style="?android:attr/spinnerDropDownItemStyle"-->
Step 3: Use spinner in layout:
<LinearLayout
android:id="#+id/ll_my_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/fet_bus_entity"
android:layout_marginTop="#dimen/dp_12"
android:orientation="horizontal">
<com.my_package.custom_views.FontTextView
style="#style/App_TextViewStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:gravity="start|bottom"
android:text="#string/are_you_a" />
<Spinner
android:id="#+id/sp_my_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/dp_5"
android:layout_marginStart="#dimen/dp_5"
android:layout_gravity="end|bottom"
android:spinnerMode="dropdown" />
</LinearLayout>
[Note: id of the FontTextView is same in both the layouts, spinner item and drop down item]
Step 4: use it in the Activity/Fragment:
private void initSpinnerBusinessType(View rootView) {
String[] ar_dd_bus_type = getResources().getStringArray(R.array.ar_dd_bus_type);
List<String> lst_bus_type = Arrays.asList(ar_dd_bus_type);
ArrayList<String> ar_bus_type = new ArrayList<>(lst_bus_type);
//==
ArrayAdapter<String> adapter = new ArrayAdapter<>(activity, R.layout.item_spinner, R.id.tv_spinner, ar_bus_type);
adapter.setDropDownViewResource(R.layout
.item_spinner_dropdown);
//=========
Spinner sp_my_spinner= rootView.findViewById(R.id.sp_my_spinner);
sp_my_spinner.setAdapter(adapter);
}
[ for further guidance see my other post: https://stackoverflow.com/a/51077569/787399 and https://stackoverflow.com/a/22164007/787399 ]
Please follow basic customization of FontTextView, FontEditView, FontRadioButton, FontCheckBox and FontButton.
[ For the exact answer, after seeing this guide, please see:
https://stackoverflow.com/a/51113022/787399 ]
Use custom FontTextView, in ArrayAdapter item layout, like this:
public class FontEditText extends AppCompatEditText {
// private String FONT = "fonts/roboto_regular.ttf";
public FontEditText(Context context) {
super(context, null);
// setFontFromAsset(context, null, R.style.DefaultFontTextView);
// FONT = getContext().getString(R.string.font_roboto_regular);
}
public FontEditText(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
setFontFromAsset(context, attrs, R.attr.fetFontStyle);
}
public FontEditText(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setFontFromAsset(context, attrs, defStyleAttr);
}
private void setFontFromAsset(Context context, AttributeSet attrs, int defStyle) {
BaseActivity activity = (BaseActivity)((MyApplication) context.getApplicationContext()).getCurrentActivity();
FontAndLocaleManager fontAndLocaleManager = activity.getFontAndLocaleManager();
fontAndLocaleManager.setFontFromAsset(this, R.styleable.FontEditText, R.styleable.FontEditText_fetFontFace, attrs, defStyle);
}
}
use the code:
public void setFontFromAsset(View view, int[] resViewStyleable, int resStyleableViewFontFace, AttributeSet attrs, int defStyle) {
String strFont = null;
Typeface tfFontFace = null;
String strButton = FontButton.class.getCanonicalName(),
strTextView = FontTextView.class.getCanonicalName(),
strEditText = FontEditText.class.getCanonicalName(),
strView = view.getClass().getCanonicalName();
try {
if (view.isInEditMode()) {
return;
}
//R.string.font_roboto_regular
strFont = context.getString(R.string.font_roboto_regular);
tfFontFace = Typeface.createFromAsset(context.getAssets(), strFont);
//AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes
//R.styleable.FontButton
TypedArray a = context.obtainStyledAttributes(attrs, resViewStyleable, defStyle, 0);
//R.styleable.FontButton_btFontFace
String derivedFont = a.getString(resStyleableViewFontFace);
a.recycle();
//==
try {
if (derivedFont != null) {
Typeface derivedFontFace = Typeface.createFromAsset(context.getAssets(), derivedFont);
if (strView.equals(strButton)) {
((FontButton) view).setTypeface(derivedFontFace);
} else if (strView.equals(strTextView)) {
((FontTextView) view).setTypeface(derivedFontFace);
} else if (strView.equals(strEditText)) {
((FontEditText) view).setTypeface(derivedFontFace);
}
return;
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (strFont != null && tfFontFace != null) {
if (strView.equals(strButton)) {
((FontButton) view).setTypeface(tfFontFace);
} else if (strView.equals(strTextView)) {
((FontTextView) view).setTypeface(tfFontFace);
} else if (strView.equals(strEditText)) {
((FontEditText) view).setTypeface(tfFontFace);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Describe style and attributes in respective xmls:
<!--FontTextView-->
<declare-styleable name="FontTextViewStyle">
<!-- Style of the FontTextView. -->
<attr name="ftvFontStyle" format="reference"/>
</declare-styleable>
<declare-styleable name="FontTextView">
<!-- Font face of FontTextView. -->
<attr name="ftvFontFace" format="reference"/>
</declare-styleable>
and
<!--FontTextView-->
<style name="StyledFontTextView" parent="#android:style/Theme.Light">
<item name="ftvFontStyle">#style/DefaultFontTextView</item>
</style>
<style name="DefaultFontTextView">
<item name="ftvFontFace">#string/font_roboto_regular</item>
</style>
define some more styles:
<style name="App_TextViewStyle" parent="#android:style/Widget.TextView">
<item name="android:textColor">#color/text_grey</item>
<item name="android:textSize">#dimen/sp_20</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="App_TextViewStyleMedium" parent="#android:style/Widget.TextView">
<item name="android:textColor">#color/text_hint</item>
<item name="android:textSize">#dimen/sp_18</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="App_TextViewStyleSmall" parent="#android:style/Widget.TextView">
<item name="android:textColor">#color/text_grey_light</item>
<item name="android:textSize">#dimen/sp_14</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
mention fonts in your strings.xml:
...
<string name="font_roboto_regular">fonts/roboto_regular.ttf</string>
...
and use in the layouts saving some code and time:
<com.mypackage.custom_views.FontTextView
style="#style/App_TextViewStyleMedium"
android:layout_gravity="start|bottom"
android:gravity="start|bottom"
app:fetFontFace="#string/font_roboto_regular"
android:text="#string/are_you_a" />
At Android level 16 and above, all this is simplified, because now you can keep TTF and other font resources in /res/font folder, rather than in assets. That removes most of the custom classes, styles and attributes, see:
Font Resources in Android
Happy Coding with style!! :-)
Guys I found an awesome solution, I wrap orignal adapter by helper like
Use this class SpinnerViewHelper and happy progamming with Android
new SpinnerViewHelper((Spinner)view.findViewById(R.id.labelSurveyNumber),(parent, v, position, id) -> UrduFontHelper.set(v));
Lambda expression is used.
I'm trying to use font-awesome icons and having some problem. It worked from MainActivity but when I use from Fragment its not showing up the icons.
This is my HomeFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View home = inflater.inflate(R.layout.fragment_home, container, false);
View feed_row = inflater.inflate(R.layout.feed_row, container, false);
like_button = (Button) feed_row.findViewById(R.id.like_button);
Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "fonts/fontawesome-webfont.ttf");
like_button.setTypeface(tf);
mHomeFeed = (RecyclerView) home.findViewById(R.id.home_feed);
mLayoutManager = new LinearLayoutManager(this.getActivity());
mHomeFeed.setHasFixedSize(true);
mHomeFeed.setLayoutManager(mLayoutManager);
This is feed_row.xml:
<Button
android:id="#+id/like_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/icon_heart"
android:background="#color/noBackground"/>
Strings.xml
<string name="icon_heart"></string>
<string name="icon_comment"></string>
What should I do now? It had no error but icons looked like below:
Instead using:
Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),
"fonts/fontawesome-webfont.ttf");
which has memory issues because constantly creating a new typeface for each icon (as in the answer comment), you can use Calligraphy. Where after you have configured your app with the library, you only need to add fontPath attribute:
So you have a more and flexible code, where the font is only in the XML:
<Button
android:id="#+id/like_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/icon_heart"
android:background="#color/noBackground"
fontPath="fonts/fontawesome-webfont.ttf"/>
You can do this by making a class and extends it from Button class like this
public class AwesomeFontButton extends Button {
public AvenirBookEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public AvenirBookEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public AvenirBookEditText(Context context) {
super(context);
init();
}
private void init() {
if (!isInEditMode()) {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"fontawesome-webfont.ttf"); //add your font path here
setTypeface(tf);
}
}
}
and use it in xml like this:
<YourFilePath.AwesomeFontButton
android:id="#+id/like_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/icon_heart"
android:background="#color/noBackground"/>
use it in xml wherever you need
How can i use the custom font which we add in asset folder in xml?
I want to create custom font for app..
but I run the programme ,it has exception.
this is my java code:
public class MainActivity extends TextView {
private static final String TAG = "TextView";
public MainActivity(Context context) {
super(context);
}
public MainActivity(Context context, AttributeSet attrs) {
super(context, attrs);
setCustomFont(context, attrs);
}
public MainActivity(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setCustomFont(context, attrs);
}
private void setCustomFont(Context ctx, AttributeSet attrs) {
TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.textfont);
String customFont = a.getString(R.styleable.TextViewPlus_customFont);
setCustomFont(ctx, customFont);
a.recycle();
}
public boolean setCustomFont(Context ctx, String asset) {
Typeface tf = null;
try {
tf = Typeface.createFromAsset(ctx.getAssets(), asset);
} catch (Exception e) {
Log.e(TAG, "Could not get typeface: "+e.getMessage());
return false;
}
setTypeface(tf);
return true;
}
}
and create a folder in res/values/attrs
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="textfont">
<attr name="customFont" format="string"/>
</declare-styleable>
</resources>
and xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:foo="http://schemas.android.com/apk/res/com.example.changfont"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.example.changfont.MainActivity
android:id="#+id/textViewPlus1"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:text="helooo"
foo:customFont="aaa.ttf">
</com.example.changfont.MainActivity>
logcat is:
09-09 20:44:28.063: E/AndroidRuntime(11515): FATAL EXCEPTION: main
09-09 20:44:28.063: E/AndroidRuntime(11515): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.changfont/com.example.changfont.MainActivity}: java.lang.InstantiationException: can't instantiate class com.example.changfont.MainActivity; no empty constructor
09-09 20:44:28.063: E/AndroidRuntime(11515): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1891)
I do not know what the problem is ?
please help me.
Your MainActivity is not an Activity but a TextView. It cannot be instantiated as an activity and should not be declared in the manifest.
Looks like you need to:
Rename this MainActivity to something like `MyCustomTextView``
Implement MainActivity as an activity that calls setContentView() with a layout that contains an instance of your MyCustomTextView, such as the XML you posted (with MainActivity renamed).
package com.binod.customviewtest;
import android.content.Context;
import android.view.LayoutInflater;
import android.widget.RelativeLayout;
public class CustomView extends RelativeLayout{
public CustomView(Context context) {
super(context);
// TODO Auto-generated constructor stub
// LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater mInflater = LayoutInflater.from(context);
mInflater.inflate(R.layout.custom_view , this, true);
}
}
Including as
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.binod.customviewtest.CustomView
android:layout_width="match_parent"
android:layout_height="wrap_content"
></com.binod.customviewtest.CustomView>
</RelativeLayout>
Custom View as
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</RelativeLayout>
Just started adding a new custom view and got the error once If I clear this then can move forward
I am getting crash "Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class"
You need to have 2 more constructors. To know why
Do I need all three constructors for an Android custom view?
public class CustomView extends RelativeLayout{
LayoutInflater mInflater;
public CustomView(Context context) {
super(context);
mInflater = LayoutInflater.from(context);
init();
}
public CustomView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mInflater = LayoutInflater.from(context);
init();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
mInflater = LayoutInflater.from(context);
init();
}
public void init()
{
View v = mInflater.inflate(R.layout.custom_view, this, true);
TextView tv = (TextView) v.findViewById(R.id.textView1);
tv.setText(" Custom RelativeLayout");
}
}
I am posting an example. My packagename is different
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.example.testall.CustomView
android:id="#+id/timer1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
custom_view.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:text="My Custom View" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Snap
As pskink suggested there in a RelativeLayout in activity_main.xml with a child CustomView. Then CustomView extends RealtiveLayout and then again you inflate a customview with RelativeLayout and a child TextView. No need for all these. Just a CustomView. Have a TextView created programatically and then add textview to RelativeLayout
Edit:
activity_main.xml
<com.example.testall.CustomView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/timer1"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
CustomView
public class CustomView extends RelativeLayout{
TextView tv;
public CustomView(Context context) {
super(context);
tv = new TextView(context);
init();
}
public CustomView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
tv = new TextView(context);
init();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
tv = new TextView(context);
init();
}
public void init()
{
this.addView(tv);
tv.setText(" Custom RelativeLayout");
}
}
Try to get Activity and use this
{
LayoutInflater inflter = activity.getLayoutInflater();
View v = inflter.inflate(R.layout.custom_view,null);
this.addView(v); or addView(v);
}
I have a ttf font file in my assets folder. I know how to use it for textviews with:
Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
textview1.setTypeface(externalFont);
I have defined look for my spinner text in it's own xml file (as usuall in android):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:textColor="#ffffff"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee" />
I just can't reference this textview from code, i always get null pointer exceptions. E.g. i tried:
TextView spinner_text=(TextView)findViewById(R.id.text1);
spinner_text.setTypeface(externalFont);
Is it possible to select my external font even for my spinner text defined in it's own xml?
Thank you.
EDIT with answer:
This works:
String [] items = new String[2];
items[0]="Something1";
items[1]="Something2";
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.spinaca, items) {
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
((TextView) v).setTypeface(externalFont);
return v;
}
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View v =super.getDropDownView(position, convertView, parent);
Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
((TextView) v).setTypeface(externalFont);
v.setBackgroundColor(Color.GREEN);
return v;
}
};
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
It may be necessary to add
import android.view.ViewGroup;
To your list of imports at the top of your file. For some reason Eclipse doesn't make this suggestion when it doesn't recognize the ViewGroup class involved in the code.
This is what worked for me (using ideas both from CommonsWare's and gsanllorente's answers):
private static class MySpinnerAdapter extends ArrayAdapter<String> {
// Initialise custom font, for example:
Typeface font = Typeface.createFromAsset(getContext().getAssets(),
"fonts/Blambot.otf");
// (In reality I used a manager which caches the Typeface objects)
// Typeface font = FontManager.getInstance().getFont(getContext(), BLAMBOT);
private MySpinnerAdapter(Context context, int resource, List<String> items) {
super(context, resource, items);
}
// Affects default (closed) state of the spinner
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getView(position, convertView, parent);
view.setTypeface(font);
return view;
}
// Affects opened state of the spinner
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getDropDownView(position, convertView, parent);
view.setTypeface(font);
return view;
}
}
If you, like me, originally populated the Spinner using ArrayAdapter.createFromResource() and an array resource (as in Spinner documentation), then you'd use MySpinnerAdapter like this:
MySpinnerAdapter<String> adapter = new MySpinnerAdapter(
getContext(),
R.layout.view_spinner_item,
Arrays.asList(getResources().getStringArray(R.array.my_array))
);
spinner.setAdapter(adapter);
You would apply the font through your own custom SpinnerAdapter, in getView() and getDropDownView().
If you implement your Adapter in another file, you can access the "getAssets()" function from the constructor of the Adapter, as you have the Context as a parameter.
public class YourItemAdapter extends ArrayAdapter<String> {
int recurso;
Typeface tf;
public YourItemAdapter(Context _context, int _resource,
List<String> _items) {
super(_context, _resource, _items);
recurso=_resource;
tf=Typeface.createFromAsset(_context.getAssets(),"font/digital-7.ttf");
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//You can use the new tf here.
TextView spinner_text=(TextView)findViewById(R.id.text1);
spinner_text.setTypeface(tf);
}
}
Try this create custom custom_spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<com.xxxx.xxxx.CheckedTextViewC
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textAlignment="center"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:textSize="18sp"
/>
Create custom CheckedtextView like this
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.CheckedTextView;
public class CheckedTextViewC extends CheckedTextView {
public CheckedTextViewC(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public CheckedTextViewC(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public CheckedTextViewC(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public void setTypeface(Typeface tf, int style) {
if(!this.isInEditMode()){
Typeface normalTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");
Typeface boldTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");
if (style == Typeface.BOLD) {
super.setTypeface(boldTypeface/*, -1*/);
} else {
super.setTypeface(normalTypeface/*, -1*/);
}
}
}
}
implemente the new layout
adapter= new ArrayAdapter <String>(Menu.this,R.layout.custom_spinner, list);
This is the continuation of my previous answer: https://stackoverflow.com/a/51100507/787399
For the compatibility reasons, you can use the styles and customized
classes against the widgets in Android. Although above Android level
15, new /res/font resource folders were introduced:
Font Resources in Android
Step 1: declare item_spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<com.my_package.custom_views.FontTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tv_spinner"
style="#style/App_TextViewStyleSmall"
android:layout_gravity="start|bottom"
android:layout_marginLeft="#dimen/dp_5"
android:layout_marginStart="#dimen/dp_5"
android:ellipsize="marquee"
android:gravity="start|bottom"
android:padding="#dimen/dp_10"
android:singleLine="true"
android:textAlignment="inherit" />
<!--declared in layout: item_spinner.xml-->
<!-- removed attributes: android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/text_grey_light"
android:textSize="#dimen/sp_14" -->
<!--style="?android:attr/spinnerItemStyle"-->
step 2: declare item_spinner_dropdown.xml:
<?xml version="1.0" encoding="utf-8"?>
<com.my_package.custom_views.FontTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tv_spinner"
style="#style/App_TextViewStyleSmall"
android:layout_gravity="start|bottom"
android:layout_marginLeft="#dimen/dp_5"
android:layout_marginStart="#dimen/dp_5"
android:ellipsize="marquee"
android:gravity="start|bottom"
android:padding="#dimen/dp_10"
android:singleLine="true" />
<!--declared in layout: item_spinner_dropdown.xml -->
<!--removed: ?android:attr/dropdownListPreferredItemHeight-->
<!--style="?android:attr/spinnerDropDownItemStyle"-->
Step 3: Use spinner in layout:
<LinearLayout
android:id="#+id/ll_my_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/fet_bus_entity"
android:layout_marginTop="#dimen/dp_12"
android:orientation="horizontal">
<com.my_package.custom_views.FontTextView
style="#style/App_TextViewStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:gravity="start|bottom"
android:text="#string/are_you_a" />
<Spinner
android:id="#+id/sp_my_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/dp_5"
android:layout_marginStart="#dimen/dp_5"
android:layout_gravity="end|bottom"
android:spinnerMode="dropdown" />
</LinearLayout>
[Note: id of the FontTextView is same in both the layouts, spinner item and drop down item]
Step 4: use it in the Activity/Fragment:
private void initSpinnerBusinessType(View rootView) {
String[] ar_dd_bus_type = getResources().getStringArray(R.array.ar_dd_bus_type);
List<String> lst_bus_type = Arrays.asList(ar_dd_bus_type);
ArrayList<String> ar_bus_type = new ArrayList<>(lst_bus_type);
//==
ArrayAdapter<String> adapter = new ArrayAdapter<>(activity, R.layout.item_spinner, R.id.tv_spinner, ar_bus_type);
adapter.setDropDownViewResource(R.layout
.item_spinner_dropdown);
//=========
Spinner sp_my_spinner= rootView.findViewById(R.id.sp_my_spinner);
sp_my_spinner.setAdapter(adapter);
}
[ for further guidance see my other post: https://stackoverflow.com/a/51077569/787399 and https://stackoverflow.com/a/22164007/787399 ]
Please follow basic customization of FontTextView, FontEditView, FontRadioButton, FontCheckBox and FontButton.
[ For the exact answer, after seeing this guide, please see:
https://stackoverflow.com/a/51113022/787399 ]
Use custom FontTextView, in ArrayAdapter item layout, like this:
public class FontEditText extends AppCompatEditText {
// private String FONT = "fonts/roboto_regular.ttf";
public FontEditText(Context context) {
super(context, null);
// setFontFromAsset(context, null, R.style.DefaultFontTextView);
// FONT = getContext().getString(R.string.font_roboto_regular);
}
public FontEditText(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
setFontFromAsset(context, attrs, R.attr.fetFontStyle);
}
public FontEditText(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setFontFromAsset(context, attrs, defStyleAttr);
}
private void setFontFromAsset(Context context, AttributeSet attrs, int defStyle) {
BaseActivity activity = (BaseActivity)((MyApplication) context.getApplicationContext()).getCurrentActivity();
FontAndLocaleManager fontAndLocaleManager = activity.getFontAndLocaleManager();
fontAndLocaleManager.setFontFromAsset(this, R.styleable.FontEditText, R.styleable.FontEditText_fetFontFace, attrs, defStyle);
}
}
use the code:
public void setFontFromAsset(View view, int[] resViewStyleable, int resStyleableViewFontFace, AttributeSet attrs, int defStyle) {
String strFont = null;
Typeface tfFontFace = null;
String strButton = FontButton.class.getCanonicalName(),
strTextView = FontTextView.class.getCanonicalName(),
strEditText = FontEditText.class.getCanonicalName(),
strView = view.getClass().getCanonicalName();
try {
if (view.isInEditMode()) {
return;
}
//R.string.font_roboto_regular
strFont = context.getString(R.string.font_roboto_regular);
tfFontFace = Typeface.createFromAsset(context.getAssets(), strFont);
//AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes
//R.styleable.FontButton
TypedArray a = context.obtainStyledAttributes(attrs, resViewStyleable, defStyle, 0);
//R.styleable.FontButton_btFontFace
String derivedFont = a.getString(resStyleableViewFontFace);
a.recycle();
//==
try {
if (derivedFont != null) {
Typeface derivedFontFace = Typeface.createFromAsset(context.getAssets(), derivedFont);
if (strView.equals(strButton)) {
((FontButton) view).setTypeface(derivedFontFace);
} else if (strView.equals(strTextView)) {
((FontTextView) view).setTypeface(derivedFontFace);
} else if (strView.equals(strEditText)) {
((FontEditText) view).setTypeface(derivedFontFace);
}
return;
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (strFont != null && tfFontFace != null) {
if (strView.equals(strButton)) {
((FontButton) view).setTypeface(tfFontFace);
} else if (strView.equals(strTextView)) {
((FontTextView) view).setTypeface(tfFontFace);
} else if (strView.equals(strEditText)) {
((FontEditText) view).setTypeface(tfFontFace);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Describe style and attributes in respective xmls:
<!--FontTextView-->
<declare-styleable name="FontTextViewStyle">
<!-- Style of the FontTextView. -->
<attr name="ftvFontStyle" format="reference"/>
</declare-styleable>
<declare-styleable name="FontTextView">
<!-- Font face of FontTextView. -->
<attr name="ftvFontFace" format="reference"/>
</declare-styleable>
and
<!--FontTextView-->
<style name="StyledFontTextView" parent="#android:style/Theme.Light">
<item name="ftvFontStyle">#style/DefaultFontTextView</item>
</style>
<style name="DefaultFontTextView">
<item name="ftvFontFace">#string/font_roboto_regular</item>
</style>
define some more styles:
<style name="App_TextViewStyle" parent="#android:style/Widget.TextView">
<item name="android:textColor">#color/text_grey</item>
<item name="android:textSize">#dimen/sp_20</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="App_TextViewStyleMedium" parent="#android:style/Widget.TextView">
<item name="android:textColor">#color/text_hint</item>
<item name="android:textSize">#dimen/sp_18</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="App_TextViewStyleSmall" parent="#android:style/Widget.TextView">
<item name="android:textColor">#color/text_grey_light</item>
<item name="android:textSize">#dimen/sp_14</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
mention fonts in your strings.xml:
...
<string name="font_roboto_regular">fonts/roboto_regular.ttf</string>
...
and use in the layouts saving some code and time:
<com.mypackage.custom_views.FontTextView
style="#style/App_TextViewStyleMedium"
android:layout_gravity="start|bottom"
android:gravity="start|bottom"
app:fetFontFace="#string/font_roboto_regular"
android:text="#string/are_you_a" />
At Android level 16 and above, all this is simplified, because now you can keep TTF and other font resources in /res/font folder, rather than in assets. That removes most of the custom classes, styles and attributes, see:
Font Resources in Android
Happy Coding with style!! :-)
Guys I found an awesome solution, I wrap orignal adapter by helper like
Use this class SpinnerViewHelper and happy progamming with Android
new SpinnerViewHelper((Spinner)view.findViewById(R.id.labelSurveyNumber),(parent, v, position, id) -> UrduFontHelper.set(v));
Lambda expression is used.