Accessing Fragment from viewpager returns null everytime? - android

My host activity has a viewpager with two fragments A and B.My activity code looks like this:
public class MainActivity extends AppCompatActivity implements
OnDataLoadedListener {
private ViewPager pager;
private MyPagerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pager = (ViewPager) findViewById(R.id.pager);
adapter = new MyPagerAdapter(getSupportFragmentManager());
pager.setAdapter(adapter);
final int pageMargin = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 4, getResources()
.getDisplayMetrics());
pager.setPageMargin(pageMargin);
tabLayout.setupWithViewPager(pager);
}
public class MyPagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = { "A",
"B" };
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return A.getInstance();
case 1:
return B.getInstance();
}
return null;
}
}
public Fragment findFragmentByPosition(int position) {
return getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + pager.getId() + ":"
+ adapter.getItemId(position));
}
Now when activity start viewpager get populated with fragment properly and I try to access fragmentby using following code:
if (AFragment == null)
AFragment = (A) findFragmentByPosition(0);
if (BFragment == null)
BFragment = (B) findFragmentByPosition(1);
But AFragment and BFragment always contains null.I have read other simmilar question but it didn't help either.I need access to fragments as I want to call some methods defined in fragment from host activity.
Code to get an instance of fragment:
public static AFragment getInstance() {
AFragment fragment = new AFragment();
return fragment;
}

I'm think that the problem is that you need to move the method to the Adapter, because you need the original instance of the FragmentManager :
public class MyPagerAdapter extends FragmentPagerAdapter {
FragmentManager fm;
private final String[] TITLES = { "A",
"B" };
public MyPagerAdapter (FragmentManager fm) {
super(fm);
this.fm = fm;
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return A.getInstance();
case 1:
return B.getInstance();
}
return null;
}
public Fragment findFragmentByPosition(int position, int pagerId) {
return fm.findFragmentByTag(
"android:switcher:" + pagerId + ":"
+ getItemId(position));
}
}
So now you can call:
adapter.findFragmentByPosition(position, pager.getId());

Related

How can I add a PreferenceFragment in a ViewPager?

All my fragments are android.support.v4.app.Fragment and the Viewpager extends FragmentStatePagerAdapter which also uses android.support.v4.app.Fragment.
I have a Fragment class which extends PreferenceFragment that I want to add in my Viewpager with my other two fragments.
How can I accomplish this?
Here's my ViewPager
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> mFragments = new ArrayList<>();
private ArrayList<String> mFragmentsTitle = new ArrayList<>();
public void addFragment(Fragment fragment, String title){
mFragments.add(fragment);
mFragmentsTitle.add(title);
}
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
#Override
public int getCount() {
return mFragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentsTitle.get(position);
}
}
Here's what I have in my PreferenceFragment
public class GameNotesFragment extends PreferenceFragment {
public GameNotesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_game_notes, container, false);
return view;
}
}
When I try to add it in:
mSectionsPagerAdapter.addFragment(new GameNotesFragment(), "Note");
It gives me
Wrong firt argument com.example.fragments.GameNotesFragment', required: 'android.support.v4.app.Fragment'
PreferenceFragment extends the platform variant of the Fragment class. What you need is a PreferenceFragmentCompat that extends the support lib variant of Fragment (mind the different packages).
The support preferences require additional package(s) in your gradle file:
implementation 'com.android.support:preference-v7:27.1.0'
implementation 'com.android.support:preference-v14:27.1.0'
Also, while you're at it, make sure to check out the bug fix lib I created for the support preferences' common (and pretty annoying) bugs.
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> mFragments = new ArrayList<>();
private ArrayList<String> mFragmentsTitle = new ArrayList<>();
public void addFragment(Fragment fragment, String title){
mFragments.add(fragment);
mFragmentsTitle.add(title);
}
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
android.support.v4.app.Fragment f = null;
if (position == 0) {
f = new GameNotesFragment();
}
if (position == 1) {
f = new GameNotesFragment(); //replace your fragment 2
}
if (position == 2) {
f = new GameNotesFragment();//replace your fragment 3
}
return f;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getResources().getString(R.string.name1);
case 1:
return getResources().getString(R.string.name2);
case 2:
return getResources().getString(R.string.name3);
return null;
}
}
and in activity:
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(MainActivity.this.getSupportFragmentManager());
tabLayout = v1.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));

Android - ViewPager third tab has not shown

i have a viewPager that contains 3 tabs fragments.
the first and the second fragments works fine but when i sweep to the third tab
i do not see him.
the third tab has shown only when the activity with the viewPager has reload(move to another activity and return).
my code:
private void setupViewPager(ViewPager viewPager) {
adapter = new PagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment1(), Constants.TAB_0);
adapter.addFragment(new Fragment2(), Constants.TAB_1);
adapter.addFragment(new Fragment3(), Constants.TAB_2);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
}
pager adapter:
public class PagerAdapter extends FragmentPagerAdapter {
/*
* Arraylist used to contain the fragments
* and contain fragments title's
*/
private final List<Fragment> fragmentList = new ArrayList<>();
private final List<String> fragmentTitleList = new ArrayList<>();
public PagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return fragmentList.size();
}
//Adds the fragment and it's title. Called in MainActivity
public void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
//Retrieves the title of the tab
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
Here is my adapter, on getItem I set the fragment object to the Fragment activity.
public class SectionPagerAdapter extends FragmentPagerAdapter {
Fragment fragment;
public SectionPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 0){
fragment = new FragmentOne();
}
else if (position == 1){
fragment = new FragmentTwo();
}
else if (position == 2){
fragment = new FragmentThree();
}
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "name one";
case 1:
return "name two";
case 2:
return "name three";
}
return null;
}
}
Then in my main activity I call it like so:
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
SectionPagerAdapter sectionPagerAdapter = new SectionPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(sectionPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
Try replacing your code with above and let me know if it helps!
USE new PagerAdapter(getChildSupportFragmentManager());instead of getSupportFragmentManager()
Try this one !!

Android: How to set tag to fragments in FragmentPagerAdapter?

Here's the inner class that contains fragments and changes fragment views on swipe. This class is defined in an Activity.
private class ViewPagerAdapter extends FragmentPagerAdapter {
private int count;
ViewPagerAdapter(FragmentManager fm, int count) {
super(fm);
this.count = count;
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new FriendsListFragment();
case 1:
Bundle bundle = new Bundle();
bundle.putString(Keys.TAG, ChatListFragment.class.getSimpleName());
ChatListFragment chatListFragment = new ChatListFragment();
chatListFragment.setArguments(bundle);
return chatListFragment;
case 2:
return new MoreFragment();
default:
return null;
}
}
#Override
public int getCount() {
return count;
}
}
Here I would like to add a code that sets tags to each fragment, so that I can recognize which fragment I'm at.
I searched quite much, and I haven't found a proper answer for this question, so please help.
You can override the setPrimaryItem method of your FragmentPagerAdapter.
private class ViewPagerAdapter extends FragmentPagerAdapter {
protected int currentPosition = -1;
protected Fragment currentFragment;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// ....
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
this.currentPosition = position;
if (object instanceof Fragment) {
this.currentFragment = (Fragment) object;
}
}
public int getCurrentPosition() {
return currentPosition;
}
public Fragment getCurrentFragment() {
return currentFragment;
}
}
Just use getCurrentPosition or getCurrentFragment methods to get information about current Fragment.

unable to set the FragmentStatePagerAdapter in ViewPager

I would like to set the object of subclass of FragmentStatePagerAdapter in ViewPager by the method
viewPager.setAdapter(myPagerAdapter);
But i got error as follows
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.Fragment.setMenuVisibility(boolean)' on a null object reference
at android.support.v4.app.FragmentStatePagerAdapter.instantiateItem(FragmentStatePagerAdapter.java:120)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:1006)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1154)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1088)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1614)
Please help me to fix this issue.
The code snippet is
public class MainActivity extends AppCompatActivity {
Toolbar toolbar;
TabLayout tabLayout;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar)findViewById(R.id.toolbar);
toolbar.setTitle("My App");
toolbar.setSubtitle("this is my test");
tabLayout = (TabLayout)findViewById(R.id.tablayout);
tabLayout.addTab(tabLayout.newTab().setText("Left"));
tabLayout.addTab(tabLayout.newTab().setText("Cent"));
tabLayout.addTab(tabLayout.newTab().setText("Right"));
viewPager = (ViewPager)findViewById(R.id.viewpage);
MyPagerAdapter myPagerAdapter = new MyPagerAdapter(
getSupportFragmentManager(),
tabLayout.getTabCount()
);
viewPager.setAdapter(myPagerAdapter);
//viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
}
}
public class MyPagerAdapter extends FragmentStatePagerAdapter {
int tabCount;
public MyPagerAdapter(FragmentManager fm, int tabCount) {
super(fm);
this.tabCount = tabCount;
}
#Override
public Fragment getItem(int position) {
switch (position){
case 1:
Fragment1 fragment1 = new Fragment1();
return fragment1;
case 2:
Fragment2 fragment2 = new Fragment2();
return fragment2;
case 3:
Fragment3 fragment3 = new Fragment3();
return fragment3;
default:
return null;
}
}
#Override
public int getCount() {
return tabCount;
}
}
While you should probably be using tabLayout.setupWithViewPager(viewPager);
Here's the problem
switch (position){
// case 1, 2, 3...
default:
return null; // Here
Did you forget that lists start indexing at position 0? You've returned a null Fragment
Try the following.
MyPagerAdapter.java
public class MyPagerAdapter extends FragmentStatePagerAdapter {
private Context mContext;
private List<Fragment> mFragments = new ArrayList<>();
public FragmentPagerAdapter(Context context, FragmentManager fm) {
super(fm);
this.mContext = context;
}
public void addFragment(Fragment fragment) {
mFragments.add(fragment);
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
#Override
public int getCount() {
return mFragments.size();
}
}
In your MainActivity,
private void setUpViewPager(ViewPager viewPager) {
adapterViewPager = new MyPagerAdapter(getApplicationContext(), getSupportFragmentManager());
adapterViewPager.addFragment(new AFragment());
viewPager.setAdapter(adapterViewPager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void setUpTabLayout(TabLayout tabLayout) {
tabLayout.setupWithViewPager(viewPager);
for (int i = 0; i < tabLayout.getTabCount(); i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
//set your tab text, image etc here.
}
tabLayout.requestFocus();
}
Then in your onCreate(), just use the methods accordingly. setUpViewPager() follow by setUpTabLayout()

Lock page fragment in ViewPager android

How can I lock paging in fragment activity of viewpager for fragment swipe.I'm performing some operations using progressbar in one fragment.While progressing progressbar fragment gets changes because of swipe action.so while progessing progressbar I want to stop swiping.How to do this?is there any solution??
activity.xml file-
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainFragmentActivity" >
<android.support.v4.view.PagerTitleStrip
android:id="#+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#drawable/title"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:textColor="#fff" />
</android.support.v4.view.ViewPager>
fragment activity-
public class MainFragmentActivity extends FragmentActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
private Context mContext;
private PagerTitleStrip pt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(),mContext);
mContext=this;
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
pt=(PagerTitleStrip) findViewById(R.id.pager_title_strip);
}
SectionsPagerAdapter-
public class SectionsPagerAdapter extends FragmentPagerAdapter {
Context mContext;
Fragment fragment;
public SectionsPagerAdapter(FragmentManager fm, Context context) {
super(fm);
mContext=context;
}
#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.
if(position==0){
fragment = new SelectItem();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
}
if(position==1){
fragment = new culation();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
}
if(position==2){
fragment = new GraphDisplay();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
}
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0 :
return "Select item";
case 1:
return "Calculation";
case 2:
return "Graph";
}
return null;
}
}
Try setting clickable to false:
mViewPager.setClickable(false);
If that works what you can do is create a function in activity to disable swipe event on view pager and call that function in fragment in event of progress bar show and a function to enable it.
Subclass ViewPager and override onTouch event for example:
EDIT
public class NonSwipeableViewPager extends ViewPager {
private boolean lock;
public void lock(){
lock=true;
}
public void unlock(){
lock=false;
}
public NonSwipeableViewPager(Context context) {
super(context);
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(lock)
return false;else{
return super.onTouchEvent(event);
}
}
}
reference:
How do disable paging by swiping with finger in ViewPager but still be able to swipe programmatically?
I found a simple way to do this, with its adapter.
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
/**
* Created by paul.boldijar on 2/24/2015.
*/
public class SimpleFragmentAdapter extends FragmentPagerAdapter {
private Fragment[] fragments;
private boolean locked = false;
private int lockedIndex;
public void setLocked(boolean locked, int page) {
this.locked = locked;
lockedIndex = page;
notifyDataSetChanged();
}
public SimpleFragmentAdapter(FragmentManager fm, Fragment[] fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
if (locked) return fragments[lockedIndex];
return fragments[position];
}
#Override
public int getCount() {
if (locked) return 1;
return fragments.length;
}
}
If you want to lock your fragment to a page, just call fragment.setLocked(true,page);
Where page is the index of the page you want to lock.
Based on the solution by Paul, I modified it to support displaying titles as well
public static class MainPagerAdapter extends FragmentStatePagerAdapter {
private Fragment[] fragments;
private String[] titles;
private boolean locked = false;
private int lockedIndex;
public MainPagerAdapter(FragmentManager fm, Fragment[] fragments, String[] titles) {
super(fm);
this.fragments = fragments;
this.titles = titles;
}
public void setLocked(boolean locked, int page) {
this.locked = locked;
lockedIndex = page;
notifyDataSetChanged();
}
#Override
public Fragment getItem(int position) {
if (locked) return fragments[lockedIndex];
return fragments[position];
}
#Override
public int getCount() {
if (locked) return 1;
return fragments.length;
}
#Override
public CharSequence getPageTitle(int position) {
if (locked) return titles[lockedIndex];
return titles[position];
}
}
The way I use it is to say
Fragment[] fragments = {//Create fragment objects here...};
String[] titles = getResources().getStringArray(R.array.tabs);
MainPagerAdapter adapter = new MainPagerAdapter(getSupportFragmentManager(), fragments, titles);
adapter.setLocked(true, 0);
mPager.setAdapter(adapter);
You can use this View:
https://github.com/mr-sarsarabi/lockableViewPager
It lets you lock the swipe gesture with a method: viewPager.setSwipeLocked(true);

Categories

Resources