I'm making a score keeping app using tabs, tablayout, fragments, and a FragmentPagerAdapter. The app runs fine, but I can't figure out how I can access the fragments. After doing some work in the fragment, I want to access the fragment to update its score. How can I access the current fragment?
Edit - my main problem is finding the position. I can use tabLayout.getSelectedTabPosition() to get the correct position if I clicked on the tab, but if I swipe between tabs, viewpager handles it differently and I don't know how to find the position from that.
public class PagerAdapter extends FragmentPagerAdapter {
private int numTabs;
public PagerAdapter(FragmentManager fm, int tabs) {
super(fm);
numTabs = tabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return makeScoreFrag(1, "Team 1");
case 1:
return makeScoreFrag(2, "Team 2");
case 2:
return makeScoreFrag(3, "Team 3");
case 3:
return makeScoreFrag(4, "Team 4");
default:
return null;
}
}
#Override
public int getCount() {
return numTabs;
}
private ScoreFragment makeScoreFrag(int num, String title){
Bundle bundle = new Bundle();
bundle.putInt("score", 0);
bundle.putInt("number", num);
bundle.putString("title", title);
ScoreFragment frag = new ScoreFragment();
frag.setArguments(bundle);
return frag;
}
}
You can Override instantiateItem method in FragmentPagerAdapter
ScoreFragment[] fragments = new ScoreFragment[numTabs];
#Override
public Object instantiateItem(ViewGroup container, final int position) {
fragments[position] = (ScoreFragment) super.instantiateItem(container, position);
return fragments[position];
}
Then current fragment is:
ScoreFragment curFragment = fragments[curTab];
Related
I have an Activity that is using viewpager and fragments with tabs. I pass data from the activity to the Fragments but it is always showing the wrong data for the specific tabs. I have one fragment which is supposed to query data depending on the arguments passed through the bundle.
private Fragment createFragment(String title){
HomeFragment fragment = new HomeFragment();
Bundle bundle = new Bundle();
bundle.putString("category",title);
fragment.setArguments(bundle);
return fragment;
}
Then I pass this function on the viewpager like so:
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(createFragment("Item 1"),"Tab 1");
adapter.addFragment(createFragment("Item 2"),"Tab 2");
adapter.addFragment(createFragment("Item 3"),"Tab 3");
adapter.addFragment(createFragment("Item 4"),"Tab 4");
adapter.addFragment(createFragment("Item 5"),"Tab 5");
Lastly I get the argument passed like so:
String argument = this.getArguments().getString("category");
the problem is when I'm on Tab 1, It returns Item 2. But when I visit all tabs, it starts to return the correct item i.e. Item 1 when on Tab 1.
Where is the problem?
EDIT:
the ViewPagerAdapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragList = new ArrayList<>();
private final List<String> titleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragList.get(position);;
}
public void addFragment(Fragment fragment, String title) {
fragList.add(fragment);
titleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return titleList.get(position);
}
#Override
public int getCount() {
return fragList.size();
}
}
Maybe you could create the adapter class and make sure you're passing the right fragment on the right position. It might be a problem with the adapter adding the fragments on the wrong position the way you are instantiating them.
class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 1: return createFragment("Item 1"),"Tab 1");
case 2: return createFragment("Item 2"),"Tab 2");
case 3: return createFragment("Item 3"),"Tab 3");
case 4: return createFragment("Item 4"),"Tab 4");
case 5: return createFragment("Item 5"),"Tab 5");
}
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
I'm using fragmentpageradapter to inflate fragment , this is my coding.
i'm adding cart item in one fragment and showing it to other fragment and all fragment comes in tab layout.My problem is cart item is not refreshing on other fragment while swiping fragment.
public class ProfileDetailePagerAdapter extends FragmentPagerAdapter
{
int TabCount;
HashMap<Integer, String> mFragmentTags;
FragmentManager mFragmentManager;
private boolean isPagingEnabled = true;
public ProfileDetailePagerAdapter(FragmentManager fm, int TabCount) {
super(fm);
this.TabCount = TabCount;
mFragmentTags = new HashMap<Integer, String>();
mFragmentManager = fm;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
MenuFragment tab1 = new MenuFragment();
return tab1;
case 1:
SelectMember_fragment tab2 = new SelectMember_fragment();
return tab2;
case 2:
ViewCart_fragment tab3 = new ViewCart_fragment();
return tab3;
/* case 3:
PaymentMode_fragment tab4=new PaymentMode_fragment();
return tab4;*/
}
return null;
}
#Override
public int getCount() {
return TabCount;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Object obj = super.instantiateItem(container, position);
if (obj instanceof Fragment) {
// record the fragment tag here.
Fragment f = (Fragment) obj;
String tag = f.getTag();
mFragmentTags.put(position, tag);
}
return obj;
}
public Fragment getFragment(int position) {
String tag = mFragmentTags.get(position);
if (tag == null)
return null;
return mFragmentManager.findFragmentByTag(tag);
}
}
Call FragmentStatePagerAdapter
You should use addOnTabSelectedListener
This method is used to add a listener that will be invoked when tab
selection changes.
tabLayoutOBJ.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){
public void onTabReselected(TabLayout.Tab tab) {
}
public void onTabSelected(TabLayout.Tab tab){
String getTAB = (String)tab.getText();
// Do your WORK
}
public void onTabUnselected(TabLayout.Tab tab){
}
});
The reason behind it is the implementation of viewpager. There is a property called offset in ViewPager to make ready fragments next to it up to offset(int) value.
Default value is 1. For example, you are in 1st position, 0th and 2nd positions are also created.
On the other hand if you are in 0th position 1st is the only created fragment. If you swipe to right (going 1st) then 2nd is going to be created.
I assume you are changing a shared object from 1st fragment and want to notify 2nd fragment with changed data. To solve it you need to use listener. The elegant way to solve it is adding observer pattern to your shared object.
Good luck
Emre
Like in the image below, I have an Activity with a ViewPager (with TabLayout) inside.
Now I want to refresh for example the text of an TextView in a ViewPager Fragment. How can I do this?
http://imgur.com/0kWQCfx
[Sorry for the image link, but I don't have enough reputations yet.]
I already tried something like this:
//In Activity
View root = getLayoutInflater().inflate(R.layout.fragment_home, null);
TextView textView = (TextView) root.findViewById(R.id.text_view);
textView.setText("test");
But I get a NullPointerException for the textView.
Edit 1:
I only need to access the components inside one Fragment, so I am not using an array inside the Adapter.
I changed my ViewPagerAdapter to this:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public HomeFragment fragment;
...
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return fragment = new HomeFragment();
case 1:
...
default:
return null;
}
}
But I still get a NullPointerException here:
final Fragment root = viewPagerAdapter.fragment;
Log.d("testtest", String.valueOf(root == null));
Write this code in your activity where you want to change fragment value. Your fragment id is e.g. my_fragment
Fragment frag = getFragmentManager().findFragmentById(R.id.my_fragment)
((TextView) frag.getView().findViewById(R.id.text_view)).setText(s);
You can create your own Adapter:
private class YourAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener
{
Fragment screens[];
public CheckinHistoryAdapter(FragmentManager fm) {
super(fm);
screens = new Fragment[3];
screens[0] = new CoachFragment();
screens[1] = new LogingFragment();
screens[2] = new HistoryFragment();
}
#Override
public Fragment getItem(int index) {
if(index <= screens.length)
{
return screens[index];
}
return null;
}
#Override
public int getCount() {
return screens.length;
}
}
Use it like this
mViewPager.setAdapter(this.mPagerAdapter);
You can access fragment object with getItem method.
If you only need a reference to one Fragment, then just use the position parameter passed into instantiateItem(), and only assign your Fragment reference for the desired position:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public HomeFragment fragment;
//...
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new HomeFragment(); //modified
case 1:
...
default:
return null;
}
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
if (position == 0) {
fragment = (HomeFragment) createdFragment;
}
return createdFragment;
}
}
I am unable to create dynamic layout for each tabs, i am able to create tabs dynamically by this constructor(public MyPagerAdapter(FragmentManager fm , int noOfTabs)), but coudn't inflate the view for each tabs creating for each fragment which should be dyanmic.
public class MyPagerAdapter extends FragmentPagerAdapter
{
private final String[] TITLES = { "Categories", "Home", "Top Paid", "Top Free", "Top Grossing", "Top New Paid",
"Top New Free", "Trending" };
int noOfTabs;
**public MyPagerAdapter(FragmentManager fm , int noOfTabs)
{
super(fm);
this.noOfTabs = noOfTabs;
}**
/*public MyPagerAdapter(FragmentManager fm)
{
super(fm);
}*/
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return noOfTabs; //TITLES.length;
}
#Override
public Fragment getItem(int position) {
return SuperAwesomeCardFragment.newInstance(position);
}
}
I am facing problem here which should be dynamic and not static as three fragments(FragmentA, FragmentB , FragmentC), it can be any number of fragments depending on the int noOfTabs:
#Override
public Fragment getItem(int position) {
Fragment fragment =null;
switch (position) {
case 0:
fragment = new FragmentA();
break;
case 1:
fragment = new FragmentB();
break;
case 2:
fragment = new FragmentC();
break; }
return fragment;
}
Thanks in advance if any one could help me in this, as i am using this with help of library PagerSlidingTabStrip.
#nbokmans solution may be okay but i've used a container to accomplish that.
Creating a simple host fragment with FrameLayout inside and by replacing fragment was a good dynamic solution for me.
Using Otto EventBus just made it awesome because it can be changed from everywhere with just simple post
#Subscribe
fun changeFragment(type: FragmentTypeEvent){
val ft = activity.supportFragmentManager.beginTransaction()
val frag = getFragment(type)
ft.replace(R.id.container_frame,frag)
ft.commit()
}
I have two ViewPagers First have 5 Views (Fragments) and Second Have 3 Fragments inside a single java file. The problem is when second view shows Fragment 1st then i can only access 3 Fragments of First ViewPager 1-3 and when second View Pager is showing 3rd Fragment then can access only 3-5 fragment means can access only 3 fragment at a time.
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a DummySectionFragment (defined as a static inner class
// below) with the page number as its lone argument.
//Log.e("Position", position+"");
if(position==0){
fragment=new AssetSelectionFragmentWallpaper();
}
else{
fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
args.putInt(DummySectionFragment.ARG_OBJECT, position+1);
fragment.setArguments(args);
}
return fragment;
}
#Override
public int getCount() {
// Show 5 total pages.
return 5;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
case 3:
return getString(R.string.title_section4).toUpperCase(l);
case 4:
return getString(R.string.title_section5).toUpperCase(l);
}
return null;
}
#Override
public int getItemPosition(Object object) {
if (object instanceof UpdateableFragment) {
((UpdateableFragment) object).update(null);
}
if(object instanceof AssetSelectionFragmentWallpaper){
return POSITION_NONE;
}
return super.getItemPosition(object);
}
}
public class SectionsPagerAdapter1 extends FragmentStatePagerAdapter {
private Fragment fragment;
private Swipe sw;
public SectionsPagerAdapter1(FragmentManager fm, Swipe s) {
super(fm);
this.sw = s;
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a DummySectionFragment (defined as a static inner class
// below) with the page number as its lone argument.
fragment = new DummySectionFragment1();
Bundle args = new Bundle();
args.putInt(DummySectionFragment1.ARG_SECTION_NUMBER, position + 1);
args.putInt(DummySectionFragment1.ARG_OBJECT, position+1);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return "SETTINGS";
case 1:
return "SHOP";
case 2:
return "CONTACTS";
case 3:
return "";
}
return null;
}
#Override
public int getItemPosition(Object object) {
// don't return POSITION_NONE, avoid fragment recreation.
return super.getItemPosition(object);
}
}
Every Object Name is Different and Globally Declared...
I think getCount() Function is conflicting to each other.
Please Help to resolve this...
Thanks...
I think you should check your XML first, if there you find any problem. or
You can fix also by declaring any RONDOM ID like _pager.setId(int);