Error: android.view.inflateExeption in CustomTextView - android

I have a menu activity that gets user setting of font and size and line spacing of text in all of TextView's, so i need a CustomTextView class to set these changes but my custom TextView does't work and give inflate Exception in logcat window. tank's a lot for your helps!
my CustomTextView:
package com.niloo.test2;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
public class CustomTextView extends TextView {
Context context;
SharedPreferences shp = context.getSharedPreferences("text", Context.MODE_PRIVATE);
int size = shp.getInt("size", 22);
int fasle = shp.getInt("fasle", 1);
String font = shp.getString("font", "bmitra");
public CustomTextView(Context context) {
super(context);
if (!isInEditMode())
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/"+font));
setTextSize(size);
setLineSpacing(fasle, 1);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if (! isInEditMode())
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/"+font));
setTextSize(size);
setLineSpacing(fasle, 1);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (!isInEditMode())
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/"+font));
setTextSize(size);
setLineSpacing(fasle, 1);
}
protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
}
}
my XML code:
<com.niloo.test2.CustomTextView
android:id="#+id/tv_onv_amoozsh"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_marginTop="10dp"
android:layout_weight="0.5"
android:textColor="#color/sabz_lajani"
android:textSize="25sp"
android:textStyle="bold" />
<com.niloo.test2.CustomTextView
android:id="#+id/tv_num_amoozsh"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_marginBottom="2dp"
android:layout_weight="0.75"
android:textColor="#color/sabz_lajani"
android:textSize="35sp" />
and my main class:
final CustomTextView tv_onv_amoozsh= (CustomTextView) findViewById(R.id.tv_onv_amoozsh);
tv_onv_amoozsh.setText("page");
final CustomTextView tv_num_amoozsh=(CustomTextView) findViewById(R.id.tv_num_amoozsh);
tv_num_amoozsh.setText(sfhe_num);
LogCat Error:
02-03 22:41:38.329: E/AndroidRuntime(19952): FATAL EXCEPTION: main
02-03 22:41:38.329: E/AndroidRuntime(19952): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.niloo.test2/com.niloo.test2.MainActivity}: android.view.InflateException: Binary XML file line #143: Error inflating class com.niloo.test2.CustomTextView

The problem is most likely that you're initializing shp, size, fasle, and font outside of the constructor. These initializations happen before any constructor code is run. context is never set and is null when getSharedPreferences is called on it.
Try this:
public class CustomTextView extends TextView {
private SharedPreferences shp;
private int size;
private int fasle;
private String font;
public CustomTextView(Context context) {
super(context);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
if (isInEditMode()) {
return;
}
shp = context.getSharedPreferences("text", Context.MODE_PRIVATE);
size = shp.getInt("size", 22);
fasle = shp.getInt("fasle", 1);
font = shp.getString("font", "bmitra");
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/" + font));
setTextSize(size);
setLineSpacing(fasle, 1);
}
}

Do you have this at the first view in your layout?
xmlns:custom="http://schemas.android.com/apk/res-auto"
Please post the full layout file (reduce it in your project to the minimum that is still failing. Maybe only have one view in it - your custom text )
EDIT:
The xml code you posted is invalid. Here is the fixed version that should work (do not omit "http://", remove semicolons)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/sabzabi_kmrng"
android:gravity="top"
android:orientation="vertical"
tools:context="com.niloo.test2.MainActivity">
</LinearLayout>

The error is coming from this line:
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/"+font));
Here we don't need to mention the keyword "fonts/" for path, because getAssets() method giving the route path of assets folder. So you can directly give font name like below:
setTypeface(Typeface.createFromAsset(context.getAssets(), font));

Related

compound layout doesn't show inner views

I extended from LinearLayout and inflated views, but on the screen those views in my layout are not appeared. I see my view group in editor, but it seems like it's empty. No views inside it.
FragmentPickerViewGroup looks like this:
package com.test.pecode.myapplication;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class FragmentPickerViewGroup extends LinearLayout {
private ImageView background;
private Button minusButton;
private Button plusButton;
public FragmentPickerViewGroup(Context context) {
super(context);
init();
}
private void init() {
setOrientation(LinearLayout.HORIZONTAL);
inflate(getContext(), R.layout.view_fragment_picker, this);
minusButton = findViewById(R.id.minus_btn);
plusButton = findViewById(R.id.plus_btn);
background = findViewById(R.id.background_rectangle);
minusButton.setVisibility(INVISIBLE);
minusButton.setGravity(Gravity.TOP | Gravity.START);
minusButton.setBackgroundResource(R.mipmap.button_bg);
background.setBackgroundResource(R.mipmap.rectangle);
background.setBackgroundResource(R.mipmap.rectangle);
plusButton.setBackgroundResource(R.mipmap.button_bg);
plusButton.setGravity(Gravity.TOP | Gravity.END);
}
public FragmentPickerViewGroup(Context context, #Nullable AttributeSet
attrs) {
super(context, attrs);
init();
}
public FragmentPickerViewGroup(Context context, #Nullable AttributeSet
attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public FragmentPickerViewGroup(Context context, AttributeSet attrs, int
defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
}
I used merge tag for my layout. Probably something goes wrong there? This is my layout, which I inflate into my view group:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/minus_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="#+id/background_rectangle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:contentDescription="#string/background_rectangle" />
<Button
android:id="#+id/plus_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</merge>

Custom view (not ViewGroup) created based on xml layout (with predefined attributes)

I want to implement a custom ImageView with some predefined attributes based on the xml file. To do that I prepared a layout wrapped within merge tag:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="#+id/my_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:src="#drawable/icon" />
</merge>
And extended ImageView class:
public class CustomImageView extends LinearLayout{
public ImageFormField(Context context) {
super(context);
init();
}
public ImageFormField(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ImageFormField(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ImageFormField(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
View.inflate(getContext(), R.layout.custom_image_view, this);
}
}
It works so far, but I actually don't need that LinearLayout as I could extend directly from the ImageView. By extending ImageView I'd like to have the possibility to override src parameter from the default layout.
So I removed merge tag to have only ImageView in the layout and tried this:
public class CustomImageView extends AppCompatImageView{
public ImageFormField(Context context) {
super(context);
init();
}
public ImageFormField(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ImageFormField(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
View.inflate(getContext(), R.layout.custom_image_view, null); //can't pass root here
}
}
... but the image is simply not displayed. I want to be able to use my view this way:
<com.my.package.CustomImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
with possibility to override src attribute. Is there a way to do that by inflating layout or do I have to go deep with attributes (including custom ones)?
UPDATE
By "overriding src attribute I mean that by default image will have source from its xml file, but user can use it that way to pass another value within this custom view:
<com.my.package.CustomImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/another_icon" />
To provide a "default" image but also allow the user to override that default by specifying the android:src attribute, you can do this:
package com.example.stackoverflow;
import android.content.Context;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
public class CustomImageView extends AppCompatImageView {
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
if (getDrawable() == null) {
setImageResource(R.drawable.default_image);
}
}
}
Then you can use it like this:
<!-- will display `default_image` -->
<com.example.stackoverflow.CustomImageView
android:layout_width="200dp"
android:layout_height="200dp"/>
Or:
<!-- will display `other_image` -->
<com.example.stackoverflow.CustomImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:src="#drawable/other_image"/>
There's no need to inflate anything inside the custom image view, and no need to create custom attributes (though you could certainly create custom attributes and use them if you wanted to).
You could update the Java code to apply other "default" styles too.

how to use custom fonts on textview in android

For implementing custom font i seen few examples here issue is different,I am taking custom font in one abstract class which is used in all over the application.i am unable to change the fonts.
thanks in advance.
Create the custom class like below.
public class CustomTextView extends TextView {
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public CustomTextView(Context context) {
super(context);
init(null);
}
private void init(AttributeSet attrs) {
if (attrs!=null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomTextView);
String fontName = a.getString(R.styleable.CustomTextView_fontName);
if (fontName!=null) {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/"+fontName);
setTypeface(myTypeface);
}
a.recycle();
}
}
}
and add your font in assets>fonts folder.
add following in attrs.xml
<declare-styleable name="CustomTextView">
<attr name="fontName" format="string" />
</declare-styleable>
to use.
<com.abc.cusomclass.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fontName="/*name of your font from assets/font folder*/"/>
You can do like this.
You have to add your .tff file on the assets folder
ArialMTBoldRegularTextView.java:
public final class ArialMTBoldRegularTextView extends CustomTextView {
public static final String FONT_PATH = "arial-rounded-mt-bold.ttf";
public ArialMTBoldRegularTextView(Context context) {
super(context);
setFont(FONT_PATH);
}
public ArialMTBoldRegularTextView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
setFont(FONT_PATH);
}
public ArialMTBoldRegularTextView(Context context, AttributeSet attributeSet, int defStyleAttr) {
super(context, attributeSet, defStyleAttr);
setFont(FONT_PATH);
}
public void setFont(String fontPath) {
changeFont(this, fontPath);
}
public static void changeFont(final CompoundButton button, final String fontPath) {
Typeface typeface = Typeface.createFromAsset(button.getContext().getAssets(), fontPath);
button.setTypeface(typeface);
}
}
CustomTextView.java
public class CustomTextView extends TextView {
public CustomTextView(Context context) {
super(context);
}
public CustomTextView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public CustomTextView(Context context, AttributeSet attributeSet, int defStyleAttr) {
super(context, attributeSet, defStyleAttr);
}
public Typeface getFont(final Context context, final String fontPath) {
return Typeface.createFromAsset(context.getAssets(), fontPath);
}
public void changeFont(final TextView textView, final String fontPath) {
Typeface typeface = Typeface.createFromAsset(textView.getContext().getAssets(), fontPath);
textView.setTypeface(typeface);
}
public void changeFont(final CompoundButton button, final String fontPath) {
Typeface typeface = Typeface.createFromAsset(button.getContext().getAssets(), fontPath);
button.setTypeface(typeface);
}
}
and fater in xml:
<packagename.views.ArialMTBoldRegularTextView
android:layout_width="wrap_content"
android:layout_height="35dp"
android:gravity="center"
android:text="Pseudo"/>
try this for custom font fron Assets
// Font path
String fontPath = "fonts/Face Your Fears.ttf";
// text view label
TextView txtGhost = (TextView) findViewById(R.id.ghost);
// Loading Font Face
Typeface tf = Typeface.createFromAsset(getAssets(), fontPath);
// Applying font
txtGhost.setTypeface(tf);
for more information check this,
http://www.androidhive.info/2012/02/android-using-external-fonts/
now android Support Library 26 supports using fonts directly from your XML see the doc for more details.
The better way of doing this is to make custom TextView with custom font like this:
Java
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
public class RegularProximaTextView extends TextView {
public static Typeface FONT_NAME;
public RegularProximaTextView(Context context) {
super(context);
if(FONT_NAME == null) FONT_NAME =
Typeface.createFromAsset(context.getAssets(), "fonts/Mark Simonson -
Proxima Nova Regular.otf");
this.setTypeface(FONT_NAME);
}
public RegularProximaTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if(FONT_NAME == null) FONT_NAME =
Typeface.createFromAsset(context.getAssets(), "fonts/Mark Simonson -
Proxima
Nova Regular.otf");
this.setTypeface(FONT_NAME);
}
public RegularProximaTextView(Context context, AttributeSet attrs, int
defStyle) {
super(context, attrs, defStyle);
if(FONT_NAME == null) FONT_NAME =
Typeface.createFromAsset(context.getAssets(), "fonts/Mark Simonson -
Proxima Nova Regular.otf");
this.setTypeface(FONT_NAME);
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_login"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true"
android:background="#color/colorGreyBar"
>
<com.tracer.joblogic.v2.helpers.custom_ui.RegularProximaTextView
android:id="#+id/tvTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:textColor="#color/colorButtonRed"
android:text="Some text"
android:textSize="8sp"
/>
</android.support.design.widget.CoordinatorLayout>

Change color Text from CustomTextView

By default to change textColor programatically is :
textView.setTextColor(Color.RED);
I need to have a custom Textview to change typeface and color by default, How can change textcolor from CustomTextView class, here is my code.
public class CustomTextView extends TextView {
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomTextView(Context context) {
super(context);
}
public void setTypeface(Typeface tf, int style) {
if(!isInEditMode()) {
if (style == Typeface.BOLD) {
super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/Lato-Bold.ttf"));
} else if(style == Typeface.ITALIC){ // constant used to set Lato-Light.
super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/Lato-Light.ttf"));
}else {
super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/Lato-Regular.ttf"));
}
}
}
The below code is the way to set your default text color and typeface.
public class CustomTextView extends TextView {
public CustomTextView(Context context) {
super(context);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
setTypeface(Typeface.createFromAsset(context.getAssets(),"fonts/Lato-Light.ttf"));
setTextColor(Color.RED);
}
}
The init() method gets called every time the text view gets created, and will then set the typeface and color in that. You can manipulate any other variables you want to in there.
Use setTextColor(Color.RED); after each super in each constructor.
Step 1
In the /assets directory (not the /resource directory), create a folder called /fonts. Copy your custom font here. You can use both TTF and OTF fonts.
Step 2
In the /res/values folder, create a new file called attrs.xml. This is how the Android SDK lets you name custom properties for your widgets.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyTextView">
<attr name="fontName" format="string" />
</declare-styleable>
</resources>
Step 3
In /res/layouts, you will need to include your to-be-created custom text view in the activity_main.xml file.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:customfontdemo="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:padding="12dp"
android:text="Standard Android Font" />
<com.authorwjf.customfontdemo.MyTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="32sp"
android:padding="12dp"
customfontdemo:fontName="pipe_dream.ttf"
android:text="Custom Android Font" />
</LinearLayout>
Step 4
In the /src folder, you will want to create your MyTextView class. It extends the standard text view, plucks the font name from the custom attribute, and applies the type face.
package com.authorwjf.customfontdemo;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
public class MyTextView extends TextView {
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public MyTextView(Context context) {
super(context);
init(null);
}
private void init(AttributeSet attrs) {
setTextColor(Color.RED);
if (attrs!=null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MyTextView);
String fontName = a.getString(R.styleable.MyTextView_fontName);
if (fontName!=null) {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/"+fontName);
setTypeface(myTypeface);
}
a.recycle();
}
}
}
Step 5
Because the text view is now self-contained, you aren't required to make any modifications to our /src/MainAcitivity.java file.
package com.authorwjf.customfontdemo;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}

I have a subclass of ImageView, but when I add this into XML it gives inflate error

This seems like a simple thing, but it does not run. What am I doing wrong?
I'm subclassing ImageView, but if I put it inside XML layouts, it gives:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myappSubclass/com.example.myappSubclass.MyActivity}:
android.view.InflateException: Binary XML file line #21: Error
inflating class com.example.myappSubclass.ImageViewSubclass
Here is my code:
package com.example.myappSubclass;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
import java.util.jar.Attributes;
/**
* Created by me on 2014-07-11.
*/
public class ImageViewSubclass extends ImageView {
public Context thisContext;
public ImageViewSubclass(Context context, AttributeSet attrs, Context thisContext) {
super(context, attrs);
this.thisContext = thisContext;
}
public ImageViewSubclass(Context context, AttributeSet attrs, int defStyle, Context thisContext) {
super(context, attrs, defStyle);
this.thisContext = thisContext;
}
public ImageViewSubclass(Context context) {
super(context);
this.thisContext = context;
}
public void changeImage(){
this.setImageLevel(0);
}
And inside the XML I have it simply:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, MyActivity"
/>
<Button android:layout_width="match_parent" android:layout_height="50dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:text="Test"
/>
<com.example.myappSubclass.ImageViewSubclass android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<!--<ImageView android:layout_width="fill_parent" android:layout_height="fill_parent"/>-->
</LinearLayout>
Custom views must have predefined constructors to be able to inflate them from an XML layout. You should remove thisContext from all of them.
public ImageViewSubclass(Context context) {
super(context);
...
}
public ImageViewSubclass(Context context, AttributeSet attrs) {
super(context, attrs);
...
}
public ImageViewSubclass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
...
}
Why did you add that extra parameter anyway? All views have a getContext() method if that's what you needed.

Categories

Resources