Question

I have a custom view that extends LinearLayout, with these constructors:

public class CustomView extends LinearLayout {

public CustomView(Context context) {
    this(context, null);
}

public CustomView(Context context, AttributeSet attrs) {
    this(context, attrs, R.attr.customViewStyle);
}

public CustomView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    /* set custom attributes with TypedArray */
}

    /* other methods */
}

In my /res/values/attrs.xml:

<attr name="customViewStyle" format="reference" />

<declare-styleable name="CustomeView">
    <attr name="value" format="integer" />
    <attr name="android:imeOptions" />
    <attr name="android:imeActionId" />
    <attr name="android:imeActionLabel" />
</declare-styleable>

In my /res/values/styles.xml:

<style name="AppTheme" parent="@android:style/Theme.Black">
    <item name="android:windowBackground">@drawable/bg_dark_fiber</item>
    <item name="customViewStyle">@style/CustomViewStyle</item>
</style>

<style name="CustomViewStyle">
    <item name="android:clickable">true</item>
    <item name="android:focusable">true</item>
    <item name="android:focusableInTouchMode">true</item>
</style>

AppTheme is set as the theme for the entire application. The desired result is that my custom view is focusable and clickable by default without my having to add those attributes in my layout files (whereas a regular LinearLayout is not). When I run the app, it crashes with the following stack trace:

05-17 14:58:53.010: E/ActivityThread(26767): Failed to inflate
05-17 14:58:53.010: E/ActivityThread(26767): android.view.InflateException: Binary XML file line #8: Error inflating class com.example.customviews.CustomView
05-17 14:58:53.010: E/ActivityThread(26767):    at android.view.LayoutInflater.createView(LayoutInflater.java:518)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:570)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:623)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.view.LayoutInflater.inflate(LayoutInflater.java:408)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
05-17 14:58:53.010: E/ActivityThread(26767):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:212)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.app.Activity.setContentView(Activity.java:1657)
05-17 14:58:53.010: E/ActivityThread(26767):    at com.example.pincode.PinCodeActivity.onCreate(PinCodeActivity.java:26)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1722)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.app.ActivityThread.access$1500(ActivityThread.java:123)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.os.Handler.dispatchMessage(Handler.java:99)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.os.Looper.loop(Looper.java:130)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.app.ActivityThread.main(ActivityThread.java:3835)
05-17 14:58:53.010: E/ActivityThread(26767):    at java.lang.reflect.Method.invokeNative(Native Method)
05-17 14:58:53.010: E/ActivityThread(26767):    at java.lang.reflect.Method.invoke(Method.java:507)
05-17 14:58:53.010: E/ActivityThread(26767):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
05-17 14:58:53.010: E/ActivityThread(26767):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
05-17 14:58:53.010: E/ActivityThread(26767):    at dalvik.system.NativeStart.main(Native Method)
05-17 14:58:53.010: E/ActivityThread(26767): Caused by: java.lang.reflect.InvocationTargetException
05-17 14:58:53.010: E/ActivityThread(26767):    at java.lang.reflect.Constructor.constructNative(Native Method)
05-17 14:58:53.010: E/ActivityThread(26767):    at java.lang.reflect.Constructor.newInstance(Constructor.java:415)
05-17 14:58:53.010: E/ActivityThread(26767):    at android.view.LayoutInflater.createView(LayoutInflater.java:505)
05-17 14:58:53.010: E/ActivityThread(26767):    ... 21 more
05-17 14:58:53.010: E/ActivityThread(26767): Caused by: java.lang.NoSuchMethodError: android.widget.LinearLayout.<init>
05-17 14:58:53.010: E/ActivityThread(26767):    at com.example.customviews.CustomView.<init>(CustomView.java:98)
05-17 14:58:53.010: E/ActivityThread(26767):    at com.example.customviews.CustomView.<init>(CustomView.java:94)
05-17 14:58:53.010: E/ActivityThread(26767):    ... 24 more

I can't understand what's causing the InflateException in the call to super(context, attrs, defStyle). I also tried super(context, attrs, 0), but that doesn't help, which is really odd because even LinearLayout uses that, as do most other views whose source code I've examined.

Était-ce utile?

La solution

I found this answer on the Android Developers Google Group:

The three-argument version of LinearLayout constructor is only available with API 11 and higher -- i.e. Android 3.0.

This dependency has to be satisfied at runtime by the actual Android version running on the device.

I was testing on a handset running Gingerbread (2.3.3). Sure enough, when I ran the program on an emulator with ICS (4.0.3), it worked fine. Still hunting for a workaround so I can use my code on pre-Honeycomb.

Autres conseils

Your constructors are calling this instead of super. If you change that, then it will work.

I have just extended linear layout with just constructors to test that it works.

I also encountered this problem with a custom LinearLayout. What I did was to call super instead of this in the constructors and set the attributes in a separate method.

public class CustomView extends LinearLayout {

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

public CustomView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CustomView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    setAttributes(attrs);
}

private void setAttributes(AttributeSet attrs) {
    /* set custom attributes with TypedArray */
}
    /* other methods */
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top