Как правильно раздуть XML-макет-файл внутри пользовательской ViewGroup?
я хочу раздуть XML-макет-файл в пользовательском классе ViewGroup, моя проблема заключается в том, что он создает только пустой экран. Делать то же самое в классе Activity работает отлично.
Вот мой простой XML-макет-файл:
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 в деятельности 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);
}
}
это показывает белый фон с черным текстом "тест" по центру.
теперь версия раздувая 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.класс
ShowNumber общественный класс расширяет активность {
/ * * Вызывается при первом создании действия. * /
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewGroup vg = new ViewNumber(this);
setContentView(vg);
}
}
я делаю это в основном, как в этом ответе объяснил.
Это просто производит пустой черный экран. Что я делаю не так?
обновление 1
@Konstantin
Я применил ваши изменения, но все еще просто пустой экран, я также сделал вход-выход для получения количества детей. Он остается всегда 1, даже я добавляю еще один Textview в XML-Layout-файл. Перед изменениями он всегда остается 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);
}
...
}
5 ответов:
вы пробовали это?
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вручную немного сумасшедший.The
LayoutInflater.inflateфункция довольно прямо вперед. Если вы используете тот, который принимает 3-й логический аргумент (attachToRoot), и это правда, он добавит представления из вашего XML в родительское представление (2-й аргумент). Если вы используете тот, который принимает только 2 аргумента, это пройдет правда чтобы attachToRoot по умолчанию, если вы предоставляете родитель, который не null.в любом случае, большая часть беспорядка, который вы испытываете, заключается в том, что представления из вашего XML добавляются в ваше пользовательское представление. Так как ваш XML имеет
RelativeLayoutroot и ваш пользовательский вид также являетсяRelativeLayout- вы получаете относительный макет внутри относительного макета.это, наверное, не то, что вы хотите.
ответ, данный Константином, имеет смысл, но вы теряете представление, потому что вы размещаете а
RelativeLayoutвнутриFrameLayout. Поскольку Android не может содержать слишком много вложенных представлений, рекомендуется оптимизировать и не добавлять это ненужноеFrameLayout.Я предлагаю сохранить ваш пользовательский вид как
RelativeLayoutи изменение корня XML на<merge>. Затем используйте форму inflate, которая добавляет 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,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 совле этого, вы можете написать:
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комментарий под ней:)
Comments