Greetings,
I am trying to get the Click - event when clicking on the currently selected tab of my TabActivity. The onTabChangedHandler is only called whenever the tab is changed, not if the currently active Tab is clicked. The debugger tells me i have the onClickListener Registered for the TabWidget within my TabHost.
Am i registering for the wrong View?
Also, I am unable to create a Context Menu for the Tabs, only for its content, is this problem related?
public class TestDroidViewTab extends TabActivity
implements TabContentFactory
, OnTabChangeListener, OnClickListener {
private static final String LOG_KEY = "TEST";
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final TabHost tabHost = getTabHost();
TabHost.TabSpec ts = tabHost.newTabSpec("ID_1");
ts.setIndicator("1");
ts.setContent(this);
tabHost.addTab(ts);
ts = tabHost.newTabSpec("ID_2");
ts.setIndicator("2");
ts.setContent(this);
tabHost.addTab(ts);
ts = tabHost.newTabSpec("ID_3");
ts.setIndicator("3");
ts.setContent(this);
tabHost.addTab(ts);
tabHost.setOnClickListener(this);
tabHost.setOnTabChangedListener(this);
}
public void onClick(View v) {
Log.d(LOG_KEY, "OnClick");
}
public void onTabChanged(String tabId) {
Log.d(LOG_KEY, "OnTabChanged");
}
If you want to see that a particular tab is clicked, you need to add your listener to the tab itself, not the TabHost.
The hierarchy of views in a tab implementation is:
TabHost
TabWidget
(tab)
(tab)
FrameLayout
The tabs are added at runtime by calling: tabHost.addTab(tabHost.newTabSpec(""));
You can then get a handle to the individual tabs by calling: getTabWidget().getChildAt(4);
In essence, you are adding your OnClickListener to a child of the TabWidget. You can now pick up the clicks on your individual tab. However, this will override the default behavior which changes the content when a tab is clicked. So, to get your content to change, your OnClickListener will need to do that for you.
Here is a full example, which lets you intercept the click event, and change the content below the tab:
final String myTabTag = "My Tab";
final int myTabIndex = 3;
getTabHost().addTab( getTabHost().newTabSpec(myTabTag) );
getTabWidget().getChildAt(myTabIndex).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (getTabHost().getCurrentTabTag().equals(myTabTag)) {
getTabHost().setCurrentTab(myTabIndex );
}
}
});
use setOnTabChangedListener instead of OnClickListener ;)
static TabHost tabHost;
tabHost = getTabHost();
tabHost.setOnTabChangedListener(new OnTabChangeListener() {
#Override
public void onTabChanged(String arg0) {
Log.i("******Clickin Tab number ... ", "" + tabHost.getCurrentTab());
}
});
Your clause is wrong, use:
...
if (getTabHost().getCurrentTabTag().equals(myTabTag) == false) {
getTabHost().setCurrentTab(myTabIndex );
}
...
into my code, it shows some errors and ask me to create new methods in
those names like getTabWidget(), getTabHost(), etc. Waiting for your
response.
Try this
tabHost.getTabHost().setCurrentTab(myTabIndex);
Related
I am adding a new tab layout to my app. My app has 4 activities.
Before, the navigation was done with buttons displayed in activities, for example a button in activity 1 make you go to section 4. Each button was starting a new activity with a new intent. To go back user could hit his native device back button.
Example of button:
Button b1= (Button) findViewById(R.id.b1);
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(this, ActivityTab4.class);
startActivity(i);
}
});
Now, with the tabhost, user goes straight to desire activity, each activity is a child of my tabhost. However, I still need in my layout to keep some buttons that jump directly to a particular activity.
The problem, with these buttons, is that when they start a new activity, the tabhost disappears. I need to keep it at all time.
So how can I use the tabhost normally, but on the top of it also use custom buttons inside the layout of my sections that would keep the tabhost when I hit them?
My tabhost structure is very basic:
public class TabWidget extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.global_tabs);
setTabs() ;
}
private void setTabs() {
addTab("Act1", R.drawable.tab1, ActivityTab1.class);
addTab("Act2", R.drawable.tab2, ActivityTab2.class);
addTab("Act3", R.drawable.tab1, ActivityTab3.class);
addTab("Act4", R.drawable.tab2, ActivityTab4.class);
}
private void addTab(String labelId, int drawableId, Class<?> c) {
TabHost tabHost = getTabHost();
Intent intent = new Intent(this, c);
TabHost.TabSpec spec = tabHost.newTabSpec("tab" + labelId);
// SET TITLETAB
View tabIndicator = LayoutInflater.from(this).inflate(R.layout.tab_indicator, getTabWidget(), false);
TextView title = (TextView) tabIndicator.findViewById(R.id.titleTab);
title.setText(labelId);
// SET IMAGETAB
ImageView icon = (ImageView) tabIndicator.findViewById(R.id.icon);
icon.setImageResource(drawableId);
spec.setIndicator(tabIndicator);
spec.setContent(intent);
tabHost.addTab(spec);
}}
Thanks for your help
EDIT: I would rather avoid fragments because it's going to take me a lot of time to implement them and on the top of that to make it compatible with API<11
All right, I've found it, thanks to this answer: setCurrentTab of a tabHost
BAsically in the main tabhost activity, add this
private static Main theInstance;
public static Main getInstance() {
return Main.theInstance;
}
public Main () {
Main.theInstance = this;
}
In the child, you can have a button sending the user to any tab + corresponding activity:
Button b1_3= (Button) findViewById(R.id.b1_3);
b1_3.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
TabWidget.getInstance().getTabHost().setCurrentTab(3);
}
});
Any reason why you use tabhost and activities instead of Fragments? I think you would find Fragments more suited to what you're trying to do.
As for your question - you can switch the displayed tab with
void setCurrentTab(int index)
void setCurrentTabByTag(String tag)
so there's no need to manually starting an activity on button press, just switch the displayed tab using these methods.
In my project, I have two tabs and a button. For two tabs,I have two activities and button calling different activity. the thing is I am showing result of button on first tab. i.e tab0 is active on tab0Event and on button click event too. And am able to change the tab events using tabHost.setOnTabChangedListener, but now what i further want is, say suppose i click on button so now button view is displaying(tab0 is active) but again if i click on tab0, tab0 activity should be displayed.
I tried many solutions for clicking on tab, one is
getTabWidget().getChildAt(getTabHost().getCurrentTab()).setOnClickListener
(new View.OnClickListener() {
#Override public void onClick(View v) {
System.out.println(getTabHost().getCurrentTab());
} });
But when i used this code with tabChnageListner, tab change not working and i got very unexpected results.
Would you please suggest solution for my problem.
Thanks.
code that is working for tab changed is as: (working fine for tab change, need to add Tab Onclick in it)
public class TabLayoutUsingTabChangeEventActivity extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost);
final TabHost.TabSpec sp1 = tabHost.newTabSpec("TAB1");
TabHost.TabSpec sp2 = tabHost.newTabSpec("TAB2");
//Creating First Tab
Intent intent1 = new Intent(this, Tab1Activity.class);
sp1.setIndicator("TAB1").setContent(intent1);
tabHost.addTab(sp1);
//Creating Second Tab
Intent intent2 = new Intent(this, Tab2Activity.class);
sp2.setIndicator("TAB2").setContent(intent2);
tabHost.addTab(sp2);
//Tab Changed Event
tabHost.setOnTabChangedListener(new OnTabChangeListener(){
#Override
public void onTabChanged(String tabId) {
Log.i("TabId :", tabId);
if(tabId.equals("TAB2")){
Log.i("TAB1", "TAB1 Changed");
Intent intent1 = new Intent().setClass(getApplicationContext(), Tab1Activity.class);
sp1.setIndicator("TAB1").setContent(intent1);
tabHost.setCurrentTab(0);
}
}
});
Button addNewButton = (Button)findViewById(R.id.add_new_ticket_btn);
addNewButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
Intent in = new Intent().setClass(getApplicationContext(), AddNewTicketActivity.class);
sp1.setContent(in);
tabHost.setCurrentTab(0);
//startActivity(in);
}
});
}
}
You can implement this listener:
host.setOnTabChangedListener(new OnTabChangeListener()
{
#Override
public void onTabChanged(String tabId)
{
if (getTabHost().getCurrentTabTag().equals("tab0"))
{
host.getCurrentTabView().setOnTouchListener(
new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
if (getTabHost().getCurrentTabTag().equals("tab0")
{
getTabHost().setCurrentTabByTag("tab1");
getTabHost().setCurrentTabByTag("tab0");
}
return false;
}
return false;
}
});
}
}
});
Also when you add tabs set tag for every tab:
host.addTab(host.newTabSpec("tab0"));
host.addTab(host.newTabSpec("tab1"));
You can used Fragment to layout
You cant. Views in TabWidget already have onClickListener and it is required fo normal workflow. If you remove it you will break TabWidget's logic.
When you set your onClickListener you remove previuos onClickListener and you break TabWidget logic.
Usually in such cases compound click listener is created (a click listener which handles click event and calls another click listener). But not in your case because there is no way to get old click listener because View doesn't have getOnClickListener method.
This is TabWidget source code. All related values are private... so we can't fix anithing from this side.
The only way to achieve your goal is a hack with Reflections because they allows to read private vars. So before set View's new onlick listener you should get old one (using Reflections), then create compound onClickListener which will do your event handling code and then call old onClickListener. Set compound click listener to the View.
I have a TabActivity in which there are two tabs , tabs may increase in future.So i need to change the title of MyTabActivity from anyone of them according to situation so that it is visible from all the tabs.
public class MyTabActivity extends TabActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tabContext = this;
setTitle("My App Name");
final TabHost tabHost = getTabHost();
tabHost.addTab(tabHost.newTabSpec(TAB_1).setIndicator(TAB_1, getResources().getDrawable(R.drawable.tab1)).setContent(new Intent(this, first.class)));
tabHost.addTab(tabHost.newTabSpec(TAB_2).setIndicator(TAB_2, getResources().getDrawable(R.drawable.tab2)).setContent(new Intent(this, second.class)));
tabHost.setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
setTabTitle();
}
});
tabHost.setCurrentTabByTag(TAB_1);
}
}
i have written setTabTitle() function to set my tabActivity title.
public void setTabTitle()
{
PrefManager prefManager = new PrefManager(getApplicationContext());
String tabtitle = prefManager.getTitle();
tabContext.setTitle("My App Name" + " " + tabtitle);
}
i am trying to change the title of MyTabActivity from the TAB_1(ListActivity) or TAB_2(Activity) when i get some data in these two activities .But when i change the tab then only the title gets changed because i have called it in (setOnTabChangedListener).But i want to change it as soon as i get some data in any one of my activity and calling this setTabTitle function.
i have tried two things as of now.Making setTabTitle() as static and calling it from two activities as MyTabActivity.setTabTitle("My Title") but its not working.
public static void setTabTitle(String title)
{
tabContext.setTitle("My App Name" + " " + title);
}
Other is as suggested by a member of this forum
MyTabActivity myTabs = (MyTabActivity) this.getParent();
myTabs.setTitle("This is First cool Activity");
But both of these is not working .Do i need to do some kind of REFRESH in activity ?.
Help me how to do this.
Thanks
I have a TabHost with 4 tabs. I need only the selected tab activity to be available on the stack. When user changes the tab, how to finish the activity under previous tab. I tried the following code. Here showing code for first tab. It similar for remaining tabs:
spec = tabHost.newTabSpec("tab1").setIndicator("Tab1",
res.getDrawable(R.drawable.ic_tab_tab1))
.setContent(new Intent(this, Tab1.class)
.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_TOP));
But the above code is deleting the Tab1 Activity on stack/heap only when the user comes again to that tab but not when user changes to new tab.
I've had a look at this, what is your reason for this?
How do you know what's on the stack? Are you depending on onDestroy() or something?
I haven't got a full answer but you can see which tab is active:
Let your class implement OnTabChangeListener
public class YourClass extends TabActivity implements OnTabChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
// Load all your normal objects as well as TabHost
// make your tabhost listen for tab changes
mTabHost.setOnTabChangedListener(this);
}
#Override
public void onTabChanged(String tabId) {
int currentTabNumber = mTabHost.getCurrentTab();
for(int i=0;i<mTabHost.getTabWidget().getChildCount();i++)
{
if(i != currentTabNumber){
System.out.println("I'm not a currently active tab");
}
}
}
}
How could I few layout and require to create in one Tabactivity.
I have try the code below but no luck got error.
tabHost.addTab(tabHost.newTabSpec("Sales Order").setIndicator("Sales Order").setContent(R.layout.frm_txn_so_item_list));
OK let me explain clearly.
I have a code below, as you can see I have 4 tab layout page. Each of it has it own activity class. I have a button which is belong to cls_so_item_list.class, whenever I am try to call it in my cls_so it always return me null value.
So I have come out an idea, to remove all the tab page(item,product,summary,Report) activity classes then create it one standalone class which is cls_so.
My question is how do I put the layout page inside the tabHost.addTab? Thanks
public class cls_so extends TabActivity implements OnClickListener {
protected TabHost tabHost;
int intSalesOrderId;
src_txn_so.cls_so_obj objSalesOrder;
static final String LIST_ID = "list_id";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tabHost = getTabHost();
newTabIntent("Item", null, cls_so_item_list.class);
newTabIntent("Product",
getResources().getDrawable(R.drawable.so_product),
cls_so_prd_list.class);
newTabIntent("Summary",
getResources().getDrawable(R.drawable.so_summary),
cls_so_summary.class);
newTabIntent("Report",
getResources().getDrawable(R.drawable.so_report),
cls_so_summary.class);
Button btnSOLineDiscount = (Button) findViewById(R.id.txn_so_btn_line_discount);
btnSOLineDiscount.setOnClickListener(this);
tabHost.setCurrentTab(0);
}
protected void newTabIntent(String label, Drawable icon, Class<?> pageClass) {
TabSpec tabSpec = tabHost.newTabSpec(label);
tabSpec.setIndicator(label, icon);
Intent SOIntent = new Intent().setClass(this,pageClass);
SOIntent.putExtra(LIST_ID, -1);
tabSpec.setContent(new Intent(this, pageClass));
tabHost.addTab(tabSpec);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
It doesn't work like that. In your main layout, add in the FrameLayout with the id of tabcontent an element <include> that points on that layout.
In your code you'll have to change it to.
tabHost.addTab(tabHost.newTabSpec("Sales Order").setIndicator("Sales Order").setContent(R.id.my_included_layout));
if you're <include> has the id "#+id/my_included_layout"