Ошибка надувания при расширении класса

188

Я пытаюсь создать собственный вид, GhostSurfaceCameraViewкоторый расширяетSurfaceView . Вот мой файл определения класса

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

И это в моем ghostviewscreen.xml:

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

Теперь в деятельности я сделал:

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

Когда setContentView()вызывается, выдается исключение:

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

Может кто-нибудь сказать мне, почему я получаю эту ошибку? Спасибо.

eccentricbiped
источник

Ответы:

369

Я думаю, я понял, почему это не работает. Я предоставлял конструктор только для случая с одним параметром context, когда я должен был предоставить конструктор для случая с двумя параметрами Context, AttributeSet. Мне также нужно было предоставить конструктору (-ам) публичный доступ. Вот мое исправление:

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
источник
4
Иногда самые простые вещи могут быть проблемой :) Приятно знать, что оба параметра используются для надувания.
Warpzit
5
Спасибо!! Нигде в примерах я не смог найти упоминаний о необходимости перегрузки всех конструкторов! Вы сэкономили мне часы (дни?) Времени.
Скотт Биггс
1
Большое спасибо! Сообщение об ошибке совершенно не определено, что на мгновение поставило меня в тупик, они должны были включить причину (отсутствие перегрузки конструктора) в свое сообщение об ошибке.
AgentKnopf
1
Спасибо за это. Кто-нибудь знает, если это идет через доску для пользовательских представлений? вам нужно включить оба конструктора, когда вы делаете пользовательское представление? (контекст, а затем контекст и атрибуты)
Тим
2
О, должен был увидеть это раньше! Это сообщение View is not using the 2- **OR** 3-argument View constructorsвводит в заблуждение.
Нападение
45

@Tim - Оба конструктора не требуются, необходим только ViewClassName(Context context, AttributeSet attrs )конструктор. Я выяснил это болезненным способом, после нескольких часов потраченного времени.

Я очень новичок в разработке для Android, но я делаю дикое предположение, что это может быть связано с тем, что, поскольку мы добавляем пользовательский Viewкласс в файл XML, мы задаем ему несколько атрибутов в XML, что требует быть обработанным во время создания экземпляра. Кто-то гораздо более знающий, чем я, сможет пролить свет на этот вопрос.

KVNam
источник
Это имеет смысл, мой собственный TextView всегда создается с ViewClassName (Context context, AttributeSet attrs), когда я определяю атрибуты для него в xml. Если я создаю его экземпляр без определения в xml-файле, обычный конструктор вызывается только с контекстом ViewClassName (Context context). Мне было интересно, что делает другой конструктор, и в соответствии с этим: stackoverflow.com/a/4022916/1505341 ответ, он должен использоваться для установки базового стиля для представления.
Керем
19

Другой возможной причиной появления сообщения «Error inflating class» может быть неправильное написание полного имени пакета, указанного в XML:

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

Открытие файла макета XML в редакторе Eclipse XML должно выделить эту проблему.

rmtheis
источник
2
Это действительно было исправлением для моего приложения. com.zerokol.views.joystickview стал com.zerokol.views.JoystickView И это сработало!
Энди
правда. Дважды проверьте орфографию или попробуйте работать, используя намерения, предоставленные вашей IDE, просто начните с ввода имени вашего пакета, и все ваши доступные классы будут показаны под намерениями.
Хай
это был мой случай.
Banee Ishaque K
2

Важно написать полный путь к классу в XML. Я получил сообщение «Ошибка надувания класса», когда в нем было написано только имя подкласса.

Николай
источник
Это очень похоже на то, что предлагает @rmtheis. Возможно, лучше прокомментировать его ответ или даже отредактировать его с дополнительной информацией.
Илья Бараховский
1

Эта ошибка мучила меня последние несколько часов. Оказывается, я добавил пользовательскую библиотеку представлений в качестве модуля в Android Studio, но я забыл добавить ее в качестве зависимости в приложении build.gradle.

dependencies {
    ...
    compile project(':gifview')
}
Ионокласт Бригам
источник
1

Между прочим , я получил эту ошибку из-за некоторой пользовательской инициализации в конструкторе, пытающейся получить доступ к нулевому объекту.

Том Ховард
источник
0

У меня была такая же проблема расширения TextEdit. Для меня ошибка была в том, что я не добавил public в конструктор. В моем случае это работает, даже если я определяю только один конструктор с аргументами Contextи AttributeSet. Дело в том, что ошибка проявляется только тогда, когда я создаю APK (опаленный или нет) и переносу его на устройства. Когда приложение запускается через AndroidStudio -> RunApp на устройстве, подключенном через USB, приложение работает.

Никола Минготти
источник
0

в моем случае я добавил такой циклический ресурс:

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

затем изменился на

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

и это сработало

Евгений Воробей
источник
0

В моем случае я скопировал свой класс откуда-то еще и сразу не заметил, что это был abstractкласс. Вы не можете раздувать абстрактные классы.

IsaiahJ
источник
0

Здесь нужно понять, что:

Конструктор ViewClassName(Context context, AttributeSet attrs )вызывается при накачке customView через xml. Вы видите, что вы не используете новое ключевое слово для создания экземпляра вашего объекта, т.е. вы этого не делаете new GhostSurfaceCameraView(). Делая это вы вызываете первый конструктор ИЭ public View (Context context).

В то время как надувая представление из XML, то есть когда вы используете setContentView(R.layout.ghostviewscreen);или используете findViewById, вы, НЕТ, а не вы! , система Android вызывает ViewClassName(Context context, AttributeSet attrs )конструктор.

Это понятно при чтении документации: «Конструктор, который вызывается при надувании представления из XML». См .: https://developer.android.com/reference/android/view/View.html#View(android.content.Context,%20android.util.AttributeSet)

Следовательно, никогда не забывайте базовый полиморфизм и никогда не забывайте читать документацию. Это экономит тонну головной боли.

Куш
источник