Обновление значков Android Tab

У меня есть активность, которая имеет TabHost, содержащую набор TabSpecs, каждый из которых имеет список, содержащий элементы, которые будут отображаться на вкладке. Когда каждый TabSpec создается, я устанавливаю значок, который будет отображаться в заголовке вкладки.

TabSpecs создаются таким образом внутри метода setupTabs(), который создает петли для создания соответствующего количества вкладок:

TabSpec ts = mTabs.newTabSpec("tab");
ts.setIndicator("TabTitle", iconResource);

ts.setContent(new TabHost.TabContentFactory(
{
    public View createTabContent(String tag)
    {
        ... 
    }            
});
mTabs.addTab(ts);

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

mTabs.getTabWidget().removeAllViews();
mTabs.clearAllTabs(true);
setupTabs();

Есть ли способ заменить значок, который отображается без удаления и повторного создания всех вкладок?

Ответ 1

Короткий ответ: вы ничего не пропустили. Android SDK не предоставляет прямого метода для изменения индикатора TabHost после его создания. TabSpec используется только для создания вкладки, поэтому изменение TabSpec после того, как факт не будет иметь эффекта.

Я думаю, что есть обходной путь. Вызовите mTabs.getTabWidget(), чтобы получить объект TabWidget. Это всего лишь подкласс ViewGroup, поэтому вы можете вызвать getChildCount() и getChildAt() для доступа к отдельным вкладкам в TabWidget. Каждая из этих вкладок также представляет собой представление, а в случае вкладок с графическим индикатором и текстовой меткой почти наверняка есть еще один ViewGroup (возможно, LinearLayout, но это не имеет значения), который содержит ImageView и a TextView. Поэтому, немного поиграв с отладчиком или Log.i, вы сможете найти рецепт, чтобы получить ImageView и изменить его напрямую.

Недостатком является то, что если вы не будете осторожны, то точное расположение элементов управления на вкладке может измениться, и ваше приложение может сломаться. Ваше первоначальное решение, возможно, более надежное, но опять же это может привести к другим нежелательным побочным эффектам, таким как проблески или проблемы с фокусом.

Ответ 2

Просто для подтверждения ответа доминикана, вот его решение в коде (что на самом деле работает):

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        if (TAB_MAP.equals(tabId)) {
            ImageView iv = (ImageView) tabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.icon);
            iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_map_black));
            iv = (ImageView) tabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.icon);
            iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_list_white));
        } else if (TAB_LIST.equals(tabId)) {
            ImageView iv = (ImageView) tabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.icon);
            iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_map_white));
            iv = (ImageView) tabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.icon);
            iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_list_black));
        }
    }
});

Конечно, он вообще не отполирован, и использование этих прямых индексов в getChildAt() не является приятным вообще...

Ответ 5

Попробуйте следующее:

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        if (TAB_MAP.equals(tabId)) {
            ImageView iv = (ImageView) tabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.icon);
            iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_map_black));
            iv = (ImageView) tabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.icon);
            iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_list_white));
        } else if (TAB_LIST.equals(tabId)) {
            ImageView iv = (ImageView) tabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.icon);
            iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_map_white));
            iv = (ImageView) tabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.icon);
            iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_list_black));
        }
    }
});

Ответ 6

Это то, что я сделал, и это работает для меня. Я создал эту функцию в активности, которая простирается от TabBarActivity

public void updateTab(int stringID) {
    ViewGroup identifyView = (ViewGroup)getTabWidget().getChildAt(0);
    TextView v =  (TextView)identifyView.getChildAt(identifyView.getChildCount() - 1);
    v.setText(stringID);
}

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

Я вызвал эту функцию из соответствующего действия, используя этот вызов

getParent().updateTab(R.string.tab_bar_analyze);