I figured out a way to get the result I wanted, just not the exact way I was trying and never managed to get the height of the tabcontent
directly but indirectly.
I found two methods to do this and I'll post them below.
First I did Method 2 but then discovered I preferred Method 1 and decided to go with that since it's more extendable.
Method 1
This way I found from How to size an Android view based on its parent's dimensions and is the most customizable and readable method. In a nut shell, you need to extend FrameLayout
and override the onMeasure
method.
<?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"
android:padding="0dip"
android:layout_margin="0dip">
<LinearLayout
android:id="@+id/topLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="0dip"
android:layout_margin="0dip">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:padding="0dip"
android:layout_margin="0dip" />
<view
class="com.tmcaz.patch.TabContentFrameLayout"
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="0dip"
android:layout_margin="0dip" />
</LinearLayout>
</TabHost>
The major difference is using a custom class for this where you can handle the sizing from the event itself, similar to Method 2 but no need to do any calculations to get the content height.
I did this to give myself access to the event and handle all of the sizing in the content. Someone reading this may very well need to override something else and deal with the onMeasure
event totally differently.
The code is below
public class TabContentFrameLayout extends FrameLayout {
// add constructors, etc
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
// Should turn these in to member variables and reference it throughout.
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth, parentHeight);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Method 2
I assigned an id
to the LinearLayout
that held the TabWidget
and FrameLayout
. Here is my main.xml
<?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"
android:padding="0dip"
android:layout_margin="0dip">
<LinearLayout
android:id="@+id/topLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="0dip"
android:layout_margin="0dip">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:padding="0dip"
android:layout_margin="0dip" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="0dip"
android:layout_margin="0dip" />
</LinearLayout>
</TabHost>
I assigned a DIP height to the tabs
and then grabbed the LayoutParams
for the LinearLayout
which I simply subtract the height of the tabs
from the result. I've added code here for basic illustrative purposes only and can do it a bit more efficiently, it's not my production code :)
One thing to note is that you can't appear to directly pull the height of the layout during the onCreate event where it's most useful. You need to create a GlobalLayoutListener
to capture the change in the layout and get the size.
public class MyTabActivity extends TabActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout ll = (LinearLayout)findViewById(R.id.topLayout);
ll.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
DisplayLayoutDimensions();
}
}
);
// Code here to add activities to the tabs, etc
}
.
public void DisplayLayoutDimensions()
{
// Put code to calculate the heights you need instead of printing
// out the values obviously.
Resources r = getResources();
LinearLayout topLayout = (LinearLayout)findViewById(R.id.topLayout);
LayoutParams tabWidgetParams = getTabHost().getTabWidget().getLayoutParams();
float scale = r.getDisplayMetrics().density;
float pxTabContent = topLayout.getHeight() - tabWidgetParams.height;
/*** The commented out DIP calculations didn't work for me in any AVD so
manually I calculated them with the scale which worked fine ***/
//float dipTopLayout = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, topLayout.getHeight(), r.getDisplayMetrics());
//float dipTabWidget = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tabWidgetParams.height, r.getDisplayMetrics());
//float dipTabContent = dipTopLayout - dipTabWidget;
Log.d("MyTabActivity", "LinearLayout (topLayout) Height: " + topLayout.getHeight() + "px / " + (topLayout.getHeight() / scale) + "dp");
Log.d("MyTabActivity", "TabWidget Height: " + tabWidgetParams.height + "px / " + (tabWidgetParams.height / scale) + "dp");
Log.d("MyTabActivity", "Calculated (tabcontent) Height: " + pxTabContent + "px / " + (pxTabContent / scale) + "dp");
}
Hope this helps someone at some point. If someone has a better way to do this, please speak up.