33

Here's the deal. I have an application with three tabs. Through various interactions with the items in the tabs I end up launching other activities. The client has reviewed this and would like the activities launched "within" the tabs, so the tabs remain visible and if the user clicks the tab it goes back to the original activity defined in the setContent function. Is this possible and how would I go about this from other activities? (ie the child activities, not the one that defines the TabHost and has access to call setContent)?

MattC
  • 12,285
  • 10
  • 54
  • 78

7 Answers7

44

It is possible to launch activities within tabs. Therefore set the tabspec content to an ActivityGroup instead of a regular Activity.

tabHost.addTab(tabHost.newTabSpec("Tab")
                .setIndicator("Tab")
                .setContent(new Intent(this, YourActivityGROUP.class)
                 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)));

From within that ActivityGroup you can then start another Activity like this that only updates the contentview of the tab you're in.

class YourActivityGROUP extends ActivityGroup{

@Override
protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      //you van get the local activitymanager to start the new activity

      View view = getLocalActivityManager()
                                .startActivity("ReferenceName", new
      Intent(this,YourActivity.class)
                                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
                                .getDecorView();
       this.setContentView(view);

   }
}
hcpl
  • 17,382
  • 7
  • 72
  • 73
  • 1
    thanks for this... actually I think this should be the correct way moving forward to implement this kind of functionality as it provides better code maintainability. – samiq Jun 30 '10 at 02:53
  • There is another way aswell but elegant? Not really... You can always save the instance of your TabActivity class in an extended Application class (to avoid global static). When you need to launch a new activity you call the Application class to return the TabActivity instance and launch a method which clears the tabs and recreates them but replacing the current Activity with the new one. If someone is interested I can go into more details. – glr Oct 30 '10 at 18:36
  • hi, thanks.. i can call new activity in same tab, but the problem comes when coming back to the previous activity. I am calling Activity B from ActivityGroup A, now i want to move to ActivityGroup A again.. Can you please give me a clue.. thank you.. – manidhar mulaparthi Dec 15 '10 at 05:29
  • It is working, but after five activites, it will be unexpectedly end, cz stack is full – Chatar Veer Suthar Jul 13 '11 at 15:32
  • hi,i have same problem as manidhar mulaparthi.i can not come back with ActivityGroup..Any solution apreciated.Thanks in advance. – Juned May 04 '12 at 07:38
  • Perfect solution. My problem was it was starting multiple activities with same intent and while pressing back it was killing one by one...thanks for post. – Dinesh Prajapati Aug 09 '12 at 08:05
  • please help me i have tabs of different modules in which one tab denotes setting i want to open a new activity within setting tab im able to do this by making setting tab activity as activitygroup bt in child activity when i press it shuts down app i want to return to setting activity – Shikhar Mar 02 '16 at 05:52
11

Here is my solution

public class ActivityStack extends ActivityGroup {

  private Stack<String> stack;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (stack == null) stack = new Stack<String>();
    //start default activity
    push("FirstStackActivity", new Intent(this, FirstStackActivity.class));
  }

  @Override
  public void finishFromChild(Activity child) {
    pop();
  }

  @Override
  public void onBackPressed() {
    pop();
  }


  public void push(String id, Intent intent) {
    Window window = getLocalActivityManager().startActivity(id, intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
    if (window != null) {
      stack.push(id);
      setContentView(window.getDecorView());
    }
  }

  public void pop() {
    if (stack.size() == 1) finish();
    LocalActivityManager manager = getLocalActivityManager();
    manager.destroyActivity(stack.pop(), true);
    if (stack.size() > 0) {
      Intent lastIntent = manager.getActivity(stack.peek()).getIntent();
      Window newWindow = manager.startActivity(stack.peek(), lastIntent);
      setContentView(newWindow.getDecorView());
    }
  }
}

Launch tab

Intent intent = new Intent().setClass(this, ActivityStack.class);
TabHost.TabSpec spec = tabHost.newTabSpec("tabId")
spec.setContent(intent);

Call next activity

public class FirstStackActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TextView textView = new TextView(this);
    textView.setText("First Stack Activity ");
    textView.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
          Intent intent = new Intent();
          intent.setClass(getParent(), SecondStackActivity .class);
          ActivityStack activityStack = (ActivityStack) getParent();
          activityStack.push("SecondStackActivity", intent);


      }
    });
    setContentView(textView);
  }
}

Call next again

public class SecondStackActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TextView textView = new TextView(this);
    textView.setText("First Stack Activity ");
    textView.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
          Intent intent = new Intent();
          intent.setClass(getParent(), ThirdStackActivity .class);
          ActivityStack activityStack = (ActivityStack) getParent();
          activityStack.push("ThirdStackActivity", intent);


      }
    });
    setContentView(textView);
  }
}

Works on emulator 2.2

Georgy Gobozov
  • 13,633
  • 8
  • 72
  • 78
  • Actually, there is a pretty big bug - if you start from activity A an activity B and then finish() in activity A, the code above will actually finish activity B. – Artem Russakovskii Aug 11 '11 at 21:22
3

I solved with this: Experience - Multiple Android Activities in a TabActivity

shanethehat
  • 15,460
  • 11
  • 57
  • 87
Premier
  • 4,160
  • 6
  • 44
  • 58
1

you can use

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

for each activity you set as a content for tabSpec, and it will create this activity each time you press on the tab

kleopatra
  • 51,061
  • 28
  • 99
  • 211
Mohammed Elsabry
  • 503
  • 5
  • 12
0

commonsware.com is correct, it's not possible. I had a similar issue, but it was only 1 activity which was being launched. I sacrificed a little of my architecture and deleted the activity which was launched from inside the tab. I put the code in a View and then I added a ViewAnimator to the tab's activity. I overrode the back button and remove that view if it's up, or else let the back button perform as normal.

This faked it well enough, and for only 1 closely-related activity, I'm not going to lose any sleep over the design considerations.

marcc
  • 12,295
  • 7
  • 49
  • 59
0

As I can open a fragment or activity from a spinner in the toolbar ?

import android.content.Intent; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log; import android.view.Menu;
import android.view.MenuItem; import android.view.View;
import android.widget.AdapterView; import android.widget.ArrayAdapter;
import android.widget.Spinner;


> public class MainActivity extends AppCompatActivity {
> 
>     @Override
>     protected void onCreate(Bundle savedInstanceState) {
>         super.onCreate(savedInstanceState);
>         setContentView(R.layout.activity_main);
> 
>         //Appbar
>         Toolbar toolbar = (Toolbar) findViewById(R.id.appbar);
>         setSupportActionBar(toolbar);
>         getSupportActionBar().setDisplayShowTitleEnabled(false);
> 
>         //Appbar page filter
>         Spinner cmbToolbar = (Spinner) findViewById(R.id.CmbToolbar);
> 
>         ArrayAdapter<String> adapter = new ArrayAdapter<>(
>                 getSupportActionBar().getThemedContext(),
>                 R.layout.appbar_filter_title,
>                 new String[]{"Opción 1 ", "Opción 2 ", "Opción 3 "});
> 
>         adapter.setDropDownViewResource(R.layout.appbar_filter_list);
> 
>         cmbToolbar.setAdapter(adapter);
> 
>         cmbToolbar.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
>             @Override
>             public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
>                 //... Acciones al seleccionar una opción de la lista
>                 Log.i("Toolbar 3", "Seleccionada opción " + position);
> 
>                 Fragment f = null;
> 
>                 switch(position) {
>                     case 0:
>                         f = Fragment2.newInstance();
>                         break;
> 
>                     case 1:
>                         f = Fragment1.newInstance();
>                         break;
> 
>                 }
>             }
> 
>             @Override
>             public void onNothingSelected(AdapterView<?> adapterView) {
>                 //... Acciones al no existir ningún elemento seleccionado
>             }
>         });
>     }
> 
>     @Override
>     public boolean onCreateOptionsMenu(Menu menu) {
>         // Inflate the menu; this adds items to the action bar if it is present.
>         getMenuInflater().inflate(R.menu.menu_main, menu);
>         return true;
>     }
> 
>     @Override
>     public boolean onOptionsItemSelected(MenuItem item) {
>         // Handle action bar item clicks here. The action bar will
>         // automatically handle clicks on the Home/Up button, so long
>         // as you specify a parent activity in AndroidManifest.xml.
>         int position = item.getItemId();
> 
>         Fragment f = null;
> 
>         switch(position) {
>             case 0:
>                 f = Fragment2.newInstance();
>                 break;
> 
>             case 1:
>                 f = Fragment1.newInstance();
>                 break;
> 
>             case 2:
>                 Intent intent = new Intent(getApplicationContext(), Fragment1.class);
>                 startActivity(intent);
>                 break;
> 
>         }
>         return super.onOptionsItemSelected(item);
>     }
> 
> 
>     public Fragment getItem(int position) {
> 
>         Fragment f = null;
> 
>         switch(position) {
>             case 0:
>                 f = Fragment2.newInstance();
>                 break;
> 
>             case 1:
>                 f = Fragment1.newInstance();
>                 break;
> 
>             case 2:
>                 Intent intent = new Intent(getApplicationContext(), Fragment1.class);
>                 startActivity(intent);
>                 break;
> 
>         }
> 
>         return f;
>     } }
Rafel C.F
  • 179
  • 1
  • 10
0

How about 2 tabbar in this problem. First 1 is menu bottom tabbar, second one is top tabbar, they are different activity and xml

Danny
  • 39
  • 5