188

I'm trying to create a custom view GhostSurfaceCameraView that extends SurfaceView. Here's my class definition file

GhostSurfaceCameraView.java:

public class GhostSurfaceCameraView extends SurfaceView implements SurfaceHolder.Callback {
    SurfaceHolder mHolder;
    Camera mCamera;

    GhostSurfaceCameraView(Context context) {
        super(context);

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where to draw.
        mCamera = Camera.open();
        try {
            mCamera.setPreviewDisplay(holder);
        } catch (IOException exception) {
            mCamera.release();
            mCamera = null;
            // TODO: add more exception handling logic here
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the preview.
        // Because the CameraDevice object is not a shared resource, it's very
        // important to release it when the activity is paused.
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }   

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // Now that the size is known, set up the camera parameters and begin
        // the preview.
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewSize(w, h);
        parameters.set("orientation", "portrait");
        // parameters.setRotation(90); // API 5+
        mCamera.setParameters(parameters);
        mCamera.startPreview();
    }
}

And this is in my ghostviewscreen.xml:

<com.alpenglow.androcap.GhostSurfaceCameraView android:id="@+id/ghostview_cameraview"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"/>

Now in the activity I made:

protected void onCreate(Bundle savedInstanceState) {
    try {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ghostviewscreen);
    }
}

When setContentView() gets called, an exception is thrown:

Binary XML file 09-17 22:47:01.958: ERROR/ERROR(337):
ERROR IN CODE:
android.view.InflateException: Binary
XML file line #14: Error inflating
class
com.alpenglow.androcap.GhostSurfaceCameraView

Can anyone tell me why I get this error? Thanks.

Bono
  • 4,757
  • 6
  • 48
  • 77
eccentricbiped
  • 5,701
  • 3
  • 16
  • 8

10 Answers10

372

I think I figured out why this wasn't working. I was only providing a constructor for the case of one parameter 'context' when I should have provided a constructor for the two parameter 'Context, AttributeSet' case. I also needed to give the constructor(s) public access. Here's my fix:

public class GhostSurfaceCameraView extends SurfaceView implements SurfaceHolder.Callback {
        SurfaceHolder mHolder;
        Camera mCamera;

        public GhostSurfaceCameraView(Context context)
        {
            super(context);
            init();
        }
        public GhostSurfaceCameraView(Context context, AttributeSet attrs)
        {
            super(context, attrs);
            init();
        }
        public GhostSurfaceCameraView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
eccentricbiped
  • 5,701
  • 3
  • 16
  • 8
  • 4
    Sometimes the simplest things can be a problem :) good to know that both parameters are used for inflating. – Warpzit Feb 20 '12 at 12:19
  • 5
    Thank you!! Nowhere in the examples could I find any mention about the necessity of overloading all the constructors! You saved me hours (days?) of time. – SMBiggs May 14 '12 at 15:12
  • 1
    Thanks a lot! The error message is quite unspecific, which had me stumped for a moment, they should have included the reason (missing constructor overload) in their error message. – AgentKnopf Jun 07 '12 at 09:46
  • 1
    thanks for this. does anyone know if this goes across the board for custom views? you need to include both constructors whenever you make a custom view? (context, and then context and attributes) – Tim Feb 03 '13 at 07:34
  • 2
    O, Should've seen it earlier! The message `View is not using the 2- **OR** 3-argument View constructors` is kind of misleading. – Attacktive Nov 03 '14 at 08:33
  • 1
    I'm having the same problem but your provided solution doesn't work for me. I'm running on Android 6.0 API 23 . Any more solutions ? – zulkarnain shah Dec 18 '15 at 05:30
  • I already had all of these constructors. But my error was that I didn't fully qualify my View's namespace (Xamarin). eccentricbiped seems to have done that already. – Chucky May 11 '16 at 13:25
  • I'm having the same issue even when i already defined my constructors to public. i'm having this issue with Api level 18 (Jelly been 4.3). While it works fine with Api level 23. – chandan kumar Jan 05 '18 at 06:57
45

@Tim - Both the constructors are not required, only the ViewClassName(Context context, AttributeSet attrs ) constructor is necessary. I found this out the painful way, after hours and hours of wasted time.

I am very new to Android development, but I am making a wild guess here, that it maybe due to the fact that since we are adding the custom View class in the XML file, we are setting several attributes to it in the XML, which needs to be processed at the time of instantiation. Someone far more knowledgeable than me will be able to shed clearer light on this matter though.

Sai Kishore
  • 326
  • 1
  • 7
  • 16
kvnam
  • 1,285
  • 2
  • 19
  • 34
  • This makes sense, my custom TextView always gets constructed with ViewClassName(Context context, AttributeSet attrs) when I define attributes for it in the xml. If I instantiate it without defining in the xml file, the regular constructor gets called with only context, ViewClassName(Context context). I was wondering what the other constructor does and according to this:http://stackoverflow.com/a/4022916/1505341 answer, it's supposed to be used for setting a base style for the view. – Kerem Mar 10 '14 at 12:52
19

Another possible cause of the "Error inflating class" message could be misspelling the full package name where it's specified in XML:

<com.alpenglow.androcap.GhostSurfaceCameraView android:id="@+id/ghostview_cameraview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>

Opening your layout XML file in the Eclipse XML editor should highlight this problem.

rmtheis
  • 5,992
  • 12
  • 61
  • 78
  • 2
    This was indeed the fix for my application. com.zerokol.views.joystickview Became com.zerokol.views.JoystickView And it worked! – Andy Mar 04 '15 at 19:21
  • true. Do double check spelling or try to work using intentions provided by your IDE, just start by typing your package name and all your availbale classes will be shown under intentions. – Khay Feb 27 '17 at 08:50
  • this was my case. – Banee Ishaque K Nov 07 '17 at 10:06
2

It's important to write full class path in the xml. I got 'Error inflating class' when only subclass's name was written in.

Mykola
  • 435
  • 4
  • 17
  • This is very similar to what @rmtheis is suggesting. Possibly better to comment his answer or even edit it with additional info. – Ilia Barahovsky Jan 25 '17 at 20:04
1

I had this error plaguing me for the past few hours. Turns out, I had added the custom view lib as a module in Android Studio, but I had neglected to add it as a dependency in app's build.gradle.

dependencies {
    ...
    compile project(':gifview')
}
Ionoclast Brigham
  • 1,703
  • 1
  • 12
  • 19
1

fwiw, I received this error due to some custom initialization within the constructor attempting to access a null object.

Tom Howard
  • 4,672
  • 2
  • 43
  • 48
0

I had the same problem extending a TextEdit. For me the mistake was I did non add "public" to the constructor. In my case it works even if I define only one constructor, the one with arguments Context and AttributeSet. The wired thing is that the bug reveals itself only when I build an APK (singed or not) and I transfer it to the devices. When the application is run via AndroidStudio -> RunApp on a USB connected device the app works.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
Nicola Mingotti
  • 860
  • 6
  • 15
0

in my case I added such cyclic resource:

<drawable name="above_shadow">@drawable/above_shadow</drawable>

then changed to

<drawable name="some_name">@drawable/other_name</drawable>

and it worked

Evgenii Vorobei
  • 1,457
  • 18
  • 20
0

In my case, I copied my class from somewhere else and didn't notice right away that it was an abstract class. You can't inflate abstract classes.

IsaiahJ
  • 454
  • 7
  • 19
0

The thing to understand here is that:

The constructor ViewClassName(Context context, AttributeSet attrs ) is called when inflating the customView via xml. You see you are not using the new keyword to instantiate your object i.e. you are not doing new GhostSurfaceCameraView(). Doing this you are calling the first constructor i.e. public View (Context context).

Whereas when inflating view from XML, i.e. when using setContentView(R.layout.ghostviewscreen); or using findViewById, you, NO, not you!, the android system calls the ViewClassName(Context context, AttributeSet attrs ) constructor.

This is clear when reading the documentation : "Constructor that is called when inflating a view from XML." See: https://developer.android.com/reference/android/view/View.html#View(android.content.Context,%20android.util.AttributeSet)

Hence, never forget basic polymorphism and never forget reading through the documentation. It saves a ton of headache.

kush
  • 486
  • 4
  • 6