Question

J'utilise une vue de titre personnalisée dans mon application pour chaque activité. Dans l'une des activités, en fonction des clics de bouton, je dois modifier l'affichage du titre personnalisé. Maintenant, cela fonctionne bien chaque fois que je fais un appel à setFeatureInt.

Mais si j'essaie de mettre à jour des éléments du titre personnalisé (par exemple, modifier le texte d'un bouton ou une vue de texte sur le titre), la mise à jour n'a pas lieu.

Le débogage via le code indique que les occurrences de la vue texte et des boutons ne sont pas nulles et que je peux également voir la barre de titre personnalisée. Mais le texte sur la vue texte ou le bouton n'est pas mis à jour. Quelqu'un at-il fait face à ce problème? Comment puis-je le résoudre?

Merci.

MODIFIER

Voici ce que j'ai essayé. Ne reçoit pas de mise à jour même en appelant postInvalidate.

    getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.text_title);

    TextView databar = (TextView) findViewById(R.id.title_text);
    databar.setText("Some Text");
    databar.postInvalidate();

    Button leftButton = (Button) findViewById(R.id.left_btn);
    leftButton.setOnClickListener(mLeftListener);
    leftButton.setText("Left Btn");
    leftButton.postInvalidate();

    Button rightBtn = (Button) findViewById(R.id.right_btn);
    rightBtn.setOnClickListener(mRightListener);
    rightBtn.postInvalidate();
Était-ce utile?

La solution

Le problème est que le seul Fenêtre implementation ( PhoneWindow ) utilise un LayoutInflater dans sa méthode setFeatureInt et instancie la nouvelle présentation avec gonfle et attachToRoot = true . Par conséquent, lorsque vous appelez setFeatureInt , les nouvelles dispositions ne sont pas remplacées , mais attachées au conteneur de titre interne et sont donc superposées.

Vous pouvez contourner ce problème en utilisant la méthode d'assistance suivante au lieu de setFeatureInt . L'assistant supprime simplement toutes les vues du conteneur de titre interne avant que la nouvelle fonctionnalité de titre personnalisé ne soit définie:


private void setCustomTitleFeatureInt(int value) {
    try {
        // retrieve value for com.android.internal.R.id.title_container(=0x1020149)
        int titleContainerId = (Integer) Class.forName(
            "com.android.internal.R$id").getField("title_container").get(null);

        // remove all views from titleContainer
        ((ViewGroup) getWindow().findViewById(titleContainerId)).removeAllViews();

        // add new custom title view 
        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, value);

    } catch(Exception ex) {
        // whatever you want to do here..
    }
}

Je ne sais pas si le comportement actuel de setFeatureInt est prévu, mais il n'est certainement pas documenté d'une manière ou d'une autre, c'est pourquoi je vais en parler aux développeurs Android;)

MODIFIER

Comme indiqué dans les commentaires, la solution de contournement susmentionnée n’est pas idéale. Au lieu de compter sur la constante com.android.internal.R.id.title_container , vous pouvez simplement masquer l'ancien titre personnalisé chaque fois que vous en définissez un nouveau.

Supposons que vous avez deux dispositions de titre personnalisées:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/custom_title_1" ...

et

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/custom_title_2" ...

et que vous souhaitez remplacer custom_title_1 par custom_title_2 , vous pouvez masquer l'ancien et utiliser setFeatureInt pour ajouter ce dernier:

findViewById(R.id.custom_title_1).setVisibility(View.GONE);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_2);

Autres conseils

La bonne façon de procéder est la suivante:

requestWindowFeature( Window.FEATURE_CUSTOM_TITLE );
setContentView( R.layout.my_layout );
getWindow().setFeatureInt( Window.FEATURE_CUSTOM_TITLE, R.layout.my_custom_title );
super.onCreate( savedInstanceState );

Veuillez noter que l'ordre de ces déclarations est très important.

Si vous appelez super.onCreate () avant l'une des autres instructions, vous obtiendrez une barre de titre vide. Le fait de chercher l'identifiant de la barre de titre et de supprimer toutes les vues de celui-ci corrigera mais n'est pas recommandé.

Appelez-vous invalidate ou postInvalidate pour redessiner la vue après la mise à jour du texte? S'il s'agit d'une vue personnalisée, pouvez-vous insérer un point d'arrêt dans le code de tirage pour vous assurer qu'il s'appelle?

Si vous êtes sur le fil de l'interface utilisateur, vous pouvez appeler "invalidate" si vous ne l'êtes pas, vous devez appeler "postInvalidate", sinon la vue ne se redessinra pas.

Juste ma valeur 2c:

Lorsque vous travaillez dans MapActivity, la demande d'un titre personnalisé a pour résultat qu'aucun titre n'est affiché.

Heureusement, tout ce que je voulais faire était de définir le texte du titre différemment, et je me suis vite rendu compte que le simple fait d'appeler setTitle () à l'intérieur de onCreate () fonctionnait pour moi (je l'ai appelé après avoir appelé setContentView ())

Désolé, mais je n'ai pas le temps pour le moment de résoudre ce problème et de comprendre pourquoi ce que je faisais n'a pas fonctionné et pourquoi le modifier a permis de le faire fonctionner. Comme je l'ai dit, je pensais que cela pourrait aider quelqu'un sur la route.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top