I am trying to create a program with TabLayout and an option menu which when selected can add or delete the tab along with the fragment. I can delete the tab but I am not able to understand what else needs to be done because I have to delete the fragments that the tab holds, more over I may also have to rearrange the position of the fragments which I just can't seem to figure out. Could you please help me with this ?
under mainAcitivity this is how I add tabs
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tab1= tabLayout.newTab().setText("TAB 1");
tabLayout.addTab(tab1);
tab2 = tabLayout.newTab().setText("TAB 2");
tabLayout.addTab(tabKantipur);
This is the FragmentstatePagerAdapter
public class TabPagerAdapter extends FragmentStatePagerAdapter {
int tabCount;
public TabPagerAdapter(FragmentManager fm, int numberOfTabs) {
super(fm);
this.tabCount = numberOfTabs;
}
#Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return NewsFragment.newInstance("data for fragment 1");
case 1:
return NewsFragment.newInstance("data for fragment 2");
default:
return null;
}
}
#Override
public int getCount() {
return tabCount;
}
}
Basically here NewsFragment is the fragment whose new instance is used in the tabs. Under onActivityResult I am getting the data that has been requested from the options Menu to add or delete fragmetns
mpagerAdapter = new TabPagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
removedTab = ..data received from ooption menu
// here I want to remove the Tab & the fragments (tab1 & its fragment)
if (removeTab == "tab1") {
tabLayout.removeTab(tab1);
mpagerAdapter.notifyDataSetChanged();
}
}
As I do this only the first tab gets removed I would like to know how to remove the associated fragment too.
You don't have to explicitly delete the fragment, you can remove the fragment.
You can remove the tab and do notifyDataSetChanged on the viewPagerAdapter instance.It will take care of removing the fragment.
I had asked a similar question using fragmentarray for which i got it to work . this is the link, Issue: Logic to find the position of a fragment in a fragment arraylist?
Related
As the title suggests, is it possible to replace two fragments while in a third one, for example pressing a button in fragment 3 replaces fragment 1 with fragment 2, while all 3 are inside a ViewPager? For simpler understanding, this is what my PagerAdapter looks like:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
int numberOfTabs;
public SectionsPagerAdapter(FragmentManager fm, int numberOfTabs) {
super(fm);
this.numberOfTabs=numberOfTabs;
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
switch(position){
case 0:
CreateEventFragmentPage1 tab1 = new CreateEventFragmentPage1();
return tab1;
case 1:
CreateEventFragmentPage2 tab2 = new CreateEventFragmentPage2();
return tab2;
case 2:
CreateEventFragmentPage3 tab3 = new CreateEventFragmentPage3();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
// Show 3 total pages.
return numberOfTabs;
}
}
Any and all advice will be highly appreciated.
As this is an adapter FragmentPagerAdapter so there is must be an notifyChanged method or similar
And i suppose it will works as notifyDataSetChanged with Recyclerview
Another reason for this that surrounded fragments of the current are not fully be destroyed
In addition rewrite method getItem(int position) to perform logic of reordering your fragments
Also try out to use an FragmentStatePagerAdapter
Sir, I have to use single fragment for multiple tabs. I have implemented it using FragmentStatePagerAdapter but after debugging I have got that some of the tabs displays data but not correct. This is because getItem called twice please help me as early as possible.
I have passed arguments from getItem. it passes arguments two times as getItem calls twice. thus it overrides data of arguments. I have 6 tabs but only 1, 3 and 5 tab displays data but data is of 2, 4 and 6th tab and 2, 4 and 6th tab not showing anything on the screen.
not working any solution from previous questions.
ViewPager Code
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
int TAB_COUNT=5;
Context mContext;
public ViewPagerAdapter(FragmentManager fm,Context context) {
super(fm);
mContext=context;
}
#Override
public Fragment getItem(int position) {
NewsFragment fragment = new NewsFragment();
Bundle args = new Bundle();
args.putString("title", String.valueOf(getPageTitle(position)));
args.putString("data", "data");
fragment.setArguments(args);
return fragment;
}
#Override
public CharSequence getPageTitle(int position) {
return mContext.getResources().getStringArray(R.array.tabs)[position];
}
#Override
public int getCount() {
return TAB_COUNT;
}
}
Listeners to change tab :
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onPageSelected(int position) {
TabLayout.Tab tab = tabLayout.getTabAt(position);
if (tab != null) {
tab.select();
}
}
Adapter setting
private void setUpTab() {
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), this);
for (int i = 0; i < viewPagerAdapter.getCount(); i++) {
tabLayout.addTab(
tabLayout.newTab()
.setText(viewPagerAdapter.getPageTitle(i)));
}
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
viewPager.setAdapter(viewPagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
viewPager.addOnPageChangeListener(this);
tabLayout.addOnTabSelectedListener(this);
}
getItem gets called every time the adapter creates a new page for the first time. The reason you see it being called twice is that the viewPager prepares the next page in advance, so if you enter page 1, page 2 is already being created too for faster paging when you swipe right.
To help you further please show us the code for NewsFragment.
Also, you might consider using FragmentPagerAdapter instead of FragmentStatePagerAdapter because you seem to have a fixed number of tabs (5 in your example) and according to the documentation that is the use case for FragmentPagerAdapter.
Documentation from the page I linked above:
This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs.
I am working on the following screen named FriendListActivity:
As you can see here , I am 3 tabs named CHAT,GROUPS and CONTACTS .Each tab is displaying some contents.For example Groups Tab is displaying the number of groups.On clicking each Group ,Group Chat Screen is opened .Now In Group Chat screen ,i have a toolbar .Consider the following code:
Toolbar toolbarGroupChat = (Toolbar) findViewById(R.id.toolbarGroupChat);
setSupportActionBar(toolbarGroupChat);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(upperCase(group_name));
//ViewPager
viewPager = (ViewPager) findViewById(R.id.viewPager);
//Initializing PagerAdapter
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(pagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
PagerAdapter.java
public class PagerAdapter extends FragmentStatePagerAdapter {
private int noOfTabs;
public PagerAdapter(FragmentManager fm, int noOfTabs) {
super(fm);
this.noOfTabs = noOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
ChatFragment chatFragment = new ChatFragment();
return chatFragment;
case 1:
GroupsFragment groupsFragment = new GroupsFragment();
return groupsFragment;
case 2:
ContactsFragment contactsFragment = new ContactsFragment();
return contactsFragment;
default:
return null;
}
}
#Override
public int getCount() {
return noOfTabs;
}
}
On clicking the arrow on the toolbar ,my application is moved to the screen containing three tabs.My problem is current selected tab is always CHAT tab ,when i am moving from an activity to FriendListActivity .When i am moving from Group Chat Screen to FriendListActivity,the current selected tab should be GROUPS Tab.
Solved.
Edited Working Code:
When we are moving from an Activity to a specific tab ,We need to pass the TAb number using intents from the Activity.Use the following code for handling click on the back button of the Toolbar .Override the getSupportParentActivityIntent() method:
public Intent getSupportParentActivityIntent() {
final Bundle bundle = new Bundle();
final Intent intent = new Intent(this, FriendsListActivity.class);
bundle.putString("TabNumber", tab_number);
intent.putExtras(bundle);
return intent;
}
Now inside the activity containing 3 tabs,use the following code:
final Intent intent = getIntent();
if (intent.hasExtra("TabNumber")) {
String tab = intent.getExtras().getString("TabNumber");
Log.e("TabNumberFriendList",tab);
switchToTab(tab);
}
public void switchToTab(String tab){
if(tab.equals("0")){
viewPager.setCurrentItem(0);
}else if(tab.equals("1")){
viewPager.setCurrentItem(1);
}else if(tab.equals("2")){
viewPager.setCurrentItem(2);
}
}
Use the setCurrentItem(int position) method of your ViewPager object to move to a specific tab.
You might have created a tabHost, so when it is done making, you should use -
tabHost.setCurrentTab(1);
and you can use same code with different parameters whenever you want to set another tab.
Ref
From the screenshot you must be using Tablayout, so from there you can use these two in build functions.
tabLayout.getSelectedTabPosition();
Save this tab in some variable and then onCreate set that integer value in this function..
tabLayout.getTabAt(<Your last selected tab>);
Hope this helps..:)
You can also use this piece of code:
Add public static TabToOpen = 1 in the group chat activity(say group_chat_activity).
then use setCurrentTab(group_chat_activity.TabToOpen) in onResume() of activity where your ViewPager object is to move to a specific tab. This is particularly useful when you need a button to access a particular tab in sliding activity.
I am trying to set up sliding tabs on top of an activity. I want this result :
I'm following the explanations of this example : http://developer.android.com/samples/SlidingTabsBasic/project.html
And I'm also looking at this video : https://www.youtube.com/watch?v=tRg_eDfQ8fk
I'm doing so because of this post : Action bar navigation modes are deprecated in Android L
I have 3 fragments for each of my tab. Each inflates a different layout and do different things. Now I need to connect them to my PageAdapter. I've already used an adaptor for a ListView. I used getView with the position to do my work
However with this PageAdapter I'm not sure what I need to proceed. Should I use this method to create my fragment :
public Object instantiateItem(ViewGroup container, int position) {
and if so, how should it be done ?
Thank you.
You must implement a FragmentPagerAdapter like this:
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstFragment();
case 1:
return new TwoFragment();
case 2:
return new ThreeFragment();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
and set it to viewpager adapter:
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
I want a tab layout in which, on every tab there are two fragments, One above showing a progress of a task that is completed by giving input in 3 tabs, from start to end, and another main fragment below that progress fragment that will be taking input.
That makes a title and detail in every tab, title fragment same and detail fragment (input fragment different on each tab)!
I tried all methods for two days :(
My Solution
i tried a layout that contains two framelayout for main fragment that is added into two tabs from ViewPager,showed here:
public static class ScreenSlidePagerAdapter extends
FragmentStatePagerAdapter {
public static ArrayList<Fragment> tabs_fragments = new ArrayList<Fragment>(
3);
public ScreenSlidePagerAdapter(FragmentManager fm,
ArrayList<Fragment> tabs) {
super(fm);
ScreenSlidePagerAdapter.tabs_fragments = tabs;
}
#Override
public Fragment getItem(int arg0) {
return tabs_fragments.get(arg0);
}
#Override
public int getCount() {
return tabs_fragments.size();
}
#Override
public int getItemPosition(Object object) {
if (tabs_fragments.contains(object)) {
return POSITION_UNCHANGED;
}
return POSITION_NONE;
}
public static void setItem(Fragment fr, int position) {
if (position <= 2 && position >= 0) {
tabs_fragments.remove(position);
tabs_fragments.add(position, fr);
} else
Log.d("adding tab", "wrong tab position to add fragment at");
}
}
On activity start i do this, see i get tab position that is used in main fragment for loading detail fragment for different tab positions:
mPager = (ViewPager) findViewById(R.id.pager);
// fragments for pagers
ArrayList<Fragment> tabs = new ArrayList<Fragment>();
tabs.add(new FrEventDetails());
tabs.add(new FrEventDetails());
tabs.add(new FrRuleSave());
mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager(), tabs);
mPager.setAdapter(mPagerAdapter);
bar = getActionBar();
bar.setTitle("Add Rule");
bar.setSubtitle("select event for rule");
bar.setDisplayShowTitleEnabled(true);
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.setDisplayHomeAsUpEnabled(true);
bar.addTab(bar.newTab().setText("Select Event")
.setTabListener(new TabListener(mPager)));
bar.addTab(bar.newTab().setText("Select Action")
.setTabListener(new TabListener(mPager)));
bar.addTab(bar.newTab().setText("Save Rule")
.setTabListener(new TabListener(mPager)));
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// When swiping between pages, select the
// corresponding tab.
if (bar.getSelectedNavigationIndex() != position)
bar.setSelectedNavigationItem(position);
tab = position;
}
and then when this fragment is attaching to activity I add a progress layout (title( for one frame-layout and based on the selected tab, add another fragment for detail frame layout(for input).
showed here:
public class FrEventDetails extends Fragment {
Context context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = (Context) activity;
int tab = AddRule1.tab;
android.app.FragmentTransaction ft = activity.getFragmentManager()
.beginTransaction();
ft.add(R.id.fr_rule_progress_container, new FrProgress());
if (tab == 1) {
ft.replace(R.id.fr_event_input_container, new FrActionSelect(),
"cell1_1").commit();
} else if (tab == 0) {
ft.replace(R.id.fr_event_action_container, new FrEventSelect(),
"cell1_2").commit();
}
}
NOTE* layout for this main fragment is simple containing two framelayouts.
result : It shows on start a title and detail beautifully on first tab, but on second tab, only main fragment and,
when i swipe to third fragment and come back, second fragment is filled beautifully (after 1 second of showing) but 1st fragment is now empty.
i can't understand what to do with this.
please give some solution to this tearful problem of two days
To Show all Tabs at the same time in start, increase PagerOffSetLimit (to 2 in this case for 3 tabs)
For refreshing state of fragment or calling some methods on your fragment in the tab beside your current tab, use the Pager.instantiateItem method.
One second delay is because you have on the animateLayoutChanges in your xml.