64 votes

Comment gonfler XML-Mise en page-Fichier correctement à l'intérieur de la Coutume ViewGroup?

Je veux gonfler un XML-schéma de Fichier personnalisé dans un ViewGroup Classe, mon Problème est qu'il ne produit qu'un écran vide. Faire de même dans la Classe d'Activité fonctionne très bien. Voici mon XML simple-Mise en page-Fichier:

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>

Ici est la Version de travail, qui gonfle l' shownumberlayout.xml dans l'Activité 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);
    }
}

Cela montre un Fond Blanc avec le Texte noir "Test" centré.

Maintenant, la Version en gonflant le xml dans la Coutume ViewGroup-Classe:

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 s'étend de l'Activité { /** Appelée lorsque l'activité est d'abord créé. */

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

}

Im faire un peu comme dans cette Réponse expliqué. Cette juste produit un Vide Noir de l'Écran. Ce que je fais de mal?

Mise à JOUR 1

@Konstantin J'ai appliqué vos modifications, mais toujours juste un écran blanc, j'ai aussi fait un journal de sortie pour obtenir le nombre d'enfants. Il reste toujours 1, même que j'en ajouter un Textview pour le XML-Mise en page-Fichier. Avant les Modifications, il reste toujours à 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 C'est le Logcat, après les Changements de Konstantin:

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

Mise à JOUR 2

Le Contenu est enfin à afficher correctement. Le manque, c'est de remplacer la Méthode de onLayout (merci à Franco) dans le RelativeLayout-sous-classe:

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

Remarque: plus Tard, vous devriez également de remplacer la Méthode de onMeasurement(), mais actuellement, le contenu est également à montrer correctement sans remplaçant.

Maintenant la solution pour la Méthode initView de Franco ne pas aligner le TextView dans le Centre, mais il met dans le coin en haut à gauche. La solution de Konstantin met correctement dans le Centre de la Vue:

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

48voto

talkol Points 4279

Je ne sais pas ce qui se passe dans ces réponses.. je pense que l'appelant onLayout manuellement est un peu fou.

L' LayoutInflater.inflate fonction est assez simple. Si vous utilisez l'un accepte le 3ème argument booléen (attachToRoot) et c'est vrai, il va ajouter de la vue depuis votre XML à votre vue parent (le 2ème argument). Si vous êtes à l'aide de celui qui n'accepte que les 2 arguments, il va passer le vrai pour attachToRoot par défaut si vous fournissez un parent qui n'est pas null.

En tout cas, la plupart de la pagaille que vous êtes en train de vivre est parce que le point de vue de votre XML sont ajoutés à votre vue personnalisée. Depuis votre XML a un RelativeLayout racine et votre vue personnalisée est également un RelativeLayout - vous avez une relative mise en page à l'intérieur d'une relative mise en page.

Ce n'est probablement pas ce que vous voulez.

La réponse donnée par Konstantin du bon sens, mais vous perdez un point de vue parce que vous n'êtes pas de placer un RelativeLayout à l'intérieur d'un FrameLayout. Depuis Android ne peut pas tenir trop de vues imbriquées, c'est une bonne idée pour optimiser et de ne pas ajouter ce inutiles FrameLayout.

Je suggère de garder votre vue personnalisée en tant que RelativeLayout et l'évolution de votre XML à la racine de <merge>. Ensuite, utilisez le gonfler formulaire qui ajoute les vues XML de votre parent - comme View.inflate(context,int,this)

Le but de l' <merge> balise est de passer le nœud racine dans le XML.. le regarder.

36voto

Konstantin Burov Points 34011

Votre mise en page est gonflé nulle part.. faire votre ViewNumber étendre FrameLayout et de le gonfler en elle:

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: Aussi, vous n'avez pas besoin de remplacer onLayout méthode, qui a l'air très incorrect.. au moins appeler super.onLayout() sur le départ:

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

33voto

Franco Points 3426

Avez-vous essayé?

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

EDIT: je réponds rapidement... une ViewGroup a la responsabilité de préparer la mise en page de leurs enfants, dans la méthode de présentation, essayez ceci:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X