如何自定义单个选项卡? (更改背景颜色、指示器颜色和文本颜色)

Posted

技术标签:

【中文标题】如何自定义单个选项卡? (更改背景颜色、指示器颜色和文本颜色)【英文标题】:How to customize individual tabs? (changing background color, indicator color and text color) 【发布时间】:2014-02-15 14:24:30 【问题描述】:

在此链接中:How do I apply a style programmatically?

Kevin Grant 解释了这个问题,我对他的代码的问题是上下文部分。准确地说:

ctv = new CustomView(context, R.attr.tabStyleAttr);

在这段代码中它说:上下文无法解析为变量

我想将特定样式应用于选项卡,这就是设置主题对我不起作用的原因。当然,我的问题的任何替代方案也是受欢迎的。

我尝试更改操作栏选项卡的背景颜色、指示器颜色和文本颜色。

@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) 

    CustomView ctv;
    ctv = new CustomView(this, R.attr.tabStyleAttr);        
    tab.setCustomView(ctv);  
    mViewPager.setCurrentItem(tab.getPosition());

styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="Theme.Ab" parent="@android:style/Theme.Holo.Light">
        <item name="android:actionBarStyle">@style/abStyle</item> 
        <item name="@attr/actionBarTabStyle">@style/tabStyle</item>        
        <item name="android:actionBarTabTextStyle">@style/tabTextColor</item>
    </style>   

    <style name="abStyle" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">
        <item name="android:background">@drawable/ab_solid_style</item>
        <item name="android:backgroundStacked">@drawable/ab_stacked_solid_style</item>
        <item name="android:backgroundSplit">@drawable/ab_bottom_solid_style</item>
        <item name="android:height">100dp</item>
    </style>    

    <style name="tabStyle" parent="@android:style/Widget.Holo.Light.ActionBar.TabView">

        <item name="android:background">@drawable/tab_indicator_ab_style</item>
    </style>

    <style name="tabTextColor" parent="@android:style/Widget.Holo.Light.ActionBar.TabText">
        <item name="android:textColor">@android:color/white</item>
    </style>



</resources>

MainActivity.java (onCreate)

public void onCreate(Bundle savedInstanceState)
           
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create the adapter that will return a fragment for each of the three primary sections
        // of the app.
        mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());

        // Set up the action bar.
        final ActionBar actionBar = getActionBar();
        //set custom actionbar
        actionBar.setCustomView(R.layout.titlebar);
        //Displays the custom design in the actionbar
        actionBar.setDisplayShowCustomEnabled(true);
        //Turns the homeIcon a View     
        View homeIcon = findViewById(android.R.id.home);
        //Hides the View (and so the icon)
        ((View)homeIcon.getParent()).setVisibility(View.GONE);

        // Specify that we will be displaying tabs in the action bar.
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Set up the ViewPager, attaching the adapter and setting up a listener for when the
        // user swipes between sections.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mAppSectionsPagerAdapter);

        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
                   
            @Override
            public void onPageSelected(int position)
            
                    // When swiping between different app sections, select the corresponding tab.
                    // We can also use ActionBar.Tab#select() to do this if we have a reference to the Tab.
                    actionBar.setSelectedNavigationItem(position);
            
        );

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++)
        

            // Create a tab with text corresponding to the page title defined by the adapter.
            // Also specify this Activity object, which implements the TabListener interface, as the
            // listener for when this tab is selected.
            Tab tab = actionBar.newTab().setText(mAppSectionsPagerAdapter.getPageTitle(i)).setTabListener(this);            
            actionBar.addTab(tab);
        
    

这就是我想做的:


至于使用 Views 的新结果发生了这种情况

MainActivity.java

package com.example.android.effectivenavigation;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MainActivity extends FragmentActivity implements ActionBar.TabListener

    AppSectionsPagerAdapter mAppSectionsPagerAdapter;
    //The viewpager displays on of the section at a time
    ViewPager mViewPager;

    public void onCreate(Bundle savedInstanceState)
           
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create the adapter that will return a fragment for each of the three primary sections
        // of the app.
        mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());

        // Set up the action bar.
        final ActionBar actionBar = getActionBar();
        //set custom actionbar
        actionBar.setCustomView(R.layout.titlebar);
        //Displays the custom design in the actionbar
        actionBar.setDisplayShowCustomEnabled(true);
        //Turns the homeIcon a View     
        View homeIcon = findViewById(android.R.id.home);
        //Hides the View (and so the icon)
        ((View)homeIcon.getParent()).setVisibility(View.GONE);


        // Specify that we will be displaying tabs in the action bar.
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Set up the ViewPager, attaching the adapter and setting up a listener for when the
        // user swipes between sections.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mAppSectionsPagerAdapter);

        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
                   
            @Override
            public void onPageSelected(int position)
            
                    // When swiping between different app sections, select the corresponding tab.
                    // We can also use ActionBar.Tab#select() to do this if we have a reference to the Tab.
                    actionBar.setSelectedNavigationItem(position);
            
        );
       /*final Tab firstTab = actionBar.newTab()
                .setText(mAppSectionsPagerAdapter.getPageTitle(0))
                .setTabListener(this)
                .setCustomView(R.id.nieuws_tab_layout);
        /*final Tab secondTab = actionBar.newTab()
                 .setText(mAppSectionsPagerAdapter.getPageTitle(1))
                 .setCustomView(R.id.nieuws_tab_layout);
        final Tab thirdTab = actionBar.newTab()
                .setText(mAppSectionsPagerAdapter.getPageTitle(2))
                .setCustomView(R.id.nieuws_tab_layout);

        actionBar.addTab(firstTab);
        actionBar.addTab(secondTab);
        actionBar.addTab(thirdTab);*/

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++)
        
            if(i == 0)
            
                final View firstCustomView = new CustomView(this);
                //firstCustomView.setBackgroundColor(Color.BLUE);
                Tab tab = actionBar.newTab().setText(mAppSectionsPagerAdapter.getPageTitle(i)).setTabListener(this).setCustomView(R.layout.nieuws_tab_layout);
                actionBar.addTab(tab);
            
            else
            
            // Create a tab with text corresponding to the page title defined by the adapter.
            // Also specify this Activity object, which implements the TabListener interface, as the
            // listener for when this tab is selected.
            Tab tab = actionBar.newTab().setText(mAppSectionsPagerAdapter.getPageTitle(i)).setTabListener(this);            
            actionBar.addTab(tab);
            
        
    

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) 
    
    

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) 
    
        //CustomView ctv;
        //ctv = new CustomView(context, R.attr.tabStyleAttr);
        // When the given tab is selected, switch to the corresponding page in the ViewPager.
        //LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        //View tabView = inflater.inflate(R.layout.nieuws_tab_layout, null);
        //tabView.setBackgroundColor(0xFF00FF00);
        //tab.setCustomView(tabView);  
        mViewPager.setCurrentItem(tab.getPosition());
    

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
    
    

    public static class AppSectionsPagerAdapter extends FragmentPagerAdapter 
    
        public AppSectionsPagerAdapter(FragmentManager fm)
        
            super(fm);
        

        @Override
        public Fragment getItem(int i) 
        
            switch (i)
            
                case 0:
                    // The first section of the app is the most interesting -- it offers
                    // a launchpad into the other demonstrations in this example application.
                    return new LaunchpadSectionFragment();

                default:
                    // The other sections of the app are dummy placeholders.
                    Fragment fragment = new DummySectionFragment();
                    Bundle args = new Bundle();
                    args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1);
                    fragment.setArguments(args);
                    return fragment;
            
        

        @Override
        public int getCount()
        
            return 3;
        

        @Override
        public CharSequence getPageTitle(int position) 
        
            switch(position)
            
                case 0:
                
                    return "Tab1";
                
                case 1:
                
                    return "Tab2";
                
                case 2:
                
                    return "Tab3";
                
                default:
                
                    return "Section " + (position + 1);
                
            
        
    
    public static class LaunchpadSectionFragment extends Fragment
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
        
            View rootView = inflater.inflate(R.layout.fragment_section_launchpad, container, false);

            // Demonstration of a collection-browsing activity.
            rootView.findViewById(R.id.demo_collection_button).setOnClickListener(new View.OnClickListener()
            
                @Override
                public void onClick(View view) 
                
                    Intent intent = new Intent(getActivity(), CollectionDemoActivity.class);
                    startActivity(intent);
                
            );

            // Demonstration of navigating to external activities.
            rootView.findViewById(R.id.demo_external_activity).setOnClickListener(new View.OnClickListener()
            
                @Override
                public void onClick(View view)
                
                    // Create an intent that asks the user to pick a photo, but using
                    // FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, ensures that relaunching
                    // the application from the device home screen does not return
                    // to the external activity.
                    Intent externalActivityIntent = new Intent(Intent.ACTION_PICK);
                    externalActivityIntent.setType("image/*");
                    externalActivityIntent.addFlags(
                    Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                    startActivity(externalActivityIntent);
                
            );
            return rootView;
        
    

    /**
     * A dummy fragment representing a section of the app, but that simply displays dummy text.
     */
    public static class DummySectionFragment extends Fragment
    
        public static final String ARG_SECTION_NUMBER = "section_number";

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        
            View rootView = inflater.inflate(R.layout.fragment_section_dummy, container, false);
            Bundle args = getArguments();
            ((TextView) rootView.findViewById(android.R.id.text1)).setText(getString(R.string.dummy_section_text, args.getInt(ARG_SECTION_NUMBER)));
            return rootView;
        
    
    public class CustomView extends View
    
        public CustomView(Context context)
        
            super(context, null);
        
     

tab_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical" >

  <TextView
              android:id="@+id/nieuws_tab_layout"
              android:layout_
              android:layout_              
              android:text="@string/nieuws"
              android:gravity="center_vertical"
              android:layout_marginTop="15dp"
              android:textColor="@android:color/white"
              android:textStyle="bold"
              android:background="@android:color/black"
              />
</LinearLayout>

【问题讨论】:

这是在一个活动中吗?尝试使用 this 而不是 context(这似乎是您尚未声明的实例) 是的,这是在实现 ActionBar.TabListener 的 FragmentActivity 中使用它确实解决了错误,但它不会将我的样式应用于我的选项卡 然后你必须调用 getActivity() 而不是上下文。我建议您阅读@desseim 的答案,因为您可能会觉得它很有趣。 我想给每个标签一个不同的颜色,并给选定的标签一个不同的文本颜色。至于指标,我想要一条与所选选项卡颜色相同的线。 (这条线应该像操作栏生成器中的细线一样位于所有选项卡下方) 如果您将代码粘贴到您初始化标签和标签栏的位置,会更容易为您提供帮助。 【参考方案1】:

只需在标签创建时设置您的自定义视图,例如:

final Tab firstTab = actionBar.newTab()
                              .setText(mAppSectionsPagerAdapter.getPageTitle(0))
                              .setCustomView(R.id.custom_tab_view_red);
final Tab secondTab = actionBar.newTab()
                               .setText(mAppSectionsPagerAdapter.getPageTitle(1))
                               .setCustomView(R.id.custom_tab_view_blue);
// etc

actionBar.addTab(firstTab);
actionBar.addTab(secondTab);
// etc

inCreate().

您还必须在您的 xml 布局文件(而不是 styles)中定义与上述 ids 相对应的 Views

或者,如果你想直接创建视图:

final View firstCustomView = new CustomView(this);
firstCustomView.setBackgroundColor(Color.BLUE);  // or with drawable or resource
final Tab firstTab = actionBar.newTab()
                              .setText(mAppSectionsPagerAdapter.getPageTitle(0))
                              .setCustomView(firstCustomView);
actionBar.addTab(firstTab);
// then same for other tabs, just with another color

留下以下资料供参考:

要定义一个这样的视图,您需要将其指定为 Android Context。这通常是显示选项卡的Activity。 假设您在Activity 中初始化选项卡,只需将Activity 实例作为Context 传递:

ctv = new CustomView(this, R.attr.tabStyleAttr);

如果来自Activity,或者例如:

ctv = new CustomView(getActivity(), R.attr.tabStyleAttr);

如果来自Fragment等内部。

至于为操作栏选项卡设置特定样式,无需像您尝试那样以编程方式创建自定义视图。首先阅读一点about the action bar,然后检查他们提供的the example。如您所见,您将能够在 xml 中指定选项卡样式:

在清单文件中,您可以将主题应用于整个应用:

<application android:theme="@style/CustomActionBarTheme" ... />

或个别活动:

<activity android:theme="@style/CustomActionBarTheme" ... />

例如。

有关与您的用例完美匹配的完整示例,请参阅此 Android 文档文章:https://developer.android.com/training/basics/actionbar/styling.html#CustomTabs。请注意使用状态列表来实现“选择时样式”。

【讨论】:

我不想使用整个主题,因为它适用于所有选项卡。我想将样式应用到单个选项卡。使用它会发出警告说 ctv 未使用。使用 getActivity 会报错说 getActivity 未定义 正如我所写,getActivity() 是在 Fragment 内部使用的,如果您在 Activity 中,只需使用 this。此外,查看您添加的代码,您构造了一个 View 并将其影响到一个变量 (ctv),但仅此而已。然后你需要对它做一些事情,例如将它应用为给定选项卡的视图。 我确实忘记设置视图了。现在我已经设置了视图,它仍然没有将它更改为我的颜色设置。 2 件事:在你的样式 xml 中用 android:actionBarStyle 替换 @attr/actionBarTabStyle 键;确保将Theme.Ab 应用为应用程序或Activity 的样式(以及正确的Activity,而不是另一个),正如我在答案末尾强调的那样;现在您至少应该将自定义可绘制对象视为背景选项卡的背景。之后,您可以尝试为突出显示的选项卡设置特定样式。 @Shishi 也看到我在答案末尾添加的链接,你应该在那里找到你需要的一切。【参考方案2】:

如果另一个像我一样使用 TabLayout,我使用了这个 sn-p

tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() 
        @Override
        public void onTabSelected(TabLayout.Tab tab) 
            tab.setCustomView(R.layout.chat_tab);

        

        @Override
        public void onTabUnselected(TabLayout.Tab tab) 
            tab.setCustomView(null);
        

        @Override
        public void onTabReselected(TabLayout.Tab tab) 

        
    );

【讨论】:

我正在使用 tabLayout,并且我希望第三个选项卡文本颜色应为红色,无论选择/不选择。你能帮帮我吗? 我在下面回答,对其他人有帮助。【参考方案3】:

我使用的是 AndroidStudio 库提供的 Tablayout。 在添加选项卡时只需对您要自定义的每个选项卡使用 setCustomView() 即可。像下面的东西

    tabLayout.addTab(tabLayout.newTab().setText("FirstTab"));  // default tab
    tabLayout.addTab(tabLayout.newTab().setText("SecondTab").setCustomView(R.layout.tabview));  // Customized tab

下面是特定 Tab 的布局设计以满足我们的要求,这里我只是让 Tab 文本颜色不同

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_
android:layout_
android:background="@color/colorPrimaryDark">  <!-- TabLayout default color in my case -->
<TextView
    android:layout_
    android:layout_
    android:text="Procurement"
    android:textAllCaps="true"
    android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small"
    android:textColor="@color/tab_selection"  <!-- textcolor which ever you like-->
    android:textStyle="bold"/>

</LinearLayout>

【讨论】:

如果我想将颜色应用到单个选项卡并将另一种不同颜色应用到另一个选项卡 我只使用 setCustomView() 为一个选项卡赋予颜色,您可以设计选项卡的数量。您必须为不同的选项卡定义不同的布局。 能否举个例子作为参考 tabLayout.addTab(tabLayout.newTab().setText("FirstTab").setcustomview(R.layout.customDesignForfirsttab)); tabLayout.addTab(tabLayout.newTab().setText("SecondTab").setCustomView(R.layout.tabview));

以上是关于如何自定义单个选项卡? (更改背景颜色、指示器颜色和文本颜色)的主要内容,如果未能解决你的问题,请参考以下文章

如何更改自定义轮播指示器背景颜色?

如何在 Android 选项卡下更改颜色/删除标签/边框?

如何更改角度材料中选定选项卡的下划线颜色?

UITabBarItem选项卡栏项目单个选定的背景颜色

如何更改特定角度材质选项卡的背景颜色?

标签栏的背景颜色 更多按钮视图