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

Я хочу раздуть 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);
    }
}

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

Теперь версия раздувает xml в пользовательском ViewGroup -Class:

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 расширяет действие {   /** Вызывается, когда действие сначала создается. */

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

}

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

ОБНОВЛЕНИЕ 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 (благодаря Франко) в 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 от Франко не выравнивает TextView в Центре, а помещает его в верхний левый угол. Решение из Константин корректно помещает его в Центр просмотра:

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

Ответ 1

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

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

Ответ 2

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

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

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

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

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

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

Цель тега <merge> - пропустить корень node в XML. Посмотрите его.

Ответ 3

Ваш макет не завышен нигде.. сделайте свой 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);
}

Ответ 4

Попробуйте следующее:

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

Ответ 5

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

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

поэтому, если вы не переопределяете onLayout, ViewNumber 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.To sovle this, вы можете написать:

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:)