Search code examples
androidxmlinflate-exception

android.view.InflateException with dynamic setText from Custom view


I have a custom view "BallHoldView" which is run from an activity "BallHoldActivity" by adding said view to the BallHoldActivity layout resource within merge tags. Also within the same layout xml is a TextView (scoreText). I want to set scoreText's text dynamically from the BallHoldView. When my program tries to run scoreText.setText("new text here"); I get a view.InflateException. Commenting out this one line of code removes the errors.

Through online research I have identified the following:

  • my BallHoldView needs a constructor with Attributes passed to it. (Check)
  • my scoreText needs to be instantiated with reference to the activity, not the view: ((Activity)getContext()).findViewById(R.id.scoreText); (Check)
  • It seems the majority of issues with this exception is that something is not declared properly in the xml file. I think the problem is that I'm missing something in the xml file, but I don't know what, and I can't find a solution online.

Can anyone see what I'm missing, or what I've done wrong?

Main errors seem to be:

android.view.InflateException: Binary XML file line #12: Error inflating class
Caused by: java.lang.reflect.InvocationTargetException
Caused by: java.lang.NullPointerException

xml line #12 (& #13):

<oaa.tms.zoneball.ballHold.BallHoldView
android:id="@+id/ballHold"

Null Pointer is at BallHoldView.java:37 which is:

scoreText.setText("New Score"); // java line 37.

Here's BallHoldView:

public class BallHoldView extends View
{
private ShapeDrawable circle10, circle50, circleEYE;
private TextView scoreText;
private int viewWidth, viewHeight;
private float circCentreX, circCentreY, circ10Radius, circ50Radius, circEyeRadius;

public BallHoldView(Context context)
{
    super(context);
}

public BallHoldView(Context context, AttributeSet attrs)
{ super(context, attrs);
 Log.e("BallHoldView", "CONSTRUCTOR ENTERED");
 circle10 = new ShapeDrawable(new OvalShape());
    circle10.getPaint().setColor(0xffff9900);
 circle50 = new ShapeDrawable(new OvalShape());
    circle50.getPaint().setColor(0xffb80000);
 circleEYE = new ShapeDrawable(new OvalShape());
    circleEYE.getPaint().setColor(0xff000000);
 scoreText = (TextView)((Activity)getContext()).findViewById(R.id.scoreText);
            Log.e("BallHoldView", "scoreText created");
    scoreText.setText("New Score");
            Log.e("BallHoldView", "scoreText changed");
}

public void onDraw(Canvas c)
{
    super.onDraw(c);
    // Draw some circles here
}

protected void onSizeChanged(int w, int h, int oldW, int oldH)
{
    // change circle parameters here
}
}

Here's the xml:

<merge 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"
android:background="@drawable/shape_rect_black_border"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="oaa.tms.zoneball.BallHoldActivity" >

<oaa.tms.zoneball.ballHold.BallHoldView
android:id="@+id/ballHold"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<TextView 
android:id="@+id/scoreText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|left"
android:background="@drawable/shape_rect_textbg"
android:textSize="22sp"
android:text="@string/score" />

<TextView 
android:id="@+id/timeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:background="@drawable/shape_rect_textbg"
android:textSize="22sp"
android:text="@string/time" />

</merge>

Here's the log cat (errors):

10-05 17:44:04.326: E/BallHoldView(3474): CONSTRUCTOR ENTERED
10-05 17:44:04.326: E/BallHoldView(3474): scoreText created
10-05 17:44:04.336: E/AndroidRuntime(3474): FATAL EXCEPTION: main
10-05 17:44:04.336: E/AndroidRuntime(3474): java.lang.RuntimeException: Unable to start activity ComponentInfo{oaa.tms.zoneball/oaa.tms.zoneball.BallHoldActivity}: android.view.InflateException: Binary XML file line #12: Error inflating class oaa.tms.zoneball.ballHold.BallHoldView
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2249)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2299)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.app.ActivityThread.access$700(ActivityThread.java:154)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.os.Looper.loop(Looper.java:137)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.app.ActivityThread.main(ActivityThread.java:5306)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at java.lang.reflect.Method.invokeNative(Native Method)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at java.lang.reflect.Method.invoke(Method.java:511)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at dalvik.system.NativeStart.main(Native Method)
10-05 17:44:04.336: E/AndroidRuntime(3474): Caused by: android.view.InflateException: Binary XML file line #12: Error inflating class oaa.tms.zoneball.ballHold.BallHoldView
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.view.LayoutInflater.createView(LayoutInflater.java:619)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:693)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:752)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.view.LayoutInflater.inflate(LayoutInflater.java:460)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:342)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.app.Activity.setContentView(Activity.java:1928)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.support.v7.app.ActionBarActivity.superSetContentView(ActionBarActivity.java:217)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.support.v7.app.ActionBarActivityDelegateICS.setContentView(ActionBarActivityDelegateICS.java:110)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.support.v7.app.ActionBarActivity.setContentView(ActionBarActivity.java:77)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at oaa.tms.zoneball.BallHoldActivity.onCreate(BallHoldActivity.java:17)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.app.Activity.performCreate(Activity.java:5255)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1097)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2213)
10-05 17:44:04.336: E/AndroidRuntime(3474):     ... 11 more
10-05 17:44:04.336: E/AndroidRuntime(3474): Caused by: java.lang.reflect.InvocationTargetException
10-05 17:44:04.336: E/AndroidRuntime(3474):     at java.lang.reflect.Constructor.constructNative(Native Method)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
10-05 17:44:04.336: E/AndroidRuntime(3474):     at android.view.LayoutInflater.createView(LayoutInflater.java:593)
10-05 17:44:04.336: E/AndroidRuntime(3474):     ... 25 more
10-05 17:44:04.336: E/AndroidRuntime(3474): Caused by: java.lang.NullPointerException
10-05 17:44:04.336: E/AndroidRuntime(3474):     at oaa.tms.zoneball.ballHold.BallHoldView.<init>(BallHoldView.java:37)
10-05 17:44:04.336: E/AndroidRuntime(3474):     ... 28 more

EDIT: Using the following code I have confirmed scoreText is null:

scoreText = (TextView)((Activity)getContext()).findViewById(R.id.scoreText);
            Log.e("BallHoldView", "scoreText created");
    if(scoreText != null)
    {
        scoreText.setText("New Score");
            Log.e("BallHoldView", "scoreText changed");
    }
    else
        Log.e("BallHoldView", "scoreText was null");

Why is it null?


Solution

  • The problem is that your code at line # 37

    scoreText.setText("New Score");
    

    scoreText is null.

    scoreText = (TextView)((Activity)getContext()).findViewById(R.id.scoreText);
    

    The above line is not able to find the scoreText. This might be because when the custom view layout is inflated, it will call its constructor, and in there you are trying to refer scoreText which has not been inflated yet, as it comes after ballHold in your android xml.
    The solution might be to put the ballHold custom view after your scoreText in android xml. Or otherwise the proper way would be to pass the scoreText TextView from your java activity code to the BallHoldView CustomView class in its constructor and then use it. In that case, in your activity code you will definitely be able to find view by id.