Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing extended/custom View throws NoSuchMethod for constructor

Tags:

android

I have a customized TextView which implements the three View constructors (nb, this is my first stab at an android app):

public class DynamicGeometryTextView extends TextView {

    public DynamicGeometryTextView (Context con) { super(con); }

    public DynamicGeometryTextView (Context con, AttributeSet attrs) {
        super(con, attrs);
    }

    public DynamicGeometryTextView (Context con, AttributeSet attrs, int style) {
        super(con, attrs, style); 
    }

This is a non-static inner class, since it needs to access instance data from the outer class. It appears in an .xml layout:

<view class="cogdis.chalkboard.DisplayText$DynamicGeometryTextView"
    android:id="@+id/chalkboard"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" /> 

Everything compiles and installs fine, but at runtime:

Caused by: android.view.InflateException: Binary XML file line #7: Error inflating class cogdis.chalkboard.DisplayText$DynamicGeometryTextView
    at android.view.LayoutInflater.createView(LayoutInflater.java:596)                                                                         
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)                                                                  
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)                                                                           
    at android.view.LayoutInflater.inflate(LayoutInflater.java:489)                                                                            
    at android.view.LayoutInflater.inflate(LayoutInflater.java:396)                                                                            
    at android.view.LayoutInflater.inflate(LayoutInflater.java:352)                                                                            
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:256)                                                       
    at android.app.Activity.setContentView(Activity.java:1867)                                                                                 
    at cogdis.chalkboard.DisplayText.onCreate(DisplayText.java:26)                                                                             
    at android.app.Activity.performCreate(Activity.java:5008)                                                                                  
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)                                                             
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)                                                              
    ... 11 more                                                                                                                                
Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]                       
    at java.lang.Class.getConstructorOrMethod(Class.java:460)                                                                                  
    at java.lang.Class.getConstructor(Class.java:431)                                                                                          
    at android.view.LayoutInflater.createView(LayoutInflater.java:561)                                                                         
    ... 22 more                                    

To my eye, this implies it can't find the (Context, AttributeSet) version of the constructor...but it exists. I've looked at a few other SO posts, like Android Custom View Constructor, this all point to the same conclusion (to my eye) and read the API Guide on Custom Components repeatedly, but I've been stumped with this for more than an hour.

Anyone have any ideas? Is there a way to debug this further?

FOR POSTERITY, ie., anyone new to this like me, non-static inner classes are a no-go if your custom View is referenced in an XML layout, but if you create it programmatically, it can work, eg:

    LayoutInflater lif = getLayoutInflater();
    ViewGroup layout = (ViewGroup)lif.inflate(R.layout.board, null);

    tv = new DynamicGeometryTextView(this);

    layout.addView((View)tv);

In this case, you only need to match the constructors you actually use. Layout parameters (WRAP_CONTENT, etc) can be set in the constructor via setLayoutParams() which is inherited from View.

like image 945
CodeClown42 Avatar asked Jul 25 '12 17:07

CodeClown42


2 Answers

There is no way of instantiating a non-static inner class without reference to an instance of the outer class.

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

So this could be the reason that the layout inflater failed to inflate your class. Make your class static after removing references to the outer class members.

like image 184
Dheeraj Vepakomma Avatar answered Nov 07 '22 01:11

Dheeraj Vepakomma


Change:

public class DynamicGeometryTextView extends TextView {

To:

public static class DynamicGeometryTextView extends TextView {

In order to properly reference it, it must be a static inner class

like image 34
Salil Pandit Avatar answered Nov 07 '22 00:11

Salil Pandit