B4A Library TabHostExtras

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Very useful library. I used it to help out with a layout problem I had, although not the way I wanted to. I ended up just setting my paddings to 0 so I can get the tabhost Tab Height and know what my content area size is then. A few suggestions for 1.8:

1. A way to get the padding values. Then I can use them in calculations to figure out the size of the content area.

2. A color array for the gradient. By the documentation I assumed only two colors too, but I made a function for my buttons lately that I use a color array and pass 3 colors which looks really nice. I'm not sure what the limit is, but it allows for more variations than I expected.

How did you pick which corners to apply a radius to? I'd like to make some buttons like that with diaganol corners rounded and not rounded.

3. Is it possible for individual Tab Colors where each tab is a different color or gradient?
 

warwound

Expert
Licensed User
Longtime User
TabHostExtras updated to version 1.80

Two new methods have been added:

getTabContentViewPadding (tabHost1 As TabHost) As Rect

Get the layout padding of tabHost1 TabContentView
Returns a Rect object containing pixel values

getTabHostPadding (tabHost1 As TabHost) As Rect

Get the layout padding of tabHost1 container View
Returns a Rect object containing pixel values

Documentation for the Rect object can be found here: Basic4android - Drawing (Core).

Version 1.80 is attached to the first post in this thread.

Martin.
 

warwound

Expert
Licensed User
Longtime User

I'm not sure about creating gradients with more than two colors - can you post your function so i can see how you have done it?

Look at the documentation for the native Android GradientDrawable and it's setCornerRadii and setCornerRadius methods.
These are the two methods i've used in TabHostExtras.

3. Is it possible for individual Tab Colors where each tab is a different color or gradient?

Here's the source code for the setTabGradientDrawable method:

B4X:
   /**
    * Set a GradientDrawable as the background on all TabIndicators in tabHost1
    * All fours corner radii of the GradientDrawable are set to the value of cornerRadius (in pixels)
    */
   public static void setTabGradientDrawable(TabHost tabHost1, String orientation, int color1, int color2, float cornerRadius) {
      GradientDrawable gradientDrawable1 = new GradientDrawable(GradientDrawable.Orientation.valueOf(orientation), new int[] { color1, color2 });
      gradientDrawable1.setCornerRadius(cornerRadius);
      TabWidget tabWidget1 = tabHost1.getTabWidget();
      int tabCount = tabWidget1.getChildCount();
      while (tabCount-- > 0) {
         tabWidget1.getChildAt(tabCount).setBackgroundDrawable(gradientDrawable1);
      }
   }

You can see that it applies the same GradientDrawable to each tab.
There's no reason why you couldn't apply a different GradientDrawable to each tab.

tabWidget1.getChildAt(tabCount) is a RelativeLayout.
So you can use any RelativeLayout methods, or methods that RelativeLayout inherits from it's super class, to manipulate it's visual style.

The problem with updating the tabs with GradientDrawables has been mentioned before in this thread, see http://www.b4x.com/forum/additional-libraries-official-updates/11056-tabhostextras-3.html#post79561.

I could create two new methods setTabGradientDrawable3 and setTabGradientDrawable4 which would function the same as setTabGradientDrawable and setTabGradientDrawable2 BUT only apply the GradientDrawable to a single tab referenced by it's index.

I don't have time for that today but will put it on my list of things to do!

Martin.
 

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Cool. No rush on the individual tab color stuff...my current app I imagine will take a while as it is very large and I can always add the tab colors later. The other stuff was great though and quick. I got an email last night about the 1.80 post and was amazed at the speed. I'll play with it today and add my padding back now. I like Putting them in a Rect vs all the int values too. When I first read the post I was thinking it was the actual Rect on the screen which would have been interesting to use for drawing on it, but they appear to just hold the pad values for that side. How are the CenterX and CenterY used here? Is CenterX an average of Right and Left and CenterY of Tob/Bottom?

The button gradient code I mentioned I actually put here already- http://www.b4x.com/forum/basic4andr...589-statelistdrawable-example.html#post102383

I use just two in the example, but I was playing yesterday trying to make a gel button with 4-5 colors. I wish the button allowed a color and a gradient on top of it without resorting to other drawing on the button. It could make a cool looking button using a static color with a white/black/transparent gradient overlay.
 

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Looks like some of what you said in post #27 is applying to my tabs. Android Tabs aren't the best...In pictures I see nice tabs with an image and text below it, and from the default margin they give I'd expect this. Unfortunately my image even when sized 16x16 all the way up to 48x48 using LoadBitmapSample takes up the whole tab. This then is drawn over by white or grey text with no shadows or outlines or anything to make it blend better.

So, I tried setting the font size with hopes of a bigger font being easier to read, but I've tried sizes all the way up to 120 and the font of the tabs don't change. I've tried making the tabs taller too in hopes of it allowing the image to shift up. It doesn't draw any different, but does appear to set its value since I use it to size my panels and they shift smaller. Erel may need to make some of this stuff an option in the view for it to work.

These last couple weeks I'm starting to wonder how anyone gets apps made for Android spending 70% of my time trying to figure out work arounds for Android's odd behaviors. Looks like I'm going to have to make my images contain the text for now...which won't look as crisp.
 

salmander

Active Member
Licensed User
Longtime User
When using Android 4.0 Layout, by changing the manifest to;
B4X:
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="14" />
The following line gives an error.
B4X:
TabHostManager.setTabTitle(TabHost1, "--VEHICLE INFO--", 0)

B4X:
search_showresults (B4A line: 846)


TabHostManager.setTabTitle(TabHost1, "--VEHICLE INFO--", 0)

java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.widget.RelativeLayout
   at uk.co.martinpearman.b4a.tabhostextras.TabHostExtras.setTabTitle(TabHostExtras.java:192)
   at com.home.cafiq.test.search._showresults(search.java:4997)
   at com.home.cafiq.test.search._searchjob(search.java:4942)
   at com.home.cafiq.test.search._jobdone(search.java:3499)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.BA.raiseEvent2(BA.java:170)
   at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:793)
   at anywheresoftware.b4a.keywords.Common.CallSub2(Common.java:780)
   at com.home.cafiq.test.httputilsservice._processnexttask(httputilsservice.java:256)
   at com.home.cafiq.test.httputilsservice._response_streamfinish(httputilsservice.java:357)
   at java.lang.reflect.Method.invokeNative(Native Method)


   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.BA.raiseEvent2(BA.java:170)
   at anywheresoftware.b4a.BA$3.run(BA.java:296)
   at android.os.Handler.handleCallback(Handler.java:607)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:156)
   at android.app.ActivityThread.main(ActivityThread.java:5005)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
   at dalvik.system.NativeStart.main(Native Method)
java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.widget.RelativeLayout
 

warwound

Expert
Licensed User
Longtime User
TabHostExtras updated to version 1.90

Hi.

Sorry for the delay in replying.

I don't have an ICS device to test on but used the emulator - API level 15.

I ran the demo code on a Gingerbread device and the ICS emulator and used the SDK tool Hierarchy Viewer to inspect the TabHost.

I suspected that with ICS a change had been made and ICS used a LinearLayout where previous versions used a RelativeLayout - that would explain the exception you posted.

But there is no change, the clickable Tabs are RelativeLayouts in both Gingerbread and ICS.
The demo code also runs with no problems on the emulator, using the Menu option Change title calls the TabHostExtras setTabTitle method and it works with no exceptions.

Then i updated the manifest, adding:

B4X:
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="14" />

And the exception is now raised.
Hierarchy Viewer now shows what i first thought - ICS is using a LinearLayout where previous versions used a RelativeLayout but only with that manifest edit.

Both LinearLayout and RelativeLayout are of type ViewGroup so a little update to the library code seems to have fixed everything.

Version 1.90 is attached to the first post in this thread.

Martin.
 

salmander

Active Member
Licensed User
Longtime User
Thank you very much mate. I am searching the forum to change the color of the tab indicator text. Is it not supported yet?
 

warwound

Expert
Licensed User
Longtime User
Thank you very much mate. I am searching the forum to change the color of the tab indicator text. Is it not supported yet?

Look back to this thread: http://www.b4x.com/forum/additional...-updates/11056-tabhostextras-4.html#post90535

The tab indicator text is displayed using an Android TextView so in theory it'd be quick and easy to add a method to change the text color of one or all tab indicators.

But tabs indicators have different states: active tab/inactive tab for example.

So you need to set a ColorStateList to define the text colors to use.

If ColorListState had already been wrapped within the B4A IDE so you could create a ColorListState in B4A then it is again simple to write a method to apply a ColorListState to one or more tab indicators.

But the ColorListState is not available within the B4A IDE so adding the ability to set tab indicator colors would mean creating a B4A wrapper class around the android ColorListState class as well as creating the required setter method.

I do not have time to create such a wrapper class unfortunately.

But thinking about it - maybe there's a simpler way...

Look here: Color State List Resource | Android Developers

You can create a ColorListArray purely in XML, make that XML file read-only and then TabHostExtras would require just a simple setter method to apply that ColorListState to a tab indicator....

I've made a note to do some research (tomorrow morning i think) and will post again.

Martin.
 

salmander

Active Member
Licensed User
Longtime User
That is very helpful of you. I am looking forward for it. But, in mean time, can I change the color of the text of all the tab indicator using reflection library please(tab state doesn't matter at the moment as my tabhost is transparent and the background of the activity is Gray colored image so the default color (white) is un-readable)?
 

warwound

Expert
Licensed User
Longtime User
Try the attached alpha version i've just compiled.

The use of a ColorListState defined in XML doesn't seem to work, that's the new setTabTextColor2 method.

But a quick test of the setTabTextColor method worked ok on my ZTE Blade.
The same color being displayed no matter what the state of the tab indicator:

B4X:
TabManager.setTabTextColor(TabHost1, Colors.Red)

Did you want all tab indicators to have the same text color?

I'll try and get the XML stuff working and post again.

Martin.
 
Last edited:

salmander

Active Member
Licensed User
Longtime User
Ohh wow That was quick...thanks a lot mate...I will test it and post my findings...

Actually, I have an activity with a background image which is basically light gray colored image. The activity contains a Tabhost with colors.transparent value. When I implemented the Android 4.0 layout (as described by Erel), the tab indicator also became transparent and thus the default color of the text indicator text (which is white) was un-readable. That is why I asked you, if it is possible to change the text color of the tabhost tab indicator to something like black while you are working on changing the textcolor StateList way. Thanks a lot again. I am testing it right now and will update you once tested.
 

warwound

Expert
Licensed User
Longtime User
TabHostExtras updated to version 2.00

At last you can set the color of the text in your tab indicators!

This update adds two new methods:

setTabTextColor

setTabTextColorStateList

Check out the first post in this thread for method syntax, usage notes and and the new library version download.

setTabTextColorStateList is probably the most useful of these two new methods, you can define a ColorStateList using XML and set that as the color to be used for the tab indicators:

B4X:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_selected="true"   
      android:color="#0000FF" />
   <item android:state_selected="false"   
      android:color="#FF0000" />
</selector>

Here a selected tab indicator's text is blue, an unselected tab indicator's text is red.
The attachement in post #1 contains this example XML file.
Assuming that your XML file is named tab_widget_text_colors.xml, you set this ColorStateList as tab indicator text color:

B4X:
TabManager.setTabTextColorStateList(TabHost1, "tab_widget_text_colors")

The ColorStateListName being the XML filename without the .xml entension.

Be sure to add the XML file to your project's Objects/res/drawable folder and make it read-only.

Martin.
 

warwound

Expert
Licensed User
Longtime User
I have just replaced the original uploaded 2.00 library.

The original upload still had it's version set to 1.90, the attachment now has the correct version code 2.00 set.

Martin.
 

AscySoft

Active Member
Licensed User
Longtime User
But is it possible to use gradient values in setTabTextColorStateList XML file?

Another (stupid) suggestion: why make external read-only XML file for setTabTextColorStateList? Why didn't you made it available from code inside library itself?
 

warwound

Expert
Licensed User
Longtime User
But is it possible to use gradient values in setTabTextColorStateList XML file?

I've done some searching but found no way so far to use a Gradient as text color.
That's not to say it's impossible - i'll have to leave you to spend the time searching if you really want this feature.
If you find any examples post again.

Another (stupid) suggestion: why make external read-only XML file for setTabTextColorStateList? Why didn't you made it available from code inside library itself?

Read back on the last few posts - implementing a ColorListState in code would have taken more time than i can spare.
I'd have had to create a wrapper library with all the possible getter and setter methods to enable a ColorListState to be created in code.

The XML solution took me relatively little time and is very flexible.
If you find any XML examples that show how to use a Gradient as a text color you can probably use those examples without requiring me to update the library.

Martin.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…