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).
Related
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
I'm trying to add CustomViewBeta (an extended RelativeLayout) to CustomViewAlpha (an extended LinearLayout) -- the idea being that the CustomViewAlpha will hold a bunch of CustomViewBetas a la a ListView. No matter what I try, it doesn't work. I either see nothing -- no CustomViewBetas, or it gives me an NPE when I try setText on one of the TextViews inside the CustomViewBeta
CustomViewAlpha works fine since it's hard-coded in the Fragment's XML:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
...>
<com.path.CustomViewAlpha
android:id="#+id/customviewalpha"
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
With the code being:
public class CustomViewAlpha extends LinearLayout {
private Context mContext;
public CustomViewAlpha (Context context) {
super(context);
this.mContext = context;
}
public CustomViewAlpha (Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}
public CustomViewAlpha (Context context, AttributeSet attrs, int defStyle){
super(context, attrs,defStyle);
this.mContext = context;
}
public void addCustomViewBeta(String someString){
CustomViewBeta customViewBeta = new CustomViewBeta(mContext);
addView(customViewBeta);
}
CustomViewBeta is not hard-coded in the Fragment's XML and get's added programmatically:
public class CustomViewBeta extends RelativeLayout{
private Context mContext;
private TextView textView;
public CustomViewBeta (Context context) {
super(context);
this.mContext = context;
init();
}
public CustomViewBeta (Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
init();
}
public CustomViewBeta (Context context, AttributeSet attrs, int defStyle){
super(context, attrs,defStyle);
this.mContext = context;
init();
}
private void init() {
LayoutInflater.from(mContext).inflate(R.layout.customviewbeta, null, false);
textView = (TextView) findViewById(R.id.tripleexpandablelistview_category_name);
textView.setText("ASDASDASDAD");
}
With this XML being:
<?xml version="1.0" encoding="utf-8"?>
<com.path.CustomViewBeta
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/customviewbeta_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</com.path.CustomViewBeta>
I usually get hit with a NPE on the "textView.setText("ASDASDASDAD");" line because the TextView is null. Is there something I'm missing? Should I not try to inflate an XML for the CustomViewBeta and just do it programmatically (adding the textviews one by one programmatically?)? Thanks.
your init is wrong
private void init() {
LayoutInflater.from(mContext).inflate(R.layout.customviewbeta, null, false);
textView = (TextView) findViewById(R.id.tripleexpandablelistview_category_name);
textView.setText("ASDASDASDAD");
}
the last parameter has to be true to add the TextViewto the RelativeLayout.Also ViewGroup, has a static inflate method, so you can avoid LayoutInflater.from(mContext), you can just call inflate(mContext, R.layout.customviewbeta, this);
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
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 extended a RelativeLayout with all its constructor.And I have created a layout in xml that I am inflating in one of constructor of my class.
My Code for MyClass
public class MyClass extends RelativeLayout
{
LayoutInflater inflater = null;
EditText edit_text;
Button btn_clear;
public MyClass(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public MyClass(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.my_class_layout, this, true);
edit_text = (EditText) findViewById(R.id.clearable_edit);
btn_clear = (Button) findViewById(R.id.clearable_button_clear);
btn_clear.setVisibility(RelativeLayout.INVISIBLE);
}
public MyClass(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
}
My class layout which I inflate
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/clearable_edit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="#+id/clearable_button_clear"
android:layout_width="30dip"
android:layout_height="30dip"
android:layout_alignParentRight="true"
android:background="#drawable/image_clear"
android:layout_centerVertical="true"
android:layout_marginRight="5dip"/>
</RelativeLayout>
And I use MyClass in my activity's layout like this
<com.and.MyClass
android:id="#+id/my_class"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
This works fine.
but when I inflate my class layout in constructor MyClass(Context context) then it doesn't work.
I am not getting what is the problem. I hope you got my question.
This is OK.
When we use a View in xml
public MyClass(Context context, AttributeSet attrs)
this constructor will be called.
Because all the attributes from XML are passed to this constructor using AttributeSet, so that these values will have effect on View's layout and other fields.
However if you want to use your View in Java also, you should also inflate in all View's constructor (Which is recommended approach).
Please change your code like this
public class MyClass extends RelativeLayout
{
LayoutInflater inflater = null;
EditText edit_text;
Button btn_clear;
public MyClass(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
public MyClass(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
public MyClass(Context context)
{
super(context);
// TODO Auto-generated constructor stub
init();
}
public void init() {
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.my_class_layout, this, true);
edit_text = (EditText) findViewById(R.id.clearable_edit);
btn_clear = (Button) findViewById(R.id.clearable_button_clear);
btn_clear.setVisibility(RelativeLayout.INVISIBLE);
}
}