自定义选项卡/视图 - TabHost 还是 ActivityGroup?

发布于 2024-09-27 15:43:29 字数 2124 浏览 0 评论 0原文

我正在构建一个选项卡式应用程序。 TabHost 的工作效果非常好。不幸的是,我的团队领导不喜欢选项卡的外观。他不喜欢小图标和选项卡之间的间隙。因此,我要么需要修改 TabHost 要么使用 ActivityGroup。

我的第一次尝试是更改 TabHost。

这是我的一个选项卡的可绘制对象:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- When selected, use grey -->
    <item android:drawable="@drawable/ic_tab_timeline_grey"
          android:state_selected="true" />
    <!-- When not selected, use white-->
    <item android:drawable="@drawable/ic_tab_timeline_white" />
    <!-- This is a state-list drawable, which you will apply as the tab image. When the tab state changes, the tab icon will automatically switch between the images defined here.  -->
</selector>

我在主要活动中初始化该选项卡:(

// Initialize a TabSpec for each tab and add it to the TabHost
intent = new Intent().setClass(this, TimelineActivity.class);
spec = tabHost.newTabSpec("timeline") .setIndicator("",
                  res.getDrawable(R.drawable.ic_tab_timeline))
              .setContent(intent);
tabHost.addTab(spec);

请注意,我将指示器设置为空白。)

然后,我设置背景图像:

TabWidget tw = getTabWidget();
//changeTabWidgetStyle(tw);
View tempView = tabHost.getTabWidget().getChildAt(0);
tempView.setBackgroundDrawable(getResources().getDrawable(R.drawable.timeline_on));

这成功地将背景设置为我想要的图像。但是,我的选项卡仍然有一个小图标,它覆盖了我的背景图像。我怎样才能摆脱该图标?我尝试在初始化选项卡时将 Drawable 设置为 null,但这会导致我的应用程序崩溃。

即使我可以让它工作,看起来选项卡之间仍然有空格。我怎样才能摆脱那些?

如果这不起作用,我可能不得不使用 ActivityGroup。但我宁愿不这样做,因为这看起来更复杂。

我正在使用这个示例: android: using ActivityGroup to embed events

LocalActivityManager mgr = getLocalActivityManager(); 

Intent i = new Intent(this, SomeActivity.class); 

Window w = mgr.startActivity("unique_per_activity_string", i); 
View wd = w != null ? w.getDecorView() : null; 

if(wd != null) { 
    mSomeContainer.addView(wd); 
} 

我可以使用“选项卡”来更改和膨胀布局,但是我无法添加本地活动。我不确定要将视图添加到哪种“容器”中。我的 xml 布局应该是什么样子?

I am building a tabbed application. Things work wonderfully with TabHost. Unfortunately, my team lead does not like the look of the tabs. He doesn't like the tiny icon and the gaps between the tabs. So, I either need to modify TabHost or use an ActivityGroup.

My first attempt was at changing TabHost.

Here is the drawable for one of my tabs:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- When selected, use grey -->
    <item android:drawable="@drawable/ic_tab_timeline_grey"
          android:state_selected="true" />
    <!-- When not selected, use white-->
    <item android:drawable="@drawable/ic_tab_timeline_white" />
    <!-- This is a state-list drawable, which you will apply as the tab image. When the tab state changes, the tab icon will automatically switch between the images defined here.  -->
</selector>

I initialize the tab in my main activity:

// Initialize a TabSpec for each tab and add it to the TabHost
intent = new Intent().setClass(this, TimelineActivity.class);
spec = tabHost.newTabSpec("timeline") .setIndicator("",
                  res.getDrawable(R.drawable.ic_tab_timeline))
              .setContent(intent);
tabHost.addTab(spec);

(Note that I set the Indicator to blanks.)

Then, I set the background image:

TabWidget tw = getTabWidget();
//changeTabWidgetStyle(tw);
View tempView = tabHost.getTabWidget().getChildAt(0);
tempView.setBackgroundDrawable(getResources().getDrawable(R.drawable.timeline_on));

This successfully sets the background to my desired image. However, my tab still has the tiny icon, which overlays my background image. How can I get rid of the icon? I tried setting the Drawable to null when I initialize the tab, but this causes my app to crash.

Even if I can get this to work, it looks like I will still have spaces between the tabs. How can I get rid of those?

If this doesn't work, I may have to go with an ActivityGroup. I would rather not, though, because that seems more complicated.

I'm using this example: android: using ActivityGroup to embed activities

LocalActivityManager mgr = getLocalActivityManager(); 

Intent i = new Intent(this, SomeActivity.class); 

Window w = mgr.startActivity("unique_per_activity_string", i); 
View wd = w != null ? w.getDecorView() : null; 

if(wd != null) { 
    mSomeContainer.addView(wd); 
} 

I can get the "tabs" to change and inflate layouts, but I can't add the local activity. I'm not sure what sort of "container" to add the view to. What should my xml layout look like?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

伪装你 2024-10-04 15:43:29

这是我在最近的项目中成功创建完全自定义外观的选项卡的方法。

这个想法是在布局中使用隐藏的 TabWidget,并使用包含按钮的自定义 LinearLayout 来控制它。这样,您可以更轻松地将按钮自定义为您想要的外观。您将在每个按钮的 OnClick 内控制 Activity 中的实际 TabWidget。

使用 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>

设置 Activity 的 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);

        }

    });
}

如您所见,我使用可绘制对象来显示按钮打开和关闭的图像。使用此技术,当您只是尝试自定义 TabWidget 选项卡的外观时,您将不受可用选项的限制,并且您可以为选项卡创建完全自定义的外观。

另外,根据经验,在 Android 选项卡中使用 ActivityGroup 不是一个好主意。这种方法会消耗大量的系统资源。一种更好的方法(我也在该项目中实施过)是通过一组视图来跟踪视图,然后根据需要交换它们。

Here is the method i used to successfully successfully create completely custom looking tabs on a recent project.

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.

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>

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);

        }

    });
}

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.

Also, as a rule of thumb, it's a bad idea to use an ActivityGroup in android tabs. That approach eats up a lot of system resources. A better approach and one that I've also implemented on this project is to keep track of the views through an array of views and then swap them out as needed.

冷夜 2024-10-04 15:43:29

除了 SBerg413 的答案之外,您可以将新选项卡按钮的按钮图像设置为透明图像。然后添加一个 ImageView 显示在按钮下方(使用 RelativeLayout 使 ImageView 与按钮出现在同一空间中),然后简单地切换那里显示的图像取决于按下的按钮。

通过这种方式,您可以拥有不同形状的选项卡按钮,并且通常可以更自由地设计选项卡栏,并将这些按钮用作每个选项卡按钮的基本点击框。

Further to SBerg413's answer you can set the button images for your new tab buttons to transparent images. Then add an ImageView to display under the buttons (use RelativeLayout to get the ImageView to appear in the same space as the buttons) and simply switch the image displayed there depending on which button is pressed.

This way you can have tab buttons of different shapes and generally more freedom of design for the tab bar and use the buttons as a basic hit box for each tab button.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文