Search code examples
androidxmlandroid-fragmentstabsandroid-tabhost

FragmentedTabHost cannot change unselected background


I have been trying to edit a FragmentedTabHost's background colors to mess around with it a bit and I am quite clueless as to why I can changed the "unselected" state but not the "selected" state.

So what I have is a main drawable called "tabs" and inside I have references to two others "tab_selected" and "tab_unselected". I applied this background pretty much everywhere I could find to see if it worked but I got to the point where I think the best place to put it is in the TabWidget tag.

The selected state remains with the grayish color of the normal tab but the other one actually changes.

I don't know if I should be changing code elsewhere, as I already changed in the code it self by saying:

mTabHost.setBackgroundResource(R.drawable.tabs);

And still no progress...

Below is the code:

tabs.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
    android:drawable="@drawable/tab_selected" />
<item android:state_selected="false"
    android:drawable="@drawable/tab_unselected" />
</selector>

tab_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="rectangle">
        <solid android:color="#7fff00" />
    </shape>
</item>
<item android:top="20dp">
    <shape android:shape="rectangle">
        <solid android:color="#7fff00" />
    </shape>
</item>
<item android:bottom="2dp">
    <shape  android:shape="rectangle">
        <gradient android:startColor="#7fff00"
            android:endColor="#7fff00"
            android:angle="270" />
        <corners android:topLeftRadius="10dp" android:topRightRadius="10dp"/>
    </shape>
</item>
</layer-list>

tab_unselected.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="rectangle">
        <solid android:color="#86B4CF" />
    </shape>
</item>
<item android:top="20dp">
    <shape android:shape="rectangle">
        <solid android:color="#86B4CF" />
    </shape>
</item>
<item android:bottom="2dp">
    <shape  android:shape="rectangle">
        <gradient android:startColor="#86B4CF"
            android:endColor="#6792AB"
            android:angle="270" />
        <corners android:topLeftRadius="10dp" android:topRightRadius="10dp"/>
    </shape>
</item>
</layer-list>

And finally the FragmentedHost:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".Home"
android:orientation="vertical"
android:background="@drawable/global_background">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv_date"
        style="@style/header"/>

</LinearLayout>

<android.support.v4.app.FragmentTabHost
    android:id="@android:id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

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

        <TabWidget
            android:id="@android:id/tabs"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0"
            android:background="@drawable/tabs"/>

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0"/>

        <FrameLayout
            android:id="@+id/realtabcontent"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"/>

    </LinearLayout>
</android.support.v4.app.FragmentTabHost>

</LinearLayout>

Solution

  • Thank you both for your answers although I decided to go another way around.

    As instead of using FragmentedTabHost I decided to use ActionBar Tab because it is the most recomended.

    To do this I created this class:

    public class ActionBarTabListener implements ActionBar.TabListener {
    public Fragment fragment;
    
    public ActionBarTabListener(Fragment fragment) {
        this.fragment = fragment;
    }
    
    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
        //do what you want when tab is reselected, I do nothing
    }
    
    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        ft.replace(R.id.fragment_placeholder, fragment);
    }
    
    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
        ft.remove(fragment);
    }
    }
    

    Changed my main class (the one holding all the tabs):

    public class EntryDetails extends ActionBarActivity {
    
    private Entry entry;
    
    //private FragmentTabHost mTabHost;
    private TextView tv_date;
    private ActionBar ab;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_entry_details);
    
        ab = getSupportActionBar();
    
        ab.setTitle("Ecz :: Entry Details");
        ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    
        entry = getIntent().getExtras().getParcelable("e");
    
        /* TAB ITCHES */
    
        Bundle i = new Bundle();
        i.putParcelableArrayList("i", ArrayListHelper.OrderItchesByTime(entry.getItches()));
    
        Fragment f = new TabItches();
        f.setArguments(i);
    
        ActionBar.Tab tab = ab.newTab().setText("Itches").setTabListener(new ActionBarTabListener(f)).setTag(i);
        ab.addTab(tab);
    
        /* TAB TREATMENTS */
    
        i = new Bundle();
        i.putParcelableArrayList("t", ArrayListHelper.OrderTreatmentsByTime(entry.getTreatments()));
    
        f = new TabTreatments();
        f.setArguments(i);
    
        tab = ab.newTab().setText("Treatments").setTabListener(new ActionBarTabListener(f)).setTag(i);
        ab.addTab(tab);
    
        tv_date = (TextView) findViewById(R.id.tv_date);
    
        tv_date.setText(entry.getDate());
    }
    
    }
    

    Then I changed my XML in my EntryDetails.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".Home"
    android:orientation="vertical"
    android:background="@drawable/global_background">
    
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    
        <TextView
            android:id="@+id/tv_date"
            style="@style/header"/>
    
    </LinearLayout>
    
    <LinearLayout
        android:id="@+id/fragment_placeholder"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    </LinearLayout>
    
    </LinearLayout>
    

    So now I only have the linearlayout and no more tabhost.

    To give you more insight I place below the code to my TabItches:

    public class TabItches extends ListFragment{
    
    private ArrayList<Itch> itches;
    public ListAdapter itchesAdapter;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.tab_layout_itches, container, false);
    
        this.setRetainInstance(true);
    
        itches = this.getArguments().getParcelableArrayList("i");
    
        itchesAdapter = new ItchAdapter(getActivity(), itches);
    
        setListAdapter(itchesAdapter);
    
        return view;
    }
    }
    

    To edit the appearance of my tabs now I had to do more things! This code belongs in "@style"

    <style name="Appy" parent="@style/Theme.AppCompat.Light.DarkActionBar">
        <item name="android:actionBarStyle">@style/AppyActionBar</item>
        <item name="actionBarStyle">@style/AppyActionBar</item>
    
        <item name="android:actionBarTabStyle">@style/AppyActionBarTab</item>
        <item name="actionBarTabStyle">@style/AppyActionBarTab</item>
    </style>
    
    <!-- ActionBar styles -->
    <style name="AppyActionBar" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
        <item name="android:background">@color/AppyBlue</item>
        <!-- Support library compatibility -->
        <item name="background">@color/AppyBlue</item>
    </style>
    
    <style name="AppyActionBarTab"    parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
        <item name="android:background">@drawable/actionbar_tab_background</item>
        <!-- Support library compatibility -->
        <item name="background">@drawable/actionbar_tab_background</item>
    
        <item name="android:gravity">center</item>
    </style>
    

    Only take into account "AppyActionBarTab" code bits please!

    actionbar_tab_background.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@color/AppyDeeperBlue"/>
    <item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/actionbar_tab_background_selected"/>
    <item android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/actionbar_tab_background_selected_pressed"/>
    </selector>
    

    actionbar_tab_selected.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:top="-5dp" android:left="-5dp" android:right="-5dp">
        <shape android:shape="rectangle">
            <stroke android:color="@color/AppyBlue" android:width="5dp"/>
            <solid android:color="@color/AppyDeeperBlue"/>
        </shape>
    </item>
    </layer-list>
    

    actionbar_tab_selected_pressed.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:top="-5dp" android:left="-5dp" android:right="-5dp">
        <shape android:shape="rectangle">
            <stroke android:color="#B8D0DE" android:width="5dp" />
            <solid android:color="@color/AppyDeeperBlue"/>
        </shape>
    </item>
    </layer-list>
    

    I based my self on posts here all throughout StackOverFlow if I manage to find them again I will reference them.

    Right now I am struggling with changing the divider's color in API 10 and I cannot seem to get around it! :D

    I hope the answer is complete enough, if any problem just write and I will try to answer accordingly!!

    EDIT Fixed my problem with divider's color. What you need to do is change the divider's drawable.

    action_tab_divider.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/AppyBlue" />
    <stroke android:width="5dp"
        android:color="@color/AppyBlue"/>
    </shape>
    

    and now you need to apply this to the style

    <style name="Appy" parent="@style/Theme.AppCompat.Light.DarkActionBar">
        <item name="android:actionBarStyle">@style/AppyActionBar</item>
        <item name="actionBarStyle">@style/AppyActionBar</item>
    
        <item name="android:actionBarTabStyle">@style/AppyActionBarTab</item>
        <item name="actionBarTabStyle">@style/AppyActionBarTab</item>
    
        <item name="android:actionBarDivider">@drawable/actionbar_tab_divider</item>
        <item name="actionBarDivider">@drawable/actionbar_tab_divider</item>
    </style>
    

    Notice that we are overwriting in the "parent" style, not inside either of the two above!

    Thank you for reading :)