Erreur de gonflement lors de l'extension d'une classe

188

J'essaye de créer une vue personnalisée GhostSurfaceCameraViewqui s'étend SurfaceView. Voici mon fichier de définition de classe

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();
    }
}

Et c'est dans mon ghostviewscreen.xml:

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

Maintenant dans l'activité que j'ai faite:

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

Lorsqu'elle setContentView()est appelée, une exception est levée:

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

Quelqu'un peut-il me dire pourquoi j'obtiens cette erreur? Merci.

excentrique
la source

Réponses:

369

Je pense avoir compris pourquoi cela ne fonctionnait pas. Je ne fournissais un constructeur que pour le cas d'un paramètre «context» alors que j'aurais dû fournir un constructeur pour le cas des deux paramètres «Context, AttributeSet». J'avais également besoin de donner un accès public aux constructeurs. Voici ma solution:

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();
        }
excentrique
la source
4
Parfois, les choses les plus simples peuvent poser problème :) bon à savoir que les deux paramètres sont utilisés pour gonfler.
Warpzit
5
Je vous remercie!! Nulle part dans les exemples je n'ai pu trouver de mention de la nécessité de surcharger tous les constructeurs! Vous m'avez fait gagner des heures (des jours?) De temps.
Scott Biggs
1
Merci beaucoup! Le message d'erreur est assez non spécifique, ce qui m'a laissé perplexe pendant un moment, ils auraient dû inclure la raison (surcharge du constructeur manquante) dans leur message d'erreur.
AgentKnopf
1
Merci pour cela. est-ce que quelqu'un sait si cela se passe partout pour les vues personnalisées? vous devez inclure les deux constructeurs chaque fois que vous créez une vue personnalisée? (contexte, puis contexte et attributs)
Tim
2
O, aurais dû le voir plus tôt! Le message View is not using the 2- **OR** 3-argument View constructorsest plutôt trompeur.
Attacktive
45

@Tim - Les deux constructeurs ne sont pas obligatoires, seul le ViewClassName(Context context, AttributeSet attrs )constructeur est nécessaire. J'ai découvert cela de manière douloureuse, après des heures et des heures de temps perdu.

Je suis très nouveau dans le développement Android, mais je suppose ici que c'est peut-être dû au fait que puisque nous ajoutons la Viewclasse personnalisée dans le fichier XML, nous lui définissons plusieurs attributs dans le XML, ce qui nécessite à traiter au moment de l'instanciation. Une personne bien plus informée que moi pourra cependant éclairer plus clairement cette question.

KVNam
la source
Cela a du sens, mon TextView personnalisé est toujours construit avec ViewClassName (contexte de contexte, AttributeSet attrs) lorsque je définis des attributs pour lui dans le xml. Si je l'instancie sans le définir dans le fichier xml, le constructeur régulier est appelé avec uniquement le contexte, ViewClassName (contexte de contexte). Je me demandais ce que faisait l'autre constructeur et selon ceci: stackoverflow.com/a/4022916/1505341 réponse, il est censé être utilisé pour définir un style de base pour la vue.
Kerem
19

Une autre cause possible du message "Erreur de gonflage de la classe" peut être une faute d'orthographe du nom complet du package là où il est spécifié en XML:

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

L'ouverture de votre fichier XML de mise en page dans l'éditeur XML Eclipse devrait mettre en évidence ce problème.

rmtheis
la source
2
C'était en effet le correctif de mon application. com.zerokol.views.joystickview Devenu com.zerokol.views.JoystickView Et cela a fonctionné!
Andy
vrai. Vérifiez l'orthographe ou essayez de travailler en utilisant les intentions fournies par votre IDE, commencez simplement par taper le nom de votre package et toutes vos classes disponibles seront affichées sous les intentions.
Khay
c'était mon cas.
Banee Ishaque K
2

Il est important d'écrire le chemin de classe complet dans le xml. J'ai eu 'Erreur lors du gonflage de la classe' lorsque seul le nom de la sous-classe était écrit.

Mykola
la source
C'est très similaire à ce que propose @rmtheis. Il vaut peut-être mieux commenter sa réponse ou même la modifier avec des informations supplémentaires.
Ilia Barahovski
1

J'ai eu cette erreur qui me tourmentait ces dernières heures. Il s'avère que j'avais ajouté la bibliothèque de vue personnalisée en tant que module dans Android Studio, mais j'avais négligé de l'ajouter en tant que dépendance dans l'application build.gradle.

dependencies {
    ...
    compile project(':gifview')
}
Ionoclast Brigham
la source
1

fwiw , j'ai reçu cette erreur en raison d'une initialisation personnalisée dans le constructeur essayant d'accéder à un objet nul.

Tom Howard
la source
0

J'ai eu le même problème d'extension d'un TextEdit. Pour moi, l'erreur a été de ne pas ajouter «public» au constructeur. Dans mon cas, cela fonctionne même si je ne définis qu'un seul constructeur, celui avec des arguments Contextet AttributeSet. Le truc filaire est que le bug ne se révèle que lorsque je construis un APK (chanté ou non) et que je le transfère sur les appareils. Lorsque l'application est exécutée via AndroidStudio -> RunApp sur un appareil connecté USB, l'application fonctionne.

Nicola Mingotti
la source
0

dans mon cas, j'ai ajouté une telle ressource cyclique:

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

puis changé en

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

et ça a marché

Evgenii Vorobei
la source
0

Dans mon cas, j'ai copié ma classe ailleurs et je n'ai pas remarqué tout de suite que c'était une abstractclasse. Vous ne pouvez pas gonfler les classes abstraites.

ÉsaïeJ
la source
0

La chose à comprendre ici est que:

Le constructeur ViewClassName(Context context, AttributeSet attrs )est appelé lors du gonflement du customView via xml. Vous voyez que vous n'utilisez pas le nouveau mot-clé pour instancier votre objet, c'est-à-dire que vous ne le faites pas new GhostSurfaceCameraView(). En faisant cela, vous appelez le premier constructeur ie public View (Context context).

Alors que lorsque vous gonflez la vue à partir de XML, c'est-à-dire lors de l'utilisation setContentView(R.layout.ghostviewscreen);ou de l'utilisation findViewById, vous, NON, pas vous! , le système Android appelle le ViewClassName(Context context, AttributeSet attrs )constructeur.

Ceci est clair à la lecture de la documentation: "Constructeur qui est appelé lors du gonflement d'une vue à partir de XML." Voir: https://developer.android.com/reference/android/view/View.html#View(android.content.Context,%20android.util.AttributeSet)

Par conséquent, n'oubliez jamais le polymorphisme de base et n'oubliez jamais de lire la documentation. Cela évite une tonne de maux de tête.

kush
la source