Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Removing tabs from tabhost causes app to crash

Posted on 2012-04-04
4
Medium Priority
?
1,553 Views
Last Modified: 2012-04-10
I need to be able to close tabs in a TabHost for an android app I'm working on. I am currently calling this code.

    tabHost.getTabWidget().removeViewAt(toDelete);

Open in new window


Where toDelete is the index of the tab that called the removal method. It looks like that code removes the tab, from the split second I can see it before it crashes. I'm thinking there's another removal method I need to call somewhere, because it appears to crash when attempting to draw the tab that was removed. I also tried

    tabHost.removeViewAt(toDelete);

Open in new window


But it crashed because it didn't have a view at toDelete, which is expected since (I think) it just contains the tab widget rather than the actual tabs.

Here are my crash logs

    04-04 16:05:53.149: E/AndroidRuntime(7885): FATAL EXCEPTION: main
    04-04 16:05:53.149: E/AndroidRuntime(7885): java.lang.NullPointerException
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2495)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.widget.TabWidget.dispatchDraw(TabWidget.java:323)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.View.draw(View.java:10981)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.widget.FrameLayout.draw(FrameLayout.java:450)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2126)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewRootImpl.draw(ViewRootImpl.java:2026)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1634)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.os.Handler.dispatchMessage(Handler.java:99)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.os.Looper.loop(Looper.java:137)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.app.ActivityThread.main(ActivityThread.java:4424)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at java.lang.reflect.Method.invokeNative(Native Method)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at java.lang.reflect.Method.invoke(Method.java:511)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at dalvik.system.NativeStart.main(Native Method)

Open in new window


Any ideas on what other methods I should be calling? Or am I going down the entirely wrong path?

Edit: I just tried opening 5 tabs and closing the second one. It didn't crash at first, but it did have some VERY odd behavior. When I click on a tab, it shows the next one to the right as being highlighted, but displays the correct tab, until I click the last tab at which point the app crashes. A few screen shots in case it helps to describe my issue.

When I click the songs tab before closing a tab
Songs tab working
When I click the tab for a specific song before closing a tab
Lyrics tab working
When I click the songs tab after closing the current program tab. The correct contents are displayed but the wrong tab looks selected.
After closing a tab
0
Comment
Question by:Curtis Long
  • 3
4 Comments
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 37809926
have you tried setting current tab to 0 before deleting?
0
 

Author Comment

by:Curtis Long
ID: 37813781
This is the entire code that is responsible for deleting the tab.

if(toDelete != -1)
{
	int currentTab = tabHost.getCurrentTab();
	if(currentTab >= toDelete)
		currentTab--;
	tabHost.setCurrentTab(0);
	tabHost.getTabWidget().removeViewAt(toDelete);
	int count = tabHost.getTabWidget().getTabCount()-1;
	while(currentTab > count)
		currentTab--;
	tabHost.setCurrentTab(currentTab);
	toDelete = -1;
}

Open in new window


I was able to find a solution, but I don't like it. As each tab is added, I save it to a Map, with the index of the tab as the key, and the TabHost.TabSpec as the value. Then this code runs when a tab is deleted

if(toDelete != -1)
{
	int currentTab = tabHost.getCurrentTab();
	tabs.remove(toDelete);
	tabHost.setCurrentTab(0);
	tabHost.clearAllTabs();
	Iterator<Entry<Integer, TabSpec>> it = tabs.entrySet().iterator();
	int counter = 0;
	while(it.hasNext())
	{
		@SuppressWarnings("rawtypes")
		Map.Entry pairs = (Map.Entry)it.next();
		TabHost.TabSpec spec = (TabSpec)pairs.getValue();
		tabHost.addTab(spec);
		if(counter != 0)
		{
			View view = getTabWidget().getChildTabViewAt(counter);
			view.setId((Integer)pairs.getKey());
			registerForContextMenu(view);
		}
		counter++;
	}
	int count = tabHost.getTabWidget().getTabCount()-1;
	while(currentTab > count)
		currentTab--;
	tabHost.setCurrentTab(currentTab);
	toDelete = -1;
}

Open in new window


I don't like having to delete all the tabs to close one tab though, and I'm still hoping there might be a better solution.
0
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 37826673
I don't like it either :) - but this seems to be the only one available
0
 
LVL 24

Accepted Solution

by:
alexey_gusev earned 2000 total points
ID: 37826879
actually, looking at the source code (conveniently available now for API levels 14 & 15 right from SDK manager)  I guess you might use TabHost.getContentView() and then go from there.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
Learn how to use the free Acronis True Image app to easily transfer data between iPhones and Android phones.
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
Suggested Courses

972 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question