2009-05-04 16 views
23

Ich verwende eine benutzerdefinierte Titelansicht in meiner Anwendung für jede Aktivität. In einer der Aktivitäten muss ich basierend auf Schaltflächenklicks die benutzerdefinierte Titelansicht ändern. Das funktioniert jetzt jedes Mal, wenn ich einen Anruf bei setFeatureInt mache.Android - benutzerdefinierte Titelansicht zur Laufzeit ändern

Wenn ich jedoch versuche, Elemente im benutzerdefinierten Titel zu aktualisieren (z. B. den Text einer Schaltfläche oder eine Textansicht im Titel ändern), findet das Update nicht statt.

Debugging durch den Code zeigt, dass die Textansicht und Schaltflächen Instanzen nicht null sind und ich kann auch die benutzerdefinierte Titelleiste sehen. Der Text in der Textansicht oder der Schaltfläche wird jedoch nicht aktualisiert. Hat jemand anderes dieses Problem konfrontiert? Wie löse ich es?

Danke.

EDIT

Hier ist, was ich versuchte. Wird auch beim Aufruf von postInvalidate nicht aktualisiert.

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(); 
+0

Siehe diese für alternative Lösung http://StackOverflow.com/Questions/8634319/How-to-set-different-title-for-alert-dialog-when-Webview-page-is-loaded/9394561#9394561 – Sameer

Antwort

30

Das Problem ist, dass die einzige Window Implementierung (PhoneWindow) mit einem in seiner LayoutInflatersetFeatureInt Methode verwendet und instanziiert das neue Layout mit inflate und attachToRoot=true. Wenn Sie also setFeatureInt aufrufen, werden die neuen Layouts nicht ersetzt sondern angefügt an den internen Titelcontainer und damit übereinander gezeichnet.

Sie können dies umgehen, indem Sie die folgende Hilfsmethode anstelle von setFeatureInt verwenden. Der Helfer entfernt einfach alle Ansichten aus den internen Titel Containern vor der neue benutzerdefinierten Titel-Funktion festgelegt ist:


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

Ich bin nicht sicher, ob das aktuelle setFeatureInt Verhalten bestimmt ist, aber es ist sicherlich nicht dokumentiert die ein oder andere weshalb ich dies auf den android-Entwickler nehmen würde;)

EDIT

Wie in den Kommentaren darauf hingewiesen, ist die bereits erwähnte Problemumgehung nicht ideal. Anstatt sich auf die Konstante com.android.internal.R.id.title_container zu verlassen, könnten Sie einfach den alten benutzerdefinierten Titel verstecken, wenn Sie einen neuen setzen.

Nehmen wir an, Sie haben zwei benutzerdefinierte Titellayouts:

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

und

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

und Sie ersetzen möchten custom_title_1 mit custom_title_2, Sie ehemalige und setFeatureInt verwenden verstecken konnte letzteres hinzuzufügen:

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

Was ist, wenn einer dieser Werte (title_container, com.android.internal) in den späteren Versionen? Wird sich das nicht auf die App auswirken? – lostInTransit

+1

Sie haben absolut recht. Obwohl es unwahrscheinlich ist, dass sich die com.android.internal.title_container-Konstante ändert, ist es falsch, sich darauf zu verlassen. Dies ist ein hässlicher Workaround im besten Fall. –

+0

Danke. Diese andere Lösung funktioniert großartig. Aber ich verstehe wirklich nicht, warum setFeatureInt Ansichten übereinander hinzufügen sollte, anstatt sie zu ersetzen? Esp mit Ansichten, die einzigartig sein müssen - wie der Titel! – lostInTransit

0

Rufen Sie invalidate oder postInvalidate auf, um die Ansicht nach dem Aktualisieren des Textes neu zu zeichnen? Wenn es sich um eine benutzerdefinierte Ansicht handelt, können Sie einen Haltepunkt in den Zeichencode einfügen, um sicherzustellen, dass er aufgerufen wird?

Wenn Sie im UI-Thread sind, können Sie 'invalidate' aufrufen, wenn nicht, Sie müssen 'postInvalidate' aufrufen oder die Ansicht wird nicht neu gezeichnet.

+0

Wenn es hilft, wird die Ansicht neu gezeichnet, denn ich sehe die aktualisierte Titelleiste, aber die Steuerelemente in der Titelleiste ändern sich nicht – lostInTransit

0

Nur Mein 2c Wert:

Wenn Sie in MapActivity arbeiten, wurde beim Anfordern eines benutzerdefinierten Titels kein Titel angezeigt.

Zum Glück war alles was ich tun wollte, anders den Titeltext zu setzen, und ich erkannte bald, dass setTitle nur anrufen() innerhalb von onCreate() arbeitete für mich (ich es nannte, nachdem ich setContentView() aufgerufen)

Entschuldigung, aber ich habe gerade keine Zeit, um dies noch einmal zu debuggen und herauszufinden, warum das, was ich getan habe, nicht funktioniert hat, und warum es geändert hat, dass es funktioniert. Wie ich schon sagte, dachte nur, dass dies jemandem helfen könnte.

13

Der richtige Weg, dies zu tun, ist wie folgt:

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

Bitte beachten Sie, dass die Reihenfolge dieser Aussagen sehr wichtig ist.

Wenn Sie super.onCreate() vor einer der anderen Anweisungen aufrufen, erhalten Sie eine leere Titelleiste, die der Hack, die Titelleisten-ID zu finden und alle Ansichten daraus zu entfernen, repariert, aber nicht empfohlen wird.

+0

OP versucht, die Titelleiste während der Laufzeit nach onCreate() zu ändern. – CACuzcatlan

Verwandte Themen