59

Grrr...

I create a subclass of view as an inner class in my Activity. Before I simply linked to this view from my activity with:

setContentView(new CustomView(this));

without problems.

Now, however, my view is getting more complex so I am making it part of a FrameLayout so that I can make this the base view and add a Spinner widget on top of it. The problem is, when I do this I get an error:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.grafightscratch.ochemmer/com.grafightscratch.ochemmer.MoleculeTablet}: android.view.InflateException: Binary XML file line #4: Error inflating class com.grafightscratch.ochemmer.MoleculeTablet.MoleculeTabletView
...
Caused by: android.view.InflateException: Binary XML file line #4: Error inflating class com.grafightscratch.ochemmer.MoleculeTablet.MoleculeTabletView
...
Caused by: java.lang.ClassNotFoundException: com.grafightscratch.ochemmer.MoleculeTablet.MoleculeTabletView in loader dalvik.system.PathClassLoader@43b74a28

So- this view worked before when I linked to it directly, but when I tried to add it in the main.xml file as part of a framelayout I got the above error. I also tried putting into a layout with only it being displayed via:

<com.grafightscratch.ochemmer.MoleculeTablet.MoleculeTabletView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/molecule_tablet_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>

Nothing works. I keep getting the InflateException/ClassNotFoundException errors. It complains about "line #3" in the binary XML file, and if it is talking about main.xml that is the package declaration which I have triple checked.

EDIT I tried making this view a separate class (ie- not an inner class) and it works. After some searching around I found some posts saying that the xml tag should look like this:

<com.grafightscratch.ochemmer.MoleculeTablet$MoleculeTabletView ...>

Ie, a dollar sign should be used to separate the innerclass from the main class. However, Eclipse barfs on this, calls it an error, and refuses to let me build or deploy with that character there. So now the question becomes: how does one reference a View that is an inner class?

IcedDante
  • 4,991
  • 10
  • 49
  • 81

6 Answers6

160

For inner classes the syntax becomes:

<view class="com.grafightscratch.ochemmer.MoleculeTablet$MoleculeTabletView" />

The reason is that $ is an illegal character in XML tags.

JRL
  • 72,358
  • 17
  • 90
  • 140
Romain Guy
  • 95,351
  • 17
  • 214
  • 199
  • 5
    Just a note here, the xml tag may need be "closer" to your class than the `View` tag (in my case I needed a `ViewGroup`) – Romuald Brunet Oct 06 '12 at 09:31
  • While I don't get an error, when I fetch the view (using findViewById), I get an instance of `android.view.View`, not an instance of the inner class. What gives? – cintron Apr 28 '14 at 18:56
  • 4
    Make sure the xml view tag is lower case then you should be able to cast it to the class you specified – wkarl Jul 16 '14 at 23:16
  • 2
    Unfortunately this answer doesn't work if you want to include your class in a `PreferenceScreen` XML layout. You get `java.lang.ClassNotFoundException: Didn't find class "android.preference.view"`. The only way round this I've found is to promote the static nested class to a full-blown class in its own file, which isn't ideal. See also http://stackoverflow.com/q/7249028/1843329 – snark Apr 26 '16 at 11:48
39

I was having the same issue. The syntax in the XML file was correct, however.

What ended up resolving the issue for me was that the inner class needs to be declared as static. For example:

public static class myWebView extends WebView
Pang
  • 8,605
  • 144
  • 77
  • 113
Whatzit Toya
  • 647
  • 7
  • 4
11

for inner class :

<view class="{package}.{ParentClass}${innerClass}" />

and for inner class , you must declare your class :

public static InnerClass

static is require .

Adnan Abdollah Zaki
  • 3,238
  • 5
  • 44
  • 53
2

Here are some key points to make a custom view inside an inner class...

public static class MainClass {
    ....
    ....
        public class SubClassView extends LinearLayout {
           public SubClassView(Context context, AttributeSet attrs) {
                super(context, attrs);
                .....
           }
    ....
    ....
       }
    }

The layout should be as follows:

<view class = ".MainClass$SubClassView"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/button"/>

Java class

  • static is required
  • constructor with AttributeSet is required (at least one)

XML file

  • view tag (with lower case NOT View) is required
  • class tag with the path to your inner class, using
  • $ instead of "." before your SubClassView name
dianakarenms
  • 2,220
  • 1
  • 18
  • 22
2
<view xmlns:android="http://schemas.android.com/apk/res/android"
    class="com.example.Myproject.Myactivity$Myview"
     android:layout_width="fill_parent" android:id="@+id/name" android:visibility="visible" android:layout_gravity="bottom" android:layout_height="fill_parent" android:focusableInTouchMode="true"
/>

this code worked for me. When i left out some of the elements like layout_width my program crashed. I also had to make my view class static in order for it to work. In the end It would have been the same if i just took it out of its nest. The android note example uses a nested class.

justin
  • 21
  • 1
0

You need to specify the fully qualified name of your view class in the XML for inflation to work and View Class to be found by the Runtime System.
Since you have declared your View as inner class of your activity the fully qualified name would be: <your_package_name>.OuterClassName.InnerClassName

Are you sure com.grafightscratch.ochemmer.CustomView is the fully qualified name of your class?

EDIT: Thanks for reminding me of this. When the views are declared as nested classes there is a slight aberration, see Use Custom component of this document.

Samuh
  • 35,513
  • 26
  • 104
  • 116
  • Ahhhh... you caught me- I was trying to edit this post for clarity and only ended up introducing a "post error". OK- I am just going to cut and paste so that it reflects the actual code. – IcedDante Jan 20 '10 at 05:14
  • Okay- the question now reflects the real package names. But yes- it is still an issue. – IcedDante Jan 20 '10 at 05:55
  • See the "Use Custom Component Section" in this page: http://developer.android.com/intl/fr/guide/topics/ui/custom-components.html#modifying – Samuh Jan 20 '10 at 07:46
  • Thanks Samuh, that document helps. It seems to suggest that making the inner class static is necessary as well. While that does seem to fix my problem, it means that ALL fields in the outer class that it references need to be static too. Is there a way to do this without the static class? – IcedDante Jan 20 '10 at 22:24
  • IMO, whether or not to make a class static is a design choice that you make. If the class can stand alone, all by itself make it static. If it needs to the tied with the instance of the outer class it should be non-static. – Samuh Jan 21 '10 at 06:14