java Android:使用 TabHost 和 TabWidget 自定义选项卡的外观

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7784546/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 21:26:30  来源:igfitidea点击:

Android: customizing the look of Tabs using TabHost & TabWidget

javaandroidtabsandroid-tabhosttabwidget

提问by Belgi

I opend a post about this before but I feel that I can now (after reading some other posts) better explain what I want and rephrase it so it will be better understand.

我之前打开过一篇关于这个的帖子,但我觉得我现在可以(在阅读其他一些帖子后)更好地解释我想要什么并重新表述它以便更好地理解。

I followed the tutorial about Tab Layout on the dev guide and I managed to create tabs with it, but I want to do some customization to it (and I did look on other posts, but either the code had many mistakes to it or it didn't answer what I'm looking for).

我遵循了开发指南中关于 Tab Layout 的教程,我设法用它创建了选项卡,但我想对其进行一些自定义(我确实查看了其他帖子,但是代码有很多错误,或者没有不回答我在找什么)。

  1. The first problem I have is that the test is in most part over the icon instead of below it (I used an icon with dimensions 48x48 as recommended on the dev guide). I want the tab with to act like wrap_content does. I also want to change the text size (I think it's called the label).

  2. I want to use hex triplets to change the background color of the tabs, to change it between to situations : when this tab is the one selected and when it's not.

  3. I want to be able to change the color of the line that is below the tabs, I could not find any information on how to do this.

  1. 我遇到的第一个问题是测试大部分是在图标上方而不是下方(我使用了开发指南中推荐的尺寸为 48x48 的图标)。我希望标签与 wrap_content 一样。我还想更改文本大小(我认为这称为标签)。

  2. 我想使用十六进制三元组来更改选项卡的背景颜色,将其更改为以下情况:当此选项卡是选中的选项卡和未选中的选项卡时。

  3. 我希望能够更改选项卡下方线条的颜色,但找不到有关如何执行此操作的任何信息。

The code I'm currently using to create a new tab is (from the dev guide):

我目前用于创建新选项卡的代码是(来自开发指南):

    intent = new Intent().setClass(this, GroupsActivity.class);
    spec = tabHost.newTabSpec("groups").setIndicator("groups",
                      res.getDrawable(R.drawable.ic_tab_groups))
                  .setContent(intent);
    tabHost.addTab(spec);

(groups is the tab name).

(组是选项卡名称)。

Help is very much appreciated!

非常感谢帮助!

回答by SBerg413

Rather than trying to customize the widget tabs themselves, here is an alternate approach that I've used successfully on a project that may save you some headaches:

这里不是尝试自己自定义小部件选项卡,而是我在一个项目中成功使用的另一种方法,它可以为您省去一些麻烦:

The idea is to use a hidden TabWidget in your layout and control it with a customized LinearLayout containing Buttons. This way, you can more easily customize the buttons to look however you'd like. You'll control the actual TabWidget in your Activity within each button's OnClick.

这个想法是在您的布局中使用隐藏的 TabWidget 并使用包含按钮的自定义 LinearLayout 来控制它。通过这种方式,您可以更轻松地自定义按钮以使其外观随心所欲。您将在每个按钮的 OnClick 中控制活动中的实际 TabWidget。

  1. Create your layout with both the TabWidget and the Buttons:

        <?xml version="1.0" encoding="utf-8"?>
    <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/tabhost" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <RelativeLayout android:orientation="vertical"
            android:layout_width="fill_parent" android:layout_height="fill_parent"
            android:gravity="bottom">
            <TabWidget android:id="@android:id/tabs"
                android:layout_width="fill_parent" android:layout_height="wrap_content"
                android:visibility="gone" />
    
            <LinearLayout android:id="@+id/tabbar"
                android:orientation="horizontal" android:layout_width="fill_parent"
                android:layout_height="wrap_content">
                <Button android:id="@+id/firstButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_first_on"
                    android:layout_width="100dp" android:layout_height="43dp"
                    android:clickable="true"></Button>
                <Button android:id="@+id/secondButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_second_off"
                    android:layout_height="43dp" android:layout_width="100dp"
                    android:clickable="true"></Button>
                <Button android:id="@+id/thirdButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_third_off"
                    android:layout_height="43dp" android:layout_width="100dp"
                    android:clickable="true"></Button>
                <Button android:id="@+id/forthButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_forth_off"
                    android:layout_height="43dp" android:layout_width="100dp"
                    android:clickable="true"></Button>
            </LinearLayout>
    
            <FrameLayout android:id="@android:id/tabcontent"
                android:layout_width="fill_parent" android:layout_height="fill_parent"
                android:layout_below="@+id/tabbar" />
    
        </RelativeLayout>
    </TabHost>
    
  2. Set up the onCreate of your activity to handle using the buttons for adjusting the tab views:

        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            // tabs        
            firstButton = (Button) findViewById(R.id.firstButton);
            secondButton = (Button) findViewById(R.id.secondButton);        
            thirdButton = (Button) findViewById(R.id.thirdButton);
            forthButton = (Button) findViewById(R.id.forthButton);
    
            Resources res = getResources(); // Resource object to get Drawables
            final TabHost tabHost = getTabHost();  // The activity TabHost
            TabHost.TabSpec spec;  // Resusable TabSpec for each tab
            Intent intent;  // Reusable Intent for each tab
    
            intent = new Intent().setClass(this, FirstGroupActivity.class);
            spec = tabHost.newTabSpec("first").setIndicator("First").setContent(intent);
            tabHost.addTab(spec);
            intent = new Intent().setClass(this, SecondGroupActivity.class);
            spec = tabHost.newTabSpec("second").setIndicator("Second").setContent(intent);
            tabHost.addTab(spec);   
    
            intent = new Intent().setClass(this, ThirdGroupActivity.class);
            spec = tabHost.newTabSpec("third").setIndicator("Third").setContent(intent);
            tabHost.addTab(spec);
    
    
            intent = new Intent().setClass(this, ForthActivity.class);
            spec = tabHost.newTabSpec("forth").setIndicator("Forth").setContent(intent);
            tabHost.addTab(spec);
    
    
            tabHost.setCurrentTab(0);
    
            firstButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(0);
                    firstButton.setBackgroundResource(R.drawable.btn_first_on);
                    secondButton.setBackgroundResource(R.drawable.btn_second_off);              
                    thirdButton.setBackgroundResource(R.drawable.btn_third_off);
                    forthButton.setBackgroundResource(R.drawable.btn_forth_off);            
                }
    
            });
    
    
            secondButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(1);
                    firstButton.setBackgroundResource(R.drawable.btn_first_off);
                    secondButton.setBackgroundResource(R.drawable.btn_second_on);                       
                    thirdButton.setBackgroundResource(R.drawable.btn_third_off);                        
                    forthButton.setBackgroundResource(R.drawable.btn_forth_off);
    
                }
    
            });
    
    
            thirdButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(3);
                    firstButton.setBackgroundResource(R.drawable.btn_first_off);
                    secondButton.setBackgroundResource(R.drawable.btn_second_off);              
                    thirdButton.setBackgroundResource(R.drawable.btn_third_on);
                    forthButton.setBackgroundResource(R.drawable.btn_forth_off);
    
                }
    
            });
    
    
            forthButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(4);
                    firstButton.setBackgroundResource(R.drawable.btn_first_off);
                    secondButton.setBackgroundResource(R.drawable.btn_second_off);              
                    thirdButton.setBackgroundResource(R.drawable.btn_third_off);
                    forthButton.setBackgroundResource(R.drawable.btn_forth_on);
    
                }
    
            });
        }
    
  1. 使用 TabWidget 和按钮创建您的布局:

        <?xml version="1.0" encoding="utf-8"?>
    <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/tabhost" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <RelativeLayout android:orientation="vertical"
            android:layout_width="fill_parent" android:layout_height="fill_parent"
            android:gravity="bottom">
            <TabWidget android:id="@android:id/tabs"
                android:layout_width="fill_parent" android:layout_height="wrap_content"
                android:visibility="gone" />
    
            <LinearLayout android:id="@+id/tabbar"
                android:orientation="horizontal" android:layout_width="fill_parent"
                android:layout_height="wrap_content">
                <Button android:id="@+id/firstButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_first_on"
                    android:layout_width="100dp" android:layout_height="43dp"
                    android:clickable="true"></Button>
                <Button android:id="@+id/secondButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_second_off"
                    android:layout_height="43dp" android:layout_width="100dp"
                    android:clickable="true"></Button>
                <Button android:id="@+id/thirdButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_third_off"
                    android:layout_height="43dp" android:layout_width="100dp"
                    android:clickable="true"></Button>
                <Button android:id="@+id/forthButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_forth_off"
                    android:layout_height="43dp" android:layout_width="100dp"
                    android:clickable="true"></Button>
            </LinearLayout>
    
            <FrameLayout android:id="@android:id/tabcontent"
                android:layout_width="fill_parent" android:layout_height="fill_parent"
                android:layout_below="@+id/tabbar" />
    
        </RelativeLayout>
    </TabHost>
    
  2. 设置活动的 onCreate 以使用调整选项卡视图的按钮进行处理:

        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            // tabs        
            firstButton = (Button) findViewById(R.id.firstButton);
            secondButton = (Button) findViewById(R.id.secondButton);        
            thirdButton = (Button) findViewById(R.id.thirdButton);
            forthButton = (Button) findViewById(R.id.forthButton);
    
            Resources res = getResources(); // Resource object to get Drawables
            final TabHost tabHost = getTabHost();  // The activity TabHost
            TabHost.TabSpec spec;  // Resusable TabSpec for each tab
            Intent intent;  // Reusable Intent for each tab
    
            intent = new Intent().setClass(this, FirstGroupActivity.class);
            spec = tabHost.newTabSpec("first").setIndicator("First").setContent(intent);
            tabHost.addTab(spec);
            intent = new Intent().setClass(this, SecondGroupActivity.class);
            spec = tabHost.newTabSpec("second").setIndicator("Second").setContent(intent);
            tabHost.addTab(spec);   
    
            intent = new Intent().setClass(this, ThirdGroupActivity.class);
            spec = tabHost.newTabSpec("third").setIndicator("Third").setContent(intent);
            tabHost.addTab(spec);
    
    
            intent = new Intent().setClass(this, ForthActivity.class);
            spec = tabHost.newTabSpec("forth").setIndicator("Forth").setContent(intent);
            tabHost.addTab(spec);
    
    
            tabHost.setCurrentTab(0);
    
            firstButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(0);
                    firstButton.setBackgroundResource(R.drawable.btn_first_on);
                    secondButton.setBackgroundResource(R.drawable.btn_second_off);              
                    thirdButton.setBackgroundResource(R.drawable.btn_third_off);
                    forthButton.setBackgroundResource(R.drawable.btn_forth_off);            
                }
    
            });
    
    
            secondButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(1);
                    firstButton.setBackgroundResource(R.drawable.btn_first_off);
                    secondButton.setBackgroundResource(R.drawable.btn_second_on);                       
                    thirdButton.setBackgroundResource(R.drawable.btn_third_off);                        
                    forthButton.setBackgroundResource(R.drawable.btn_forth_off);
    
                }
    
            });
    
    
            thirdButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(3);
                    firstButton.setBackgroundResource(R.drawable.btn_first_off);
                    secondButton.setBackgroundResource(R.drawable.btn_second_off);              
                    thirdButton.setBackgroundResource(R.drawable.btn_third_on);
                    forthButton.setBackgroundResource(R.drawable.btn_forth_off);
    
                }
    
            });
    
    
            forthButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(4);
                    firstButton.setBackgroundResource(R.drawable.btn_first_off);
                    secondButton.setBackgroundResource(R.drawable.btn_second_off);              
                    thirdButton.setBackgroundResource(R.drawable.btn_third_off);
                    forthButton.setBackgroundResource(R.drawable.btn_forth_on);
    
                }
    
            });
        }
    

As you can see, I'm using drawables for the images of the buttons on and off. Using this technique, you're not limited to the options available when simply just trying to customize the look of the TabWidget's tabs and you can create a completely custom look to your tabs.

如您所见,我使用 drawable 来显示按钮的开和关图像。使用此技术,您不仅限于尝试自定义 TabWidget 选项卡的外观时可用的选项,还可以为选项卡创建完全自定义的外观。

回答by albodelu

1- Use a custom view:

1- 使用自定义视图:

    spec = tabHost.newTabSpec("groups");
    View view = LayoutInflater.from(this).inflate(R.layout.tabwidget_tabs, tabHost.getTabWidget(), false);
    spec.setIndicator(view);
    spec.setContent(intent);

instead of:

代替:

    spec = tabHost.newTabSpec("groups").setIndicator("groups", res.getDrawable(R.drawable.ic_tab_groups)).setContent(intent);
    tabHost.addTab(spec);

And then define the view for the tabs in the file tabwidget_tabs.xml (you can define an ImageView before the textView and the textsize):

然后在文件 tabwidget_tabs.xml 中定义选项卡的视图(您可以在 textView 和 textsize 之前定义一个 ImageView):

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/tabsLayout" 
        android:layout_width="wrap_content"
        android:layout_height="34dp"
        android:background="@drawable/tabs_bkgrd"
        android:padding="5dp" 
        android:orientation="vertical">

        <TextView android:id="@+id/tabsText" 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:singleLine="true"
            android:textStyle="bold" 
            android:gravity="center_horizontal"
            android:textSize="14dp" />
    </LinearLayout>

2- It's not possible to use hex triplets to change the background color of the tabs because are drawables not colors. However you can use a selector that changes the drawables. and you can combine this solution with setColorFilter() and android:tint and then you can select the background using hex triplets: How to tint a bitmap

2- 不可能使用十六进制三元组来更改选项卡的背景颜色,因为可绘制对象不是颜色。但是,您可以使用更改可绘制对象的选择器。您可以将此解决方案与 setColorFilter() 和 android:tint 结合使用,然后您可以使用十六进制三元组选择背景:How to tint a bitmap

tabs_bkgrd.xml:

tabs_bkgrd.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Non focused states -->
    <item android:state_focused="false" android:state_selected="false" 
        android:state_pressed="false" android:drawable="@drawable/tab_unselected_shape" />
    <item android:state_focused="false" android:state_selected="true" 
        android:state_pressed="false" android:drawable="@drawable/tab_selected_shape" /> 

    <!-- Focused states -->
    <item android:state_focused="true" android:state_selected="false" 
        android:state_pressed="false" android:drawable="@drawable/tab_focused_shape" />
    <item android:state_focused="true" android:state_selected="true" 
        android:state_pressed="false" android:drawable="@drawable/tab_focused_shape" /> 

    <!-- Pressed -->
    <item android:state_pressed="true" android:drawable="@drawable/tab_pressed_shape" /> 

    </selector>

You can define a color or a shape, tab_selected_shape.xml:

您可以定义颜色或形状,tab_selected_shape.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
                android:shape="rectangle">
            <gradient android:startColor="@color/gold1"
                android:centerColor="@color/gold2" 
                android:endColor="@color/gold2"
                android:angle="@integer/vertical_shape" />
    </shape>

3- The line is a drawable too. you can find the files in the sdk and copy them into your project after modify them to change the color using gimp. You can combine this solution with setColorFilter() and android:tint and then you can select the background using hex triplets too. Read: further explanation

3- 该线也是可绘制的。您可以在sdk中找到这些文件,并在修改它们以使用gimp更改颜色后将它们复制到您的项目中。您可以将此解决方案与 setColorFilter() 和 android:tint 结合使用,然后您也可以使用十六进制三元组选择背景。阅读: 进一步解释

android-sdk-linux_x86/platforms/android-7/data/res/drawable

android-sdk-linux_x86/platforms/android-7/data/res/drawable

tab_bottom_left.xml,  
tab_bottom_right.xml,  
tab_indicator.xml  (define state changes)

android-sdk-linux_x86/platforms/android-7/data/res/drawable-mdpi

android-sdk-linux_x86/platforms/android-7/data/res/drawable-mdpi

tab_focus.9.png (change color)
tab_focus_bar_left.9.png
tab_focus_bar_right.9.png
tab_press.9.png (change color)
tab_press_bar_left.9.png
tab_press_bar_right.9.png
tab_selected.9.png (change color)
tab_selected_bar_left.9.png tab_selected_bar_right.9.png
tab_unselected.9.png

tab_focus.9.png (改变颜色)
tab_focus_bar_left.9.png
tab_focus_bar_right.9.png
tab_press.9.png (改变颜色)
tab_press_bar_left.9.png
tab_press_bar_right.9.png
tab_selected.9.png (改变颜色)
tab_selected_bar_left.9 .png tab_selected_bar_right.9.png
tab_unselected.9.png

回答by Rainbowbreeze

What about the solution I proposed on this question?

我在这个问题上提出的解决方案怎么样?

You can customize the drawable of each button using the same used by native Android Tab bar(looking for resources in Android.jar to find the right drawables), plus you can customize additional behavious as you desire.

您可以使用与原生 Android Tab 栏相同的方式自定义每个按钮的可绘制对象(在 Android.jar 中查找资源以找到正确的可绘制对象),此外您还可以根据需要自定义其他行为。

At the end, you will obtain something that is graphically similar to a tabbar, from an user perspective, but acts differently from a developer perspective.

最后,从用户的角度来看,您将获得在图形上类似于选项卡栏的东西,但从开发人员的角度来看,它的行为却有所不同。