2009-05-04 3 views
23

Я использую пользовательский заголовок в своем приложении для каждого действия. В одном из действий, основанном на нажатиях кнопок, мне нужно изменить пользовательский вид заголовка. Теперь это прекрасно работает при каждом вызове setFeatureInt.Android - изменение пользовательского заголовка во время выполнения

Но если я попытаюсь обновить любые элементы в настраиваемом заголовке (скажем, измените текст кнопки или текстовое представление заголовка), обновление не произойдет.

Отладка с помощью кода показывает, что экземпляры текстового вида и кнопки не являются нулевыми, и я также могу видеть настраиваемую строку заголовка. Но текст в текстовом представлении или кнопке не обновляется. Кто-нибудь еще столкнулся с этой проблемой? Как его разрешить?

Спасибо.

EDIT

Вот что я пытался. Не обновляется даже при вызове 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(); 
+0

См. Это альтернативное решение http://stackoverflow.com/questions/8634319/how-to-set-different-title-for-alert-dialog-when-webview-page-is-loaded/9394561#9394561 – Sameer

ответ

30

Проблема заключается в том, что единственный Window реализации (PhoneWindow) использует в своем методе setFeatureInt с LayoutInflater и инициализирует новый макет с inflate и attachToRoot=true. Следовательно, когда вы звоните setFeatureInt, новые макеты не заменены, но прикреплены к внутреннему контейнеру заголовка и, таким образом, нарисованы друг над другом.

Вы можете обойти это, используя следующий вспомогательный метод вместо setFeatureInt. Помощник просто удаляет все виды из внутреннего контейнера заголовка, прежде чем новая функция пользовательского названия устанавливается:


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

Я не уверен, предназначено ли текущий setFeatureInt поведения, но это, конечно, не документирован, так или другой, поэтому я возьму это на андроид дэвов;)

EDIT

Как было отмечено в комментариях, вышеупомянутый способ не идеален. Вместо того, чтобы полагаться на константу com.android.internal.R.id.title_container, вы могли бы просто скрыть старый пользовательский заголовок всякий раз, когда вы устанавливаете новый.

Предположим, у вас есть два заказных макетов название:

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

и

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

и вы хотите заменить custom_title_1 с custom_title_2, вы можете скрыть бывший и использовать setFeatureInt добавить последний:

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

Что делать, если какое-либо из этих значений (title_container, com.android.internal) в более поздних версиях? Не повлияет ли это на приложение? – lostInTransit

+1

Вы абсолютно правы. Несмотря на то, что константа com.android.internal.title_container вряд ли изменится, неправильно полагаться на нее. В лучшем случае это уродливое обходное решение. –

+0

Спасибо. Это другое решение отлично работает. Но я действительно не понимаю, почему setFeatureInt должен добавлять представления один над другим, а не заменять их? Esp с представлениями, которые должны быть сингулярными - как название! – lostInTransit

0

Вы вызываете invalidate или postInvalidate, чтобы перерисовать вид после обновления текста? Если это пользовательский вид, можете ли вы поместить контрольную точку в код розыгрыша, чтобы убедиться, что он вызван?

Если вы находитесь в потоке пользовательского интерфейса, вы можете позвонить 'invalidate', если вы этого не сделали, вы должны называть 'postInvalidate' или представление не будет перерисовываться.

+0

Если это помогает, представление перерисовывается, я вижу обновленную строку заголовка, но элементы управления в строке заголовка не изменяются. – lostInTransit

0

Просто мой 2c стоит:

При работе в MapActivity, запрашивая собственное название, не было видно никакого названия.

К счастью, все, что я хотел сделать, чтобы установить текст заголовка по-разному, и вскоре я понял, что просто звоню SETTITLE() внутри OnCreate() работал для меня (я назвал это после того, как я назвал setContentView())

Извините, но у меня нет времени прямо сейчас, чтобы отладить это и выяснить, почему то, что я делаю, не работает, и почему его изменение заставило его работать. Как я уже сказал, просто подумал, что это может помочь кому-то по дороге.

13

Правильный способ сделать это состоит в следующем:

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

Пожалуйста, обратите внимание, что порядок этих утверждений является очень важным.

Если вы вызываете super.onCreate() перед любым из других утверждений, вы получите пустую строку заголовка, в которой взломать идентификатор заголовка и удалить все его виды будет исправлена, но не рекомендуется.

+0

OP пытается изменить строку заголовка во время выполнения, после onCreate(). – CACuzcatlan

Смежные вопросы