Android TabWidget обнаруживает нажатие на текущую вкладку

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

Я пробовал этот способ (среди нескольких других) без успеха.

public void onTabChanged(String tabId) {
    Log.d(this.getClass().getName(), ">>>>>>>>>>>>>>>>>>>>>>>> tabId: " + tabId);

    int tabs = getTabWidget().getChildCount();
    Log.d(this.getClass().getName(), "tabs: " + tabs);
    for(int i=0; i<tabs; i++){
        View tab = getTabWidget().getChildAt(i);
        if(i==tabHost.getCurrentTab()){
            Log.d(this.getClass().getName(), "tab: " + i);
            tab.setOnClickListener(this);
        }else{
            tab.setOnClickListener(null);
            tab.getOnFocusChangeListener();
        }
    }   
}

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

Есть идеи снаружи?


person 0m4r    schedule 02.12.2010    source источник
comment
Я пытаюсь найти способ запустить событие onclick на вкладке, когда эта вкладка является текущей вкладкой. -- это не очень поддающийся обнаружению шаблон пользовательского интерфейса. Пользователи не ожидают, что нажатие на текущую вкладку что-то сделает. Я призываю вас пересмотреть свой подход.   -  person CommonsWare    schedule 02.12.2010
comment
Я согласен с вами, мой клиент не доза :/   -  person 0m4r    schedule 03.12.2010
comment
у меня похожая ситуация, когда на каждой вкладке есть инструкции для пользователя, и я хочу, чтобы они могли снова щелкнуть вкладку, чтобы снова показать направления. я предполагаю, что это необычная схема, но это единственная, о которой я подумал, чтобы сделать направления легко просматриваемыми   -  person dylan murphy    schedule 21.09.2011
comment
Попробовав большинство решений в этой теме, я, наконец, решил эту проблему всего за 5 минут, используя этот ответ.   -  person Hugo Matilla    schedule 18.07.2012


Ответы (8)


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

getTabHost().setOnTabChangedListener(new OnTabChangeListener() {

@Override
public void onTabChanged(String tabId) {

int i = getTabHost().getCurrentTab();
 Log.i("@@@@@@@@ ANN CLICK TAB NUMBER", "------" + i);

    if (i == 0) {
            Log.i("@@@@@@@@@@ Inside onClick tab 0", "onClick tab");

    }
    else if (i ==1) {
            Log.i("@@@@@@@@@@ Inside onClick tab 1", "onClick tab");
    }

  }
});
person Chirag_CID    schedule 13.10.2011
comment
Это не решает проблему OP: это вызывается только при изменении вкладки, а не при нажатии на ту же вкладку. - person dhaag23; 23.08.2012
comment
Спасибо, чувак, ты помог мне закончить один долгий и безумный проект. - person IamStalker; 21.04.2013
comment
@Chirag_CID отличный ответ :-), я застрял последние 3 дня, и этот ответ решил мою конкретную проблему;) - person Zubair Ahmed; 24.11.2013
comment
@ dhaag23 dhaag23: Вы должны отключить текущую вкладку, чтобы избежать повторного нажатия. Это было бы более знакомо с пользователями. - person Huy Tower; 28.12.2016
comment
@TranDucHuy - отключенная вкладка может быть не тем, чего хотят или ожидают пользователи - все зависит от варианта использования, и, как я уже упоминал, это не то, о чем просили. - person dhaag23; 29.12.2016

После долгих раздумий решение оказалось проще, чем я думал. Что я сделал, так это просто создал новый дочерний класс, который расширяет TabHost и переопределяет метод setCurrentTab следующим образом:

package com.mycompany.Views;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.TabHost;
import android.widget.Toast;

public class ReclickableTabHost extends TabHost {

    public ReclickableTabHost(Context context) {
        super(context);
    }

    public ReclickableTabHost(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setCurrentTab(int index) {
        if (index == getCurrentTab()) {
            // FIRE OFF NEW LISTENER
        } else {
            super.setCurrentTab(index);
        }
    }
}

Чтобы использовать новый класс вместо типичного TabHost, просто отредактируйте XML-файл макета с помощью:

<FrameLayout
    android:layout_height="match_parent"
    android:layout_width="0dip"
    android:layout_weight=".8">

    <com.myCompany.Views.ReclickableTabHost
        android:id="@android:id/tabhost"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/tab_unselected_holo"/>
            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
            </FrameLayout>

        </LinearLayout>

    </com.myCompany.Views.ReclickableTabHost>

Надеюсь это поможет...

person SteveBorkman    schedule 15.02.2012
comment
Кажется самым надежным решением. Спасибо, Стив. - person dhaag23; 23.08.2012
comment
Отличный ответ. Я добавил public interface OnReClickListener { public void onReClick(int index); } an и ivar private OnReClickListener onReClickListener; (плюс геттеры и сеттеры), а также этот код для запуска слушателя: if (null != onReClickListener) { onReClickListener.onReClick(index);} Надеюсь, это поможет. - person Moritz; 14.06.2013
comment
Также важно добавить проверку isShown() перед уведомлением слушателя. Поскольку Android вызывает setCurrentTab, если пользователь блокирует/разблокирует устройство. - person Oleksandr; 31.08.2015

Я думаю, что нашел решение, вот пример кода:

    intent = new Intent(this, HomeGroup.class);
    View tab1 = _inflater.inflate(R.layout.custom_tab_1,null);
    homeTab.setTag("Tab1");
    spec = tabHost.newTabSpec("Tab1").setIndicator(tab1).setContent(intent);
    tabHost.addTab(spec);

    View tab2 = _inflater.inflate(R.layout.custom_tab_2,null);
    homeTab.setTag("Tab2");
    spec = tabHost.newTabSpec("Tab2").setIndicator(tab2).setContent(intent);
    tabHost.addTab(spec);

    View tab3 = _inflater.inflate(R.layout.custom_tab_3,null);
    homeTab.setTag("Tab3");
    spec = tabHost.newTabSpec("Tab3").setIndicator(tab3).setContent(intent);
    tabHost.addTab(spec);

    tabHost.setOnTabChangedListener(this);

    //click on seleccted tab
    int numberOfTabs = tabHost.getTabWidget().getChildCount();
    for(int t=0; t<numberOfTabs; t++){
        tabHost.getTabWidget().getChildAt(t).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(event.getAction()==MotionEvent.ACTION_UP){

                    String currentSelectedTag = MainTab.this.getTabHost().getCurrentTabTag();
                    String currentTag = (String)v.getTag();
                    Log.d(this.getClass().getSimpleName(), "currentSelectedTag: " + currentSelectedTag + " currentTag: " + currentTag);
                    if(currentSelectedTag.equalsIgnoreCase(currentTag)){
                        MainTab.this.getTabHost().setCurrentTabByTag(currentTag);
                        String newSelectedTabTag = MainTab.this.getTabHost().getCurrentTabTag();
                        if(newSelectedTabTag.toLowerCase().indexOf("tab1")!=-1){
                            //do smthg
                        }else if(newSelectedTabTag.toLowerCase().indexOf("tab1")!=-1){
                            //do smthg
                        }else if(newSelectedTabTag.toLowerCase().indexOf("tab3")!=-1){
                            //do smthg
                        }
                        return true;
                    }
                }
                return false;
            }
        });
    }       

Вероятно, это можно улучшить, но это работает для меня!

person 0m4r    schedule 04.02.2011
comment
v.getTag() возвращает null для меня. - person neobie; 08.06.2013
comment
@ 0m4r ........ вы можете изучить этот вопрос ..... stackoverflow.com/q/19269322/2825729 - person ; 09.10.2013
comment
@ 0m4r - Подскажите, пожалуйста, на что ссылается homeTab? - person Ria; 08.11.2013
comment
@Ria homeTab — это представление, которое отображается, когда я нажимаю кнопку вкладки (вероятно, в приведенном выше фрагменте тот факт, что у меня более одного homeTab, является ошибкой cut&past....) - person 0m4r; 08.11.2013
comment
@ 0m4r - Спасибо, чувак. - person Ria; 11.11.2013

Уродливое исправление: В onClickListener поместите: tabHost.SetCurrentTab(OtherTab); tabHost.SetCurrentTab(CurrentTab); Где для индекса вкладки «Другое» я использую свой самый простой вид на вкладках.

P.S. Клиенты всегда хотят, чтобы их приложения отличались :)

Это код, который я использую (у меня есть только 2 вкладки Tab1 и Tab2):

 getTabWidget().getChildAt(1).setOnClickListener(new OnClickListener() { 
            @Override 
            public void onClick(View v) { 

                Log.d(TAG,"1"+getTabHost().getCurrentTabTag());

                if (getTabHost().getCurrentTabTag().equals("Tab2")) { 
                    Log.d(TAG,"2");

                    tabHost.setCurrentTab(0);                                    
                    tabHost.setCurrentTab(1);

                } else {
                    tabHost.setCurrentTab(1);
                }
            } 
        });
person Lyubomir Todorov    schedule 03.12.2010
comment
что вы имеете в виду под «Где для индекса вкладки «Другие» я использую свой самый простой вид на вкладках? - person 0m4r; 04.12.2010
comment
Я пробовал ваше решение, но у меня все еще есть проблема, заключающаяся в том, что переопределяя событие onClick по умолчанию на вкладке, я переопределяю поведение по умолчанию... и устанавливая для него значение null, удаляю событие onClick вообще.... так что, спасибо за вашу помощь, но я думаю, что не смогу использовать ваше решение, если я не перепишу все событие onClick для вкладки:/ - person 0m4r; 05.12.2010
comment
полезно с двумя вкладками, с более чем двумя я бы не знал, как с этим справиться :) Но все равно спасибо! - person 0m4r; 23.12.2010
comment
вместо этого переопределите onTouchListener и верните false внутри onTouch. Использование onClick приведет к тому, что вкладки перестанут меняться - person Jimmar; 27.09.2014

Проблема здесь в том, что setOnTabChangedListener не срабатывает при нажатии на выбранную вкладку, и если вы установите OnClickListener на вкладке, вы потеряете нормальное поведение вкладки.

Таким образом, простое решение - поместить OnClickListener на вкладку, а внутри нее программно установить, что это текущая вкладка.

С TabHost:

getTabWidget().getChildAt(0).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // custom code
        tabHost.setCurrentTab(0);                                    
    }
});

С TabLayout

tabLayout.getTabAt(0)setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                    // custom code
                    TabLayout.Tab tab  = tabLayout.getTabAt(0);
                    tab.select();
                }
            }
        });
person ElYeante    schedule 24.02.2016

Если вы хотите попробовать android.support.design.widget.TabLayout, вы можете сделать это следующим образом:

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
   @Override public void onTabSelected(Tab tab) {

   }

   @Override public void onTabUnselected(Tab tab) {

   }

   @Override public void onTabReselected(Tab tab) {

   }
});
person Yuchen    schedule 09.12.2016
comment
Привет, @AmiAram, спасибо за ваше редактирование. К сожалению, не прошло. Но это хорошее предложение, и я изменил свой ответ на него! - person Yuchen; 09.03.2017

Это работает для меня...

TabHost host = (TabHost)findViewById(R.id.tabHost);

host.setOnTabChangedListener(new OnTabChangeListener() {
    @Override
    public void onTabChanged(String tabId) {

        int i = host.getCurrentTab();

        if (i == 0) {
             // your method 1
        }
        else if (i ==1) {
            // your method 2
        }
    }
});
person Ms. Sonia    schedule 23.12.2017

Если у вас есть собственный макет вкладок, вам может потребоваться добавить это в свой собственный вид, это решило мою проблему:

android:duplicateParentState="true"
person ODAXY    schedule 28.04.2017