I am trying to set up validation script between tabs (users cant switch from one tab to another without required fields being filled). I am having trouble getting field values from the fragments/Tabs to the onTabSelected method of my TabListener class. As it is I can identify the index of the selected tab and was hoping to use that validate fields of previous tab
import android.app.ActionBar;
import android.app.Fragment;
import android.app.FragmentTransaction;
public class MyTabListener implements ActionBar.TabListener{
private Fragment fragment;
public MyTabListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
if(tab.getPosition() == 0)
{
ft.replace(R.id.content, fragment);
}
else if(tab.getPosition() == 1)
{
ft.replace(R.id.content, fragment);
}
else if(tab.getPosition() == 2)
{
ft.replace(R.id.content, fragment);
}
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
}
Inside your fragment put a function
public static boolean checkValidation() {
/*...check validation for all fields here,
return true if all fields are filled else return false....*/
if(validated){
return true;
}else {
return false;
}
return false;
}
Then inside onTabSelected
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
if(tab.getPosition() == 0)
{
if(YourFragment.checkValidation() == true) {
ft.replace(R.id.content, fragment);
} else{
//do something
}
}
}
I'm not sure if this works. Just try this and let me know if this works. :)
Related
I want to create an activity that can display any number of tabs, without creating an activity for each tab.
Is it possible?
The only way I saw creating tabs included creating an activity for each one.
You can try as follows ,
Extend your activity from ActionBarActivity and add required number of tabs programmatically ,
ActionBar.TabListener tabListener;
mactionBar = getActionBar();
mactionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
tabListener=new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
displayTabs(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
displayTabs(tab.getPosition());
}
};
mactionBar.addTab(mactionBar.newTab().setText(<any text>).setTabListener(tabListener));
//call the same method for required number of tabs
Call the same fragment for each tab click
private void displayTabs(int position)
{
Fragment fragment = null;
switch (position) {
case 0:
fragment = new YourFragment();
break;
case 1:
fragment = new YourFragment();
break;
// same for required numder of cases
default:
break;
}
if (fragment != null)
{
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(<container id>, fragment).commit();
}
}
How can I attach existing fragment, when change back tab in ActionBar.NAVIGATION_MODE_TABS?
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.detach(fragment);
}
}
You can verify if your fragment was loaded previously in the fragment stack. Also could store all your used fragments to reuse it
public void setFragment(Fragment fragmentInstance) {
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
Fragment oldFragmentInstance = fragmentManager
.findFragmentById(R.id.curr_fragment);
boolean onlyAttach = false;
List<Fragment> prevFragments = getSupportFragmentManager()
.getFragments();
for (Fragment fragment : prevFragments) {
if (fragment == null) {
continue;
}
if (fragment.getClass().equals(fragmentInstance.getClass())) {
onlyAttach = true;
fragmentInstance = fragment;
break;
}
}
fragmentTransaction.detach(oldFragmentInstance);
if (onlyAttach) {
fragmentTransaction.attach(fragmentInstance);
} else {
fragmentTransaction.replace(R.id.curr_fragment,
fragmentInstance);
fragmentTransaction.addToBackStack(null);
}
try {
fragmentTransaction.commit();
}
}
Hope this helps
i have 3 actionbar tabs home:video:purchase by default home will be selected.I can switch between different tabs where i'm able to replace the fragments.I have a gridview in home fragment on click of any grid cell i'm using the below piece of code to navigate to purchase tab,i'm able to replace the home fragment with purchase fragment but how can change the actionbar tab from home tab to purchase tab?????
FragmentTransaction ft = parentActivity
.getFragmentManager()
.beginTransaction();
ft.replace(R.id.mainLayout,new purchase());
ft.commit();
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (fragment != null) {
ft.setCustomAnimations(R.animator.fragmentanimatorleft,
R.animator.fragmentanimatorright);
ft.replace(R.id.mainLayout, fragment);
// isSettingClicked = false;
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (fragment != null) {
try {
ft.remove(fragment);
} catch (Exception e) {
// TODO: handle exception
}
}
}
I have a Fragment Activity which holds three fragments.
public class MainActivity extends SherlockFragmentActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tab1 = bar.newTab();
ActionBar.Tab tab2 = bar.newTab();
ActionBar.Tab tab3 = bar.newTab();
tab1.setText("");
tab1.setIcon(R.drawable.abs__ic_menu_share_holo_dark);
tab2.setText("");
tab2.setIcon(R.drawable.abs__ic_voice_search);
tab3.setText("");
tab3.setIcon(R.drawable.abs__ic_cab_done_holo_dark);
if (savedInstanceState == null) {
tab1.setTabListener(new MyTabListener());
tab2.setTabListener(new MyTabListener());
tab3.setTabListener(new MyTabListener());
bar.addTab(tab1);
bar.addTab(tab2);
bar.addTab(tab3);
}
}
private class MyTabListener implements ActionBar.TabListener {
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
switch (tab.getPosition()) {
case 0:
FeedsActivity frag = new FeedsActivity();
ft.replace(android.R.id.content, frag);
return;
case 1:
ProfileActivity frag2 = new ProfileActivity();
ft.replace(android.R.id.content, frag2);
return;
case 2:
MyMemoirsActivity frag3 = new MyMemoirsActivity();
ft.replace(android.R.id.content, frag3);
return;
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
}
And here is first Fragment,
public class FeedsActivity extends SherlockFragment {
public static String[] MainCategory;
public static String[] MainCategoryId;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup group,
Bundle saved) {
setRetainInstance(true);
return inflater.inflate(R.layout.activity_feeds, group, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
new GetMainCategory(getActivity()).execute();
}
}
When I select second tab and then select first tab the async task in first fragment is called again.How can I retain state of first fragment so that its view is created once? I have used setRetainInstance(true) but didnt work.
I solved this issue by using show and hide instead of attach and detach.
private class MyTabListener implements ActionBar.TabListener {
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
switch (tab.getPosition()) {
case 0:
if (frag1 == null) {
// If not, instantiate and add it to the activity
frag1 = Fragment.instantiate(getApplicationContext(),
FeedsActivity.class.getName());
ft.add(android.R.id.content, frag1, "Feeds");
} else {
// If it exists, simply attach it in order to show it
ft.show(frag1);
}
return;
case 1:
if (frag2 == null) {
// If not, instantiate and add it to the activity
frag2 = Fragment.instantiate(getApplicationContext(),
ProfileActivity.class.getName());
ft.add(android.R.id.content, frag2, "Profile");
} else {
// If it exists, simply attach it in order to show it
ft.show(frag2);
}
return;
case 2:
if (frag3 == null) {
// If not, instantiate and add it to the activity
frag3 = Fragment.instantiate(getApplicationContext(),
History.class.getName());
ft.add(android.R.id.content, frag3, "History");
} else {
// If it exists, simply attach it in order to show it
ft.show(frag3);
}
return;
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
if (frag1 != null) {
// Detach the fragment, because another one is being attached
switch (tab.getPosition()) {
case 0:
ft.hide(frag1);
return;
case 1:
ft.hide(frag2);
return;
case 2:
ft.hide(frag3);
return;
}
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
The proper way to use TabListener is this :
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, mTag);
} else {
// If it exists, simply attach it in order to show it
ft.attach(mFragment);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(mFragment);
}
}
#override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
Basically you need to check if that's the first time when your Fragment is being initialised. If not, you should add it to your screen and when the user unselect a tab you should detach the current visible fragment and add the new one. That's the way it should work. You don't need to create a new instance of Fragment everytime user click the tab.
I've got Fragment ActionBar Tabs with an TabListener attached to every tab. In my main activity I got a delete tab button as follows:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()
case R.id.closeTab:
closeTab();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void closeTab() {
if(getActionBar().getTabCount() > 1) {
Tab tab = getActionBar().getSelectedTab();
getActionBar().removeTab(tab);
}
}
What I'm trying to accomplish is to run some code in my tab-fragment before it gets removed. I could place this in the fragments onDestroyView() or onDestroy() but I only whant to run this code when I press my delete tab button.
I have checked the documentation for the TabListener but it seems like TabListener only listens to selectionchanges.
My TabListener:
public TabListener(Activity a, String t, Class<T> c) {
activity = a;
tag = t;
myClass = c;
}
/* The following are each of the ActionBar.TabListener callbacks */
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (fragment == null) {
// If not, instantiate and add it to the activity
fragment = Fragment.instantiate(activity, myClass.getName());
ft.add(android.R.id.content, fragment, tag);
} else {
// If it exists, simply attach it in order to show it
ft.attach(fragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (fragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(fragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
To clarify my question: How can I run code in my Fragment before the tab is removed?
Okey, I figured it out after reading this post: link.
In my fragment I put setHasOptionMenu(true)
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
And then I could just add onOptionsItemSelected in my fragment.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.closeTab:
closeTab();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void closeTab() {
ActionBar actionBar = getActivity().getActionBar();
if(actionBar.getTabCount() > 1) {
Tab tab = actionBar.getSelectedTab();
actionBar.removeTab(tab);
Log.d(TAG, "CLOSED TAB");
}
}