2014-05-13 4 views
1

Я создаю настраиваемый составной макет, который состоит из интерактивного горизонтального LinearLayout, который содержит ImageView и два TextViews. В конечном итоге я хочу иметь возможность ссылаться на всю вещь, используя одно поле, и добавлять, вычитать и редактировать их для моей активности в зависимости от активности пользователя. Я использую XML-ресурс, который я раздуваю в конструкторе. Однако мой телефон думает, что я создаю LinearLayout и я получаю следующее сообщение об ошибке при попытке реализовать пользовательский класс:Android: Пользовательский составной класс, расширяющий LinearLayout, думает, что это LinearLayout

D/ConnectionButton﹕ Ready to inflate 
D/ConnectionButton﹕ constructor 2 
D/AndroidRuntime﹕ Shutting down VM 
W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x417be898) 
E/AndroidRuntime﹕ FATAL EXCEPTION: main 
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.exampleapp.app/com.exampleapp.app.ManageFriends}: android.view.InflateException: Binary XML file line #3: Error inflating class com.exampleapp.utils.ConnectionButton 

В, когда я устанавливаю NameText ошибки. Если я оставлю эту строку из него работает, но мой позже Log говорит мне андроид думает, что это LinearLayout, не ConnectionButton

Так вот мой класс определение ConnectionButton:

public class ConnectionButton extends LinearLayout { 
    ImageView IconView; 
    TextView NameView; 
    TextView StatusView; 

    public ConnectionButton(Context context) { 
     super(context); 
     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     Log.d("ConnectionButton","Ready to inflate"); 
     addView(inflater.inflate(R.layout.connection_row, null)); 
     Log.d("ConnectionButton","Inflated"); 
     IconView = (ImageView) findViewById(R.id.icon); 
     NameView = (TextView) findViewById(R.id.name); 
     StatusView = (TextView) findViewById(R.id.status); 
    } 

    public ConnectionButton (Context context, AttributeSet attrs) { 
     super(context, attrs); 
     Log.d("ConnectionButton","constructor 2"); 
/*  LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     Log.d("ConnectionButton","Ready to inflate"); 
     addView(inflater.inflate(R.layout.connection_row, null)); 
     Log.d("ConnectionButton","Inflated");*/ 
     IconView = (ImageView) this.findViewById(R.id.icon); 
     NameView = (TextView) this.findViewById(R.id.name); 
     StatusView = (TextView) this.findViewById(R.id.status); 
     NameView.setText("From Constructor 2"); 
    } 
} 

Вот мой XML ресурс:

<com.exampleapp.utils.ConnectionButton xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="50dp" 
    android:orientation="horizontal" 
    android:clickable="true" 
    style="@android:style/Widget.Button"> 
     <ImageView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_gravity="left" 
      android:adjustViewBounds="true" 
      android:paddingRight="5dp" 
      android:id="@+id/icon"/> 
     <TextView 
      android:layout_width="0dp" 
      android:layout_height="wrap_content" 
      android:textSize="16sp" 
      android:layout_weight="2" 
      android:id="@+id/name"/> 
     <TextView 
      android:layout_width="0dp" 
      android:layout_height="wrap_content" 
      android:textSize="16sp" 
      android:layout_weight="1" 
      android:id="@+id/status"/> 
</com.exampleapp.utils.ConnectionButton> 

И вот где я его создаю: (NB ConnectionList - это существующий вертикальный LinearLayout, который должен содержать эти объекты)

LinearLayout box = (LinearLayout)findViewById(R.id.ConnectionList); 
    LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    Log.d("ConnectionButton","Ready to inflate"); 
    View CBv = inflater.inflate(R.layout.connection_row, box); 
    Log.d("CBv class",CBv.getClass().toString()); 

ответ

2

Вы принимаете неверное предположение о том, что надувной элемент. В соответствии с документацией он возвращает:

Корневой вид завышенной иерархии. Если был установлен корневой каталог, это корневой вид; в противном случае это корень завышенного XML-файла.

Так что в вашем случае CBv является LinearLayout, потому что это то, что является родителем. Чтобы получить доступ к вашему виду, просто используйте findViewById.

+0

Как я упоминал в своем комментарии к BladeCoder, эта рекурсия не вызывается. Реальный вопрос, почему Android распознает его как LinearLayout вместо моего пользовательского класса? – Scott

+0

О, я думаю, я вижу, что происходит. Вы пытаетесь получить доступ к дочернему элементу в конструкторе макета, но он еще не создан. – anakin78z

+0

Хорошо, теперь, когда это выяснилось, я отправил фактический ответ, который вы искали :-P – anakin78z

0

Я думаю, что вы пытаетесь надуть ConnectionButton внутри конструктора ConnectionButton который представляет рекурсивную проблему.

Я предлагаю вам изменить ConnectionButton, чтобы он наследовал от FrameLayout вместо этого (поскольку у вас есть только один дочерний корень) и измените корневой тип его содержимого макета XML на LinearLayout. Тогда ваш контроль будет расширенным FrameLayout, который содержит один LinearLayout.

+0

О, я оставил это в первом конструкторе, вы правы. Но на втором - это комментарий, который называется надувным устройством. Если ConnectionButton расширяет FrameLayout, и у меня было несколько его экземпляров, было бы тогда несколько FrameLayouts, каждый из которых выбирал один LinearLayout и в этом 3 других представлениях? – Scott

+0

Я думал, что вы используете элемент управления в обратном порядке: создаете его по коду и заставляете его раздувать свой собственный макет. Если вы позволите надувнику раздуть ваш контроль, проблема в том, что дочерние представления добавляются после вызова конструктора, поэтому они еще не доступны в конструкторе, и вы получите исключение NullPointerException при попытке установить текст в «NameView», , Ссылка на дочерние представления позже, например, в onFinishInflate(). – BladeCoder

+0

Да, я открыт в любом случае. Раньше я программировал простые пользовательские классы. Это первый раз, когда я использовал расширитель XML, и я до сих пор не обволакиваю его полностью. Я еще не нашел документацию, которая дает полный пример, просто бит и куски для конкретных ситуаций.(как этот :)) – Scott

Смежные вопросы