【问题标题】:TabLayout tab selectionTabLayout 选项卡选择
【发布时间】:2015-08-28 02:07:09
【问题描述】:

我应该如何以编程方式在 TabLayout 中选择一个选项卡?

 TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
 tabLayout.setupWithViewPager(viewPager);

【问题讨论】:

    标签: android android-viewpager android-tablayout android-design-library


    【解决方案1】:

    如果您知道要选择的选项卡的索引,则可以这样做:

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    TabLayout.Tab tab = tabLayout.getTabAt(someIndex);
    tab.select();
    

    即使您在没有 ViewPager 的情况下单独使用 TabLayout 时,这种技术也有效(这是非典型的,可能是不好的做法,但我已经看到它完成了)。

    【讨论】:

    • 此解决方案仅适用于已将选项卡添加到操作栏的情况,但情况并非总是如此。从TabLayout.Tab.select()“文档中选择此选项卡。只有在动作栏中添加了选项卡时才有效。” i> span>
    • @DanielKvist,实际上文档本身是不正确的。源代码不言自明。这个答案应该是公认的答案。
    • @JasonSparc 嗯,我记得上次尝试此解决方案时它对我不起作用,但我会看看是否可以检查它是否适合我。你有没有尝试过?它可能在某些情况下有效,而在其他情况下则无效?它可能取决于 API 级别或类似的东西?
    • 感谢您在半熟的答案中清除空气!因为这在独立的 TabLayout 上不起作用,可能是因为您所说的原因;它适用于操作栏中的选项卡!
    • 为什么在没有 ViewPager 的情况下使用 TabLayout 应该被视为不好的做法?
    【解决方案2】:

    这可能不是最终解决方案,并且它要求您将TabLayoutViewPager 一起使用,但我是这样解决的:

    void selectPage(int pageIndex)
    {
        viewPager.setCurrentItem(pageIndex);
        tabLayout.setupWithViewPager(viewPager);
    }
    

    我测试了使用此代码对性能的影响有多大在我自己的页面之间(使用滑动手势),并且差异不是很大,所以至少它不是一个可怕的解决方案......

    希望这对某人有所帮助!

    【讨论】:

    • 当我执行 dap 的解决方案 (tabLayout.setScrollPosition(pageIndex,0f,true);) 时,当我单击右侧的选项卡时,它没有更新 ViewPager 的页面(我不知道为什么)。只有单击左侧选项卡然后再次单击右侧选项卡才能最终将页面更新为具有右侧选项卡的页面,这非常有问题。但是这个解决方案没有故障。
    【解决方案3】:

    我就是这样解决的:

    void selectPage(int pageIndex){
        tabLayout.setScrollPosition(pageIndex,0f,true);
        viewPager.setCurrentItem(pageIndex);
    }
    

    【讨论】:

    • 选择的答案对我不起作用,但这个对我有用。
    • 很好的解决方案!对我来说工作得很好,当我需要移回第一页时 viewPager 和 TabView
    • 有风险的一面。它可以防止创建其他选项卡。
    【解决方案4】:

    如果您不能使用 tab.select() 并且不想使用 ViewPager,您仍然可以以编程方式选择一个选项卡。如果您通过TabLayout.Tab setCustomView(android.view.View view) 使用自定义视图,则更简单。这是两种方式的方法。

    // if you've set a custom view
    void updateTabSelection(int position) {
        // get the position of the currently selected tab and set selected to false
        mTabLayout.getTabAt(mTabLayout.getSelectedTabPosition()).getCustomView().setSelected(false);
        // set selected to true on the desired tab
        mTabLayout.getTabAt(position).getCustomView().setSelected(true);
        // move the selection indicator
        mTabLayout.setScrollPosition(position, 0, true);
    
        // ... your logic to swap out your fragments
    }
    

    如果您不使用自定义视图,那么您可以这样做

    // if you are not using a custom view
    void updateTabSelection(int position) {
        // get a reference to the tabs container view
        LinearLayout ll = (LinearLayout) mTabLayout.getChildAt(0);
        // get the child view at the position of the currently selected tab and set selected to false
        ll.getChildAt(mTabLayout.getSelectedTabPosition()).setSelected(false);
        // get the child view at the new selected position and set selected to true
        ll.getChildAt(position).setSelected(true);
        // move the selection indicator
        mTabLayout.setScrollPosition(position, 0, true);
    
        // ... your logic to swap out your fragments
    }
    

    使用 StateListDrawable 在选定和未选定的可绘制对象或类似的东西之间切换,以使用颜色和/或可绘制对象做你想做的事情。

    【讨论】:

      【解决方案5】:

      默认情况下,如果您选择一个选项卡,它将突出显示。如果要显式选择意味着将 onTabSelected(TabLayout.Tab tab) 下的给定注释代码与您指定的选项卡索引位置一起使用。此代码将解释使用 viewpager 更改选项卡所选位置的片段。

      public class GalleryFragment extends Fragment implements TabLayout.OnTabSelectedListener 
      {
      private ViewPager viewPager;public ViewPagerAdapter adapter;private TabLayout tabLayout;
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
                               Bundle savedInstanceState) {
      View rootView = inflater.inflate(R.layout.fragment_gallery, container, false);
      viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
      adapter = new ViewPagerAdapter(getChildFragmentManager());
      adapter.addFragment(new PaymentCardFragment(), "PAYMENT CARDS");
      adapter.addFragment(new LoyaltyCardFragment(), "LOYALTY CARDS");
      viewPager.setAdapter(adapter);
      tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
          tabLayout.setupWithViewPager(viewPager);
          tabLayout.setOnTabSelectedListener(this);
      }
      
      @Override
      public void onTabSelected(TabLayout.Tab tab) {
          //This will be called 2nd when you select a tab or swipe using viewpager
          final int position = tab.getPosition();
          Log.i("card", "Tablayout pos: " + position);
          //TabLayout.Tab tabdata=tabLayout.getTabAt(position);
          //tabdata.select();
          tabLayout.post(new Runnable() {
              @Override
              public void run() {
                  if (position == 0) {
                      PaymentCardFragment paymentCardFragment = getPaymentCardFragment();
                      if (paymentCardFragment != null) {
                         VerticalViewpager vp = paymentCardFragment.mypager;
                          if(vp!=null)
                          {
                            //vp.setCurrentItem(position,true);
                            vp.setCurrentItem(vp.getAdapter().getCount()-1,true);
                          }
                        }
                  }
                  if (position == 1) {
                     LoyaltyCardFragment loyaltyCardFragment = getLoyaltyCardFragment();
                      if (loyaltyCardFragment != null) {
                         VerticalViewpager vp = loyaltyCardFragment.mypager;
                          if(vp!=null)
                          {
                              vp.setCurrentItem(position);
                          }
                        }
                  }
              }
          });
      }
      
      @Override
      public void onTabUnselected(TabLayout.Tab tab) {
       //This will be called 1st when you select a tab or swipe using viewpager
      }
      @Override
      public void onTabReselected(TabLayout.Tab tab) {
        //This will be called only when you select the already selected tab(Ex: selecting 3rd tab again and again)
      }
       private PaymentCardFragment getLoyaltyCardFragment() {
          Fragment f = adapter.mFragmentList.get(viewPager.getCurrentItem());
      
         if(f instanceof PaymentCardFragment)
         {
          return (PaymentCardFragment) f;
         }
         return null;
       }
      private LoyaltyCardFragment getPaymentCardFragment() {
          Fragment f = adapter.mFragmentList.get(viewPager.getCurrentItem());
          if(f instanceof LoyaltyCardFragment)
         {
          return (LoyaltyCardFragment) f;
         }
         return null;
       }
        class ViewPagerAdapter extends FragmentPagerAdapter {
         public List<Fragment> mFragmentList = new ArrayList<>();
          private final List<String> mFragmentTitleList = new ArrayList<>();
         public void addFragment(Fragment fragment, String title) {
         mFragmentList.add(fragment);
         mFragmentTitleList.add(title);
        }
       }
      }
      

      【讨论】:

        【解决方案6】:

        使用这个:

        tabs.getTabAt(index).select();
        

        请记住,如果 currentTabIndex 和 index 相同,那么这会将您的流程发送到 onTabReselected 而不是 onTabSelected。

        【讨论】:

        • 谢谢,对于我的实施来说,这是一个安全的解决方案
        • Objects.requireNonNull(tabs.getTabAt(position)).select(); 使用安全
        • 请记住,如果 currentTabIndex 和 index 相同,那么这会将您的流程发送到 onTabReselected 而不是 onTabSelected。
        • @WilliaanLopes,这不会保护你免受 NPI 的伤害,只会尽快扔掉它
        【解决方案7】:

        为您的浏览器添加:

         viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        
                    @Override
                    public void onPageSelected(int position) {
                        array.clear();
                        switch (position) {
                            case 1:
                                //like a example
                                setViewPagerByIndex(0);
                                break;
                        }
                    }
        
                    @Override
                    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                    }
        
                    @Override
                    public void onPageScrollStateChanged(int state) {
                    }
                });
        

        //on 处理程序以防止崩溃内存不足

        private void setViewPagerByIndex(final int index){
            Application.getInstance().getHandler().post(new Runnable() {
                @Override
                public void run() {
                    viewPager.setCurrentItem(index);
                }
            });
        }
        

        【讨论】:

        • “防止崩溃内存不足” - 为什么我们需要单独的线程来选择当前项目?
        【解决方案8】:

        试试这个

            new Handler().postDelayed(
                    new Runnable(){
                        @Override
                        public void run() {
                            if (i == 1){
                                tabLayout.getTabAt(0).select();
                            } else if (i == 2){
                                tabLayout.getTabAt(1).select();
                            }
                        }
                    }, 100);
        

        【讨论】:

        • 谢谢。它对我有用。但是使用延迟是一种好习惯吗?
        • 我猜如果假设您从后端服务器获取选项卡的文本并且如果 b'coz 出于任何原因服务器延迟然后这个系统线程在任何布局上运行线程是不好的会不必要地消耗您的设备资源。
        • 这么丑的解决方案
        • 这对我不起作用。如果用户单击一个选项卡,我该如何做到这一点,然后延迟该选项卡的选择?我什么都做不了。我尝试了 if i ==1 来使用 (mV​​iewPager.getCurrentItem()==0) 但它不起作用,其他任何东西都没有。
        【解决方案9】:

        使用这个:

        <android.support.design.widget.TabLayout
            android:id="@+id/patienthomescreen_tabs"
            android:layout_width="match_parent"
            android:layout_height="72sp"
            app:tabGravity="fill"
            app:tabMode="fixed"
            app:tabIndicatorColor="@android:color/white"
            app:tabSelectedTextColor="@color/green"/>
        

        在 OnClickListener 之后:

        TabLayout tabLayout = (TabLayout) findViewById(R.id.patienthomescreen_tabs);
        TabLayout.Tab tab = tabLayout.getTabAt(someIndex);
        tab.select();
        

        请记住,如果 currentTabIndex 和 index 相同,那么这会将您的流程发送到 onTabReselected 而不是 onTabSelected。

        【讨论】:

        • 如果tabMode是可滚动的呢?
        • 我也这么认为,请先试试看。
        【解决方案10】:

        am 使用 TabLayout 来切换片段。它在大多数情况下都有效,除非每当我尝试使用tab.select() 以编程方式选择选项卡时,我的TabLayout.OnTabSelectedListener 会触发onTabSelected(TabLayout.Tab tab),这会让我很伤心。我正在寻找一种在不触发侦听器的情况下进行编程选择的方法。

        所以我改编了@kenodoggy 的回答来适应我的使用。我还面临一些内部对象将返回 null 的问题(因为它们尚未创建,因为我从我的片段中回答onActivityResult(),如果活动是singleTask,它发生在onCreate() 之前或singleInstance) 所以我写了一个详细的if/else 序列,它会报告错误并在没有NullPointerException 否则会触发的情况下失败。如果您不使用 Log.e() 的替代品,我会使用 Timber 进行日志记录。

        void updateSelectedTabTo(int position) {
            if (tabLayout != null){
                int selected = tabLayout.getSelectedTabPosition();
                if (selected != -1){
                    TabLayout.Tab oldTab = tabLayout.getTabAt(0);
                    if (oldTab != null){
                        View view = oldTab.getCustomView();
                        if (view != null){
                            view.setSelected(false);
                        }
                        else {
                            Timber.e("oldTab customView is null");
                        }
                    }
                    else {
                        Timber.e("oldTab is null");
                    }
                }
                else {
                    Timber.e("selected is -1");
                }
                TabLayout.Tab newTab = tabLayout.getTabAt(position);
                if (newTab != null){
                    View view = newTab.getCustomView();
                    if (view != null){
                        view.setSelected(false);
                    }
                    else {
                        Timber.e("newTab customView is null");
                    }
                }
                else {
                    Timber.e("newTab is null");
                }
            }
            else {
                Timber.e("tablayout is null");
            }
        }
        

        这里,tabLayout 是绑定到我的 XML 中的 TabLayout 对象的内存变量。而且我不使用滚动标签功能,所以我也删除了它。

        【讨论】:

          【解决方案11】:

          你可以尝试用这个解决它:

          TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
          tabLayout.setupWithViewPager(mViewPager);
          
          TabLayout.Tab tab = tabLayout.getTabAt(pos);
          if (tab != null) {
              tab.select();
          }
          

          【讨论】:

            【解决方案12】:

            这也有帮助

            viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageScrolled(int i, float v, int i1) {
                }
            
                @Override
                public void onPageSelected(int i) {
                    tablayout.getTabAt(i).select();
                }
            
                @Override
                public void onPageScrollStateChanged(int i) {
                }
            });
            

            【讨论】:

              【解决方案13】:

              只需设置viewPager.setCurrentItem(index),关联的 TabLayout 就会选择相应的选项卡。

              【讨论】:

              • 这对我不起作用。我不得不使用 .post 方法。
              【解决方案14】:

              您可以使用以下函数设置 TabLayout 位置

              public void setTab(){
               tabLayout.setScrollPosition(YOUR_SCROLL_INDEX,0,true);
               tabLayout.setSelected(true);
              }
              

              【讨论】:

                【解决方案15】:

                如果您的默认选项卡是第一个(0)并且您恰好切换到片段,那么您必须第一次手动替换片段。这是因为在注册监听器之前选择了选项卡。

                private TabLayout mTabLayout;
                
                ...
                
                @Override
                public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                    View view = inflater.inflate(R.layout.fragment_tablayout, container, false);
                    mTabLayout = view.findViewById(R.id.sliding_tabs);
                    mTabLayout.addOnTabSelectedListener(mOnTabSelectedListener);
                
                    getActivity().getSupportFragmentManager().beginTransaction()
                        .replace(R.id.tabContent, MyFirstFragment.newInstance()).commit();
                    return view;
                }
                

                或者,您可以考虑像这样调用getTabAt(0).select() 并覆盖onTabReselected

                @Override
                public void onTabReselected(TabLayout.Tab tab) {
                    // Replace the corresponding tab fragment.
                }
                

                这会起作用,因为您实际上是在每次重新选择选项卡时替换片段。

                【讨论】:

                  【解决方案16】:

                  如果你有理解困难,这段代码可以帮助你

                  private void MyTabLayout(){
                      TabLayout.Tab myTab = myTabLayout.newTab(); // create a new tab
                      myTabLayout.addTab(myTab); // add my new tab to myTabLayout
                      myTab.setText("new tab"); 
                      myTab.select(); // select the new tab
                  }
                  

                  您也可以将其添加到您的代码中:

                  myTabLayout.setTabTextColors(getColor(R.color.colorNormalTab),getColor(R.color.colorSelectedTab));
                  

                  【讨论】:

                    【解决方案17】:

                    试试这个方法。

                    tabLayout.setTabTextColors(getResources().getColor(R.color.colorHintTextLight),
                                               getResources().getColor(R.color.colorPrimaryTextLight));
                    

                    【讨论】:

                      【解决方案18】:

                      如果你使用没有 viewPager 的 TabLayout 这会有所帮助

                       mTitles = getResources().getStringArray(R.array.tabItems);
                          mIcons = getResources().obtainTypedArray(R.array.tabIcons);
                          for (int i = 0; i < mTitles.length; i++) {
                      
                              tabs.addTab(tabs.newTab().setText(mTitles[i]).setIcon(mIcons.getDrawable(i)));
                              if (i == 0) {
                                  /*For setting selected position 0 at start*/
                                  Objects.requireNonNull(Objects.requireNonNull(tabs.getTabAt(i)).getIcon()).setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary), PorterDuff.Mode.SRC_IN);
                              }
                          }
                      
                          tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                              @Override
                              public void onTabSelected(TabLayout.Tab tab) {
                                  Objects.requireNonNull(tab.getIcon()).setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary), PorterDuff.Mode.SRC_IN);
                              }
                      
                              @Override
                              public void onTabUnselected(TabLayout.Tab tab) {
                                  Objects.requireNonNull(tab.getIcon()).setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.white), PorterDuff.Mode.SRC_IN);
                              }
                      
                              @Override
                              public void onTabReselected(TabLayout.Tab tab) {
                      
                              }
                          });
                      

                      【讨论】:

                        【解决方案19】:

                        有点晚,但可能是一个有用的解决方案。 我在 Fragment 中直接使用 TabLayout 并尝试在 Fragment 的生命周期的早期选择一个选项卡。 对我有用的是等到 TabLayout 使用android.view.View#post 方法完成其子视图的绘制。即:

                        int myPosition = 0;
                        myFilterTabLayout.post(() -> { filterTabLayout.getTabAt(myPosition).select(); });
                        

                        【讨论】:

                        • 正确答案对我有用,但一些延迟会给它带来很好的效果new Handler().postDelayed(()-&gt;{ tabLayout.post(() -&gt; { tabLayout.getTabAt(myPosition).select(); }); },200);
                        • @Hisham,我不喜欢编码中的延迟钩子。不幸的是,这是唯一安全的方法。主要是 Pager2..
                        【解决方案20】:

                        不同答案的组合解决方案是:

                        new Handler().postDelayed(() -> {
                          myViewPager.setCurrentItem(position, true);
                          myTabLayout.setScrollPosition(position, 0f, true);
                        },
                        100);
                        

                        【讨论】:

                          【解决方案21】:

                          你应该使用 viewPager 来使用 viewPager.setCurrentItem()

                           viewPager.setCurrentItem(n);
                           tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                                      @Override
                                      public void onTabSelected(TabLayout.Tab tab) {
                                          viewPager.setCurrentItem(tab.getPosition());
                                      }
                          
                                      @Override
                                      public void onTabUnselected(TabLayout.Tab tab) {
                                      }
                          
                                      @Override
                                      public void onTabReselected(TabLayout.Tab tab) {
                          
                                      }
                                  });
                          

                          【讨论】:

                            【解决方案22】:

                            使用Material Components Library 提供的TabLayout 只需使用selectTab 方法:

                            TabLayout tabLayout = findViewById(R.id.tab_layout);
                            tabLayout.selectTab(tabLayout.getTabAt(index));
                            

                            它需要 1.1.0 版本。

                            【讨论】:

                            • 不,selectTab 是包私有方法。
                            • @xyuber.com 我添加了一个重要信息。它需要版本 1.1.0。方法是public now
                            • 索引在哪里??
                            【解决方案23】:

                            Kotlin 修复

                            viewPager.currentItem = 0

                            tabs.setupWithViewPager(viewPager)

                            【讨论】:

                              【解决方案24】:
                              TabLayout jobTabs = v.findViewById(R.id.jobTabs);
                              ViewPager jobFrame = v.findViewById(R.id.jobPager);
                              jobFrame.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(jobTabs));
                              

                              这将选择标签作为查看寻呼机滑动页面

                              【讨论】:

                                【解决方案25】:

                                如果您将 TabLayout 与 viewPager 一起使用,那么这会对您有所帮助。您在 addOnpagelistener 中使用 ViewPager 设置 TabLayout。

                                如果你想直接设置 TabLayout 的位置(不是点击单独的 Tab)试试下面的代码tabLayout.getTabAt(position_you_want_to_set).select()

                                   /* will be invoked whenever the page changes or is incrementally scrolled*/
                                    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                                        @Override
                                        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                                
                                        }
                                
                                        @Override
                                        public void onPageSelected(int position) {
                                            tabLayout.getTabAt(position).select();
                                        }
                                
                                        @Override
                                        public void onPageScrollStateChanged(int state) {
                                
                                        }
                                    });
                                

                                【讨论】:

                                • 欢迎来到 StackOverflow!虽然答案可能是正确的,但您应该解释提供的代码如何解决声明的问题
                                【解决方案26】:

                                这不适用于已实现 ViewPager2 的应用,为此,您需要使用

                                viewPager2.setCurrentItem(position);
                                

                                onConfigureTabonConfigureTab 中,如果我们使用 TabLayoutMediator 时发现的

                                TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(
                                                tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
                                            @Override
                                            public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                                                switch (position){
                                                    case 0 : tab.setIcon(getResources().getDrawable(R.drawable.camera));
                                                            break;
                                                    case 1 : tab.setText("CHAT");
                                                            viewPager2.setCurrentItem(position); // when app starts this will be the selected tab
                                                            break;
                                                    case 2 : tab.setText("STATUS");
                                                            break;
                                                    case 3 : tab.setText("CALL");
                                                        break;
                                                }
                                            }
                                        }
                                        );
                                        tabLayoutMediator.attach();
                                

                                【讨论】:

                                  【解决方案27】:

                                  Kotlin 用户:

                                  Handler(Looper.getMainLooper()).postDelayed(
                                              { tabLayout.getTabAt(position).select() }, 100
                                          )
                                  

                                  如果需要滚动,这也会滚动您的标签布局。

                                  【讨论】:

                                    猜你喜欢
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2015-12-15
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2015-08-25
                                    • 2015-09-28
                                    • 1970-01-01
                                    • 1970-01-01
                                    相关资源
                                    最近更新 更多