Как правильно наполнить XML-Layout-File внутри CustomGroup?

Я хочу раздуть XML-Layout-File в пользовательском классе ViewGroup, моя проблема в том, что он создает только пустой экран. Выполнение этого же действия в классе активности отлично работает. Вот мой простой XML-Layout-File:

shownumberlayout.xml: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#FFFFFF" android:id="@+id/layoutForNumber"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tvNumber" android:layout_centerHorizontal="true" android:textColor="#000000" android:text="Test" android:layout_centerVertical="true" android:textSize="30dip"> </TextView> </RelativeLayout> 

Вот рабочая версия, надувающая shownumberlayout.xml в Activity ShowNumber :

 ShowNumber.class public class ShowNumber extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); ViewGroup vg = (ViewGroup) inflater.inflate(R.layout.shownumberlayout, null); setContentView(vg); } } 

Это показывает белый фон с черным текстом «Тест» с центром.

Теперь версия, ViewGroup xml в пользовательской ViewGroup :

 ViewGroup.class public class ViewNumber extends ViewGroup { private LayoutInflater inflater; public ViewNumber(Context context) { super(context); // TODO Auto-generated constructor stub initView(context); } public ViewNumber(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub initView(context); } public ViewNumber(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub initView(context); } private void initView(Context context){ inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.shownumberlayout, null); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub } } 

ShowNumber.class public class ShowNumber extends Activity {/ ** Вызывается, когда действие сначала создается. * /

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewGroup vg = new ViewNumber(this); setContentView(vg); } 

}

Я делаю это в основном как в этом ответе. Это просто создает пустой черный экран. Что я делаю неправильно?

ОБНОВЛЕНИЕ 1

@Konstantin Я применил ваши изменения, но все еще просто пустой экран, я также сделал log-ouput для получения количества детей. Он остается всегда 1, даже я добавляю еще одно Textview в XML-Layout-File. Перед изменениями он всегда остается 0.

 public class ViewNumber extends RelativeLayout { ... private void initView(Context context){ //inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); //inflater.inflate(R.layout.shownumberlayout, null); View.inflate(context, R.layout.shownumberlayout,this); Log.v("ViewNumber", "Number of Child: " + this.getChildCount());//output is 1,before it remains 0 } ... } 

@Sankar Это Logcat, после изменений от Константина:

 12-16 09:24:23.606: DEBUG/AndroidRuntime(8951): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<< 12-16 09:24:23.606: DEBUG/AndroidRuntime(8951): CheckJNI is OFF 12-16 09:24:23.606: DEBUG/dalvikvm(8951): creating instr width table 12-16 09:24:23.656: DEBUG/AndroidRuntime(8951): --- registering native functions --- 12-16 09:24:23.916: DEBUG/AndroidRuntime(8951): Shutting down VM 12-16 09:24:23.916: DEBUG/dalvikvm(8951): Debugger has detached; object registry had 1 entries 12-16 09:24:23.916: INFO/AndroidRuntime(8951): NOTE: attach of thread 'Binder Thread #3' failed 12-16 09:24:24.076: DEBUG/AndroidRuntime(8960): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<< 12-16 09:24:24.076: DEBUG/AndroidRuntime(8960): CheckJNI is OFF 12-16 09:24:24.076: DEBUG/dalvikvm(8960): creating instr width table 12-16 09:24:24.126: DEBUG/AndroidRuntime(8960): --- registering native functions --- 12-16 09:24:24.376: INFO/ActivityManager(78): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.customview.harold/.ShowNumber } 12-16 09:24:24.426: DEBUG/AndroidRuntime(8960): Shutting down VM 12-16 09:24:24.426: DEBUG/jdwp(8960): Got wake-up signal, bailing out of select 12-16 09:24:24.426: DEBUG/dalvikvm(8960): Debugger has detached; object registry had 1 entries 12-16 09:24:24.456: INFO/AndroidRuntime(8960): NOTE: attach of thread 'Binder Thread #3' failed 12-16 09:24:24.456: VERBOSE/ViewNumber(8923): Number of Child: 1 12-16 09:24:24.496: VERBOSE/RenderScript_jni(164): surfaceDestroyed 12-16 09:24:24.526: INFO/ActivityManager(78): Displayed activity org.customview.harold/.ShowNumber: 104 ms (total 104 ms) 12-16 09:24:24.576: DEBUG/dalvikvm(158): GC_FOR_MALLOC freed 10631 objects / 526248 bytes in 52ms 12-16 09:24:34.606: DEBUG/dalvikvm(164): GC_EXPLICIT freed 1776 objects / 106960 bytes in 91ms 

ОБНОВЛЕНИЕ 2

Содержимое окончательно отображается правильно. onLayout было переопределение метода onLayout (спасибо Franco ) в RelativeLayout-Sublcass:

 public class ViewNumber extends RelativeLayout { ... @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub for(int i = 0 ; i < getChildCount() ; i++){ getChildAt(i).layout(l, t, r, b); } } ... } 

Примечание. Позже вы также должны переопределить метод onMeasurement() , но в настоящее время содержимое также отображается правильно, не переопределяя его.

Теперь решение для метода initView от Franco не выравнивает TextView в Центре, а помещает его в верхний левый угол. Решение Константина правильно помещает его в Центр просмотра:

 public class ViewNumber extends RelativeLayout { ... private void initView(Context context){ View.inflate(context, R.layout.shownumberlayout,this); } ... } 

Solutions Collecting From Web of "Как правильно наполнить XML-Layout-File внутри CustomGroup?"

Вы попробовали это?

 private void initView(Context context){ inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.addView(inflater.inflate(R.layout.shownumberlayout, null)); } 

EDIT: я отвечаю быстро … ViewGroup несет ответственность за подготовку макета для своих детей, в методе макета попробуйте это:

  @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub for(int i = 0 ; i < getChildCount() ; i++){ getChildAt(i).layout(l, t, r, b); } } 

Я не знаю, что происходит в этих ответах. Я думаю, что вызов onLayout вручную немного сумасшедший.

Функция LayoutInflater.inflate довольно проста. Если вы используете тот, который принимает третий логический аргумент (attachToRoot), и это правда , он добавит представления из вашего XML в родительское представление (второй аргумент). Если вы используете тот, который принимает только 2 аргумента, он передаст true для attachToRoot по умолчанию, если вы предоставите родительский элемент, который не является нулевым .

В любом случае, большая часть беспорядка, который вы испытываете, связана с тем, что представления из вашего XML добавляются в ваш пользовательский вид. Поскольку ваш XML имеет корень RelativeLayout а ваш пользовательский вид также является RelativeLayout вы получаете относительный макет внутри относительного макета.

Это, вероятно, не то, что вы хотите.

Ответ, данный Константином, имеет смысл, но вы теряете представление, потому что вы размещаете RelativeLayout внутри FrameLayout . Поскольку Android не может содержать слишком много вложенных представлений, рекомендуется оптимизировать и не добавлять лишний FrameLayout .

Я предлагаю сохранить ваше собственное представление как RelativeLayout и изменить ваш корень XML на <merge> . Затем используйте форму раздувания, которая добавляет представления XML вашему родителю – например View.inflate(context,int,this)

Цель <merge> – пропустить корневой узел в XML. Посмотрите его.

Ваш макет не завышен нигде .. сделайте, чтобы ваш ViewNumber расширял FrameLayout и раздувал его:

 public class ViewNumber extends FrameLayout { public ViewNumber(Context context) { super(context); initView(context); } public ViewNumber(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public ViewNumber(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); } private void initView(Context context){ View.inflate(context, R.layout.shownumberlayout, this); //correct way to inflate.. } } 

UPD: Также вам не нужно переопределять метод onLayout, который выглядит очень некорректно .. по крайней мере, вызовите super.onLayout () с самого начала:

 @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); } 

Попробуй это:

  LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE ); inflater.inflate( R.layout.login_view_layout, null ); 

Переопределение onLayout необходимо. Когда вы создаете объект ViewNumber ( ViewGroup vg = new ViewNumber(this) ), это похоже на раздувание xml:

 <ViewNumber I have no child :( </ViewNumber> 

Поэтому, если вы не переопределяете onLayout , onLayout onLayout не может найти никакого дочернего onLayout , тогда он будет пустым.

 @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); } 

После переопределения он будет использовать метод onLayout родителя ViewNumber, если ваши коды:

 public class ViewNumber extends RelativeLayout { ... private void initView(Context context){ View.inflate(context, R.layout.shownumberlayout,this); } ... } 

То это похоже на раздувание xml ниже

  <RelativeLayout <RelativeLayout your xml file /> </RelativeLayout> 

Есть еще один RelativeLayout. Чтобы справиться с этим, вы можете написать:

 public class ViewNumber extends RelativeLayout { ... private void initView(Context context){ inflater.inflate( R.layout.login_view_layout, null ); //change (..,this) to (..,null) } ... } 

Однако произойдет что-то неожиданное. android:layout_xxx=".." вашего xml-файла может измениться (вот почему ваш текст помещен в левый верхний угол). Чтобы узнать больше и лучшее решение, вы можете увидеть комментарий talkol и комментарий fgeorgiew под ним 🙂