It is maybe quite a newbie question but anyway. Since Tabhost is depreciated I tried to switch to the action bar tabs but I have my problems using fragments. Is there a possibility to use activities within the action bar tabs anyway?
I would appreciate any help.
Thanks.
If you're set on using Activities over Fragments you could just use an intent to launch your activity from your ActionBar.TabListener
startActivity(new Intent(thisActivity(), thatActivity.class));
You should also check out this comment about using Fragments over Activities
Is there a possibility to use activities within the action bar tabs anyway?
Fortunately, no.
That does not mean you have to use fragments, though. Your TabListener can do whatever it wants to affect the change in your UI. A brute-force solution would be to call setContentView() again, to dump all your old widgets and lay down a brand-new (presumably different) set.
It's possible to use an Activity with the ActionBar. Beware this is not intended behaviour though, but that doesn't mean it doesn't work perfectly.
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
//#SuppressLint("NewApi")
public class ActionBarActivity extends Activity {
private String TAG = getClass().getName();
private Intent i = null;
private ActionBar actionBar;
private Tab one;
private Tab two;
private Tab three;
// create a tab listener that is called when the user changes tabs
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
if (tab.getTag().equals("one")){
Log.d(TAG, "tab one selected");
i = new Intent(getApplicationContext(), One.class);
determineRun();
}
if (tab.getTag().equals("two")){
Log.d(TAG, "tab two selected");
i = new Intent(getApplicationContext(), Two.class);
determineRun();
}
if (tab.getTag().equals("three")){
Log.d(TAG, "tab three selected");
i = new Intent(getApplicationContext(), Three.class);
determineRun();
}
}
#Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
// TODO Auto-generated method stub
}
};
// we only need to start the Activity if it's not actually already the current Activity!
void determineRun(){
if (!TAG.equals(i.getComponent().getClassName())){
startActivity(i);
}
return;
}//end method
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
actionBar = getActionBar();
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setSubtitle(getResources().getString("subtitle"));
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
one = actionBar.newTab();
one.setText("Tab 1").setTag("one");
two = actionBar.newTab();
two.setText("Tab 2").setTag("two");
three = actionBar.newTab();
three.setText("Tab 3").setTag("three");
one.setTabListener(tabListener);
two.setTabListener(tabListener);
three.setTabListener(tabListener);
// You will have to set the selected Tab manually
// A good idea would be to create a subclass for each Tab based on this code
// Then, just create a new Activity which extends ActionBarActivity
actionBar.addTab(one, 0, false);
actionBar.addTab(two, 1, true); // selected Tab
actionBar.addTab(three, 2, false);
}//end method
#Override
public void onResume(){
super.onResume();
Log.d(TAG, "onResume()");
Log.d(TAG, ""+i.getComponent().getClassName());
// again, here you need to select the Tab manually
if (!TAG.equals(i.getComponent().getClassName())){
actionBar.selectTab(two); // selected Tab
}
}//end method
#Override
public void onPause(){
super.onPause();
Log.d(TAG, "onPause()");
}//end method
#Override
public void onBackPressed() {
super.onBackPressed();
overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
}//end method
}//end class
You probably want to override the animation in your Activity so the change of tabs is seemless.
To do so, modify the onCreate() method of your Activity which extends ActionBarActivity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(0, 0);
}//end method
if my understanding is correct, you want to use action bar to swap activity instead of fragment. in this case, please continue to read.
from the official document you can see, the actionbar feature defines a set of ui, position. if you want to implement actionbar with activity, the most important thing to do is
1. to associate your tab(position) with your activity.
2. add tablistener callback(instantiate your new activity, stop the current activity) every time the tab is click
the best design is to have the tablistener implemented a seperate class, so that each of your activity could use this class.
Related
I'm passing data from fragment to another fragment with a bundle, but I have a map and I want to update this fragment and non replace it...this is the code in the MainActivity:
Mapped map = new Mapped();
final Bundle bundle = new Bundle();
bundle.putString("Position",one);
bundle.putString("ID",two);
map.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.mapView, map).commit();
and every time it delete the old fragment...How can I do to update it and not replace?
EDIT: this is the code of MainActivity:
public class MainActivity extends FragmentActivity implements Connection.SendMessage
{
ViewPager Tab;
TabPagerAdapter TabAdapter;
ActionBar actionBar;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabAdapter = new TabPagerAdapter(getSupportFragmentManager());
Tab = (ViewPager)findViewById(R.id.pager);
Tab.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
{
public void onPageSelected(int position)
{
actionBar = getActionBar();
actionBar.setSelectedNavigationItem(position);
}
});
Tab.setAdapter(TabAdapter);
actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener tabListener = new ActionBar.TabListener()
{
public void onTabReselected(android.app.ActionBar.Tab tab,FragmentTransaction ft)
{
}
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft)
{
Tab.setCurrentItem(tab.getPosition());
}
public void onTabUnselected(android.app.ActionBar.Tab tab,FragmentTransaction ft)
{
}};
actionBar.addTab(actionBar.newTab().setText("Connessione").setTabListener(tabListener));
actionBar.addTab(actionBar.newTab().setText("Mappa").setTabListener(tabListener));
}
public void send(String one, String two)
{
Mapped map = new Mapped();
final Bundle bundle = new Bundle();
bundle.putString("Position",one);
bundle.putString("ID",two);
map.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.mapView, map).commit();
}
}
The communication between fragments must be done through the parent FragmentActivity like documentation says:
Often you will want one Fragment to communicate with another, for example to change the content based on a user event. All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.
The problem is how to refresh something in the ui. If you call replace to make the back navigation, in the OnCreateView of the new fragment you get the value of the parent activity. If you use the popbackstack to navigate backwards you should implement an interface.if you show the two fragments together, only use the fragment activity to refresh data.You can chage this:
getSupportFragmentManager().beginTransaction().replace(R.id.mapView, map).commit();
for this:
MyFragment myFragment = (MyFragment) getFragmentManager().findFragmentById(R.id.test_fragment);
if(myFragment!=null){
myFragment.update();
}
I'll give you some links to talk about this:
http://developer.android.com/training/basics/fragments/communicating.html
https://stackoverflow.com/a/9977370/944630
How to pass data between fragments
hope you help
You could try this solution:
add Mapped with a tag myMap:
Mapped map = new Mapped();
getSupportFragmentManager().beginTransaction().add(R.id.mapView, map, "myMap").commit();
make a method in Mapped, named addData(Bundle data), then you can pass data by this method when you need.
after data added to Mapped, then refresh it by:
Fragment mapFrg = getSupportFragmentManager().findFragmentByTag("myMap");
getSupportFragmentManager().beginTransaction().detach(mapFrg);
getSupportFragmentManager().beginTransaction().atach(mapFrg).commit();
in Mappde, in onCreateView(), each time check MapView is null or not
Hope this help.
I am using AppCompat for my theme in my app. Also, I am using a viewpager to manage some fragments.
Now I would to hide the actionbar in one of my fragments. How can I do that. I tried to hide the actionbar manually in the fragment like this
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBarActivity activity = (ActionBarActivity) this.getActivity();
ActionBar aBar = activity.getSupportActionBar();
aBar.hide();
}
but this hides the actionbar for all fragments. Any ideas?
When you load other fragments call (for example in onResume):
aBar.show();
Edit:
in each fragment that you want to have show the ActionBar put the following method:
#Override
public void onResume() {
super.onResume();
aBar.show();
}
in the OnResume method of the Fragment which you don't want the action bar to show do this:
#Override
public void onResume() {
super.onResume();
aBar.hide();
}
SInce you're using the view pager I assume you're using code similar to:
http://developer.android.com/reference/android/support/v4/view/ViewPager.html
In which case in this method:
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
// add check here to determine if the selected item is the fragment you want to hide the action bar in...
// if so call aBar.hide();
// for example:
if(i == MY_NO_BAR_FRAGMENT) {
// when you set up the view fragment, you would set MY_NO_BAR_FRAGMENT to the index of that fragment in the view pagers list of pages.
aBar.hide();
}
}
}
}
I have had some trouble finding an example I understand for using ActionBarSherlock. I can implement the TabNavigation.java example that comes with the download. I'm not sure how to extend this example so that it triggers a new activity but still keeps the tabs displayed. Here's the example that I've implemented:
package com.actionbarsherlock.sample.demos;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockActivity;
public class TabNavigation extends SherlockActivity implements ActionBar.TabListener {
private TextView mSelected;
#Override
public void onCreate(Bundle savedInstanceState) {
setTheme(SampleList.THEME); //Used for theme switching in samples
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_navigation);
mSelected = (TextView)findViewById(R.id.text);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (int i = 1; i <= 3; i++) {
ActionBar.Tab tab = getSupportActionBar().newTab();
tab.setText("Tab " + i);
tab.setTabListener(this);
getSupportActionBar().addTab(tab);
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction transaction) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction transaction) {
mSelected.setText("Selected: " + tab.getText());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction transaction) {
}
}
I believe I need to create a new "Listener" class and pass that to the .setTabListener() method. I want to stick with Activities (not Fragments) as I have a pretty complex implementation of ORMLite and I'm not sure how to use ORMLite with Fragments yet.
I want to add a new tab labeled "Profile" which triggers ProfileActivity.class.
Thanks in advance!
I guess that TabListener is supposed to work with Fragments and FragmentTransaction. You will have to move your code from ProfileActivity to a new ProfileFragment class and add it with the FragmentTransaction you receive by the listener.
I would suggest you to add ViewPagerIndicator library on your project, just like this answer. A ViewPager is just like tabs plus the swype movement to navigate between them.
It sounds like the reason I'm not finding the example I am looking for is because you just can't use the action bar persistently with Activities. Comments or a better answer would be much appreciated. :)
I have an activity that uses ActionBarSherlock to show an action bar with navigation tabs. I need one of those tabs to open another activity (taking over the whole screen) when it is tapped. I built a custom TabListener to achieve this, but it fires when the tab contents are initially rendered, not just when it's manually selected.
I can't see a way to catch a traditional onClick event, so I assume I need to handle this in the TabListener and somehow distinguish the initial selection from a later manual selection, but how? I could use a counter each time the tab is selected and only start the secondary activity if the counter is above zero, but that looks like an ugly hack. I was hoping there was a way to handle a "click" as opposed to a "selection" as the latter includes both the initial display of the views, as well as later manual clicks.
I attach the listener to the action bar navigation tab like this:
tab.setTabListener(new TabDiseaseSelectorListener(this));
And then the listener looks like this:
public class TabDiseaseSelectorListener implements ActionBar.TabListener {
private final Activity mActivity;
public TabDiseaseSelectorListener(Activity activity) {
mActivity = activity;
}
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction unused) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setClass(mActivity, DiseaseSelector.class);
startActivity(intent);
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction unused) {
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
}
I tried using onTabReselected() but that only fires if the tab is already selected and the user taps it again.
How are you Mark? I have a question regarding the program you have written in the book "CommonsWare The Busy Coders Guide to Android Development".
I am talking about Fragments/EU4You_6 on Chapter 28 page 377. I want to expand this by adding an ActionBar Tab.
Without making any changes on your original program, what I did was that I copied EU4You.java to EU5You.java, which represents Tab2. EU4You.java will be the default Tab1.
The following are my approach:
I created a java program called EU4Main.java, which represents the MAIN program instead of the original EU4You. Of course, I changed the manifest to android:name=".EU4Main"
The EU4Main.java is where I put the ActionBar Tab. The trouble is and making me frustrated is in the TabListener setup. I have this setup .setTabListener(new TabListener(EU4You.class))); , which passes a Class. It did not work. Do you have any advise on this instead of passing a class?
Also, the onTabSelected on the code snippets below, did not work properly. If I clicked Tab2, it will show the list for Tab2 but it will automatically returns to Tab1. It won't stay at Tab2. I don't know why?
I would appreciate of any help if you can provide a better and working approach for both .setTabListener and onTabSelected
I have also extended FragmentActivity to EU4Main or shall I just use extends Activity instead?
Thanks in advance.
I have included EU4Main below with incorrect and incomplete codes( I just can't make it work...)
public class EU4Main extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.addTab(bar
.newTab()
.setText("Countries")
.setTabListener(new TabListener(EU4You.class)));
bar.addTab(bar
.newTab()
.setText("Artists")
.setTabListener(new TabListener(EU5You.class)));
.
.
.
private class TabListener implements ActionBar.TabListener {
public TabListener(Activity activity) {
mActivity = activity;
}
public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction unused) {
if (tab.getPosition() == 0) {
Intent intent = new Intent();
String packageName = "com.commonsware.android.eu4you";
String className = "com.commonsware.android.eu4you.EU4You";
intent.setClassName(packageName, className);
startActivity(intent);
else{
Intent intent = new Intent();
String packageName = "com.commonsware.android.eu4you";
String className = "com.commonsware.android.eu4you.EU5You";
intent.setClassName(packageName, className);
startActivity(intent);
}
}
public void onTabUnselected(ActionBar.Tab tab, android.app.FragmentTransaction unused) {
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xaction=fragMgr.beginTransaction();
}
public void onTabReselected(ActionBar.Tab tab,
android.app.FragmentTransaction xaction) {
// NO-OP
}
}
Your TabListener has a constructor that takes an Activity. You are calling the constructor with a Class. A Class is not an Activity.
Furthermore, you are using two separate TabListener instances, but your code for TabListener does not do anything different based upon the supplied parameter.
And, you are starting activities when tabs are selected, which is not going to be especially useful.
When a TabListener is called with onTabSelected(), it needs to affect a change to the existing UI. Starting a whole new activity does not constitute a change to the existing UI. Rather, TabListener should do something like:
execute a FragmentTransaction
set a fresh ListAdapter in the ListFragment managed by the tabs
update ordinary widgets in the current activity
etc.