简体   繁体   中英

Interface in fragment in ViewPager.OnPageChangeListener

In my viewpager i set listener from which i call methods from my interface in tab fragments. But variable in this tab fragments in my interfaces methods always return null. Tell me why ? ps sorry for my english)

Parent fragment:

public class MyFragment
extends Fragment {

protected Context mContext;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mContext = context;
}

@Override
public void onDetach() {
    super.onDetach();
    mContext = null;
} }

Container fragment with PagerAdapter:

public class FragmentContainer
    extends MyFragment {

private ViewPager viewPager;
private ViewPager.OnPageChangeListener onPageChangeListener;

public interface IPageSelected {
    void onPageSelected();
    void onPageUnselected();
}

public static FragmentContainer newInstance() {
    return new FragmentContainer();
}

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(
            R.layout.fragment_container, container, false);

    viewPager = view.findViewById(R.id.pager);
    PagerAdapter pagerAdapter = new PagerAdapter(getFragmentManager());
    viewPager.setAdapter(pagerAdapter);

    TabLayout tabLayout = view.findViewById(R.id.tab_layout);
    tabLayout.setupWithViewPager(viewPager);

    onPageChangeListener = new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            for(int x = 0; x < pagerAdapter.getCount(); x++) {
                ((IPageSelected) pagerAdapter.getItem(x)).onPageUnselected();
            }

            ((IPageSelected) pagerAdapter.getItem(position)).onPageSelected();
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    };

    viewPager.addOnPageChangeListener(onPageChangeListener);

    return view;
}

@Override
public void onResume() {
    super.onResume();
    setCurrentItem();
}

private void setCurrentItem() {
    viewPager.post(() -> {
        viewPager.setCurrentItem(0);
        onPageChangeListener.onPageSelected(0);
    });
}


class PagerAdapter
        extends FragmentStatePagerAdapter {

    PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return TestFragment1.newInstance();
            case 1:
                return TestFragment2.newInstance();
        }
        return null;
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return "Tab1";
            case 1:
                return "Tab2";
            default:
                return null;
        }

    }
} }

Tab fragments. Question: why variable mContext in interface methods always return null ?

public class TestFragment1
    extends MyFragment
    implements FragmentContainer.IPageSelected {

public static TestFragment1 newInstance() {
    return new TestFragment1();
}

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment1, container, false);
}

@Override
public void onPageSelected() {
    Log.d("myLog", "TestFragment1 onPageSelected: " + mContext); // WHY NULL ???
}

@Override
public void onPageUnselected() {
    Log.d("myLog", "TestFragment1 onPageUnselected: " + mContext); // WHY  NULL ???
} }

public class TestFragment2
    extends MyFragment
    implements FragmentContainer.IPageSelected {

public static TestFragment2 newInstance() {
    return new TestFragment2();
}

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment2, container, false);
}

@Override
public void onPageSelected() {
    Log.d("myLog", "TestFragment2 onPageSelected: " + mContext); // WHY NULL ???
}

@Override
public void onPageUnselected() {
    Log.d("myLog", "TestFragment2 onPageUnselected: " + mContext); // WHY  NULL ???
} }

In your fragment container :

PagerAdapter pagerAdapter = new PagerAdapter(getFragmentManager()); here is the fault.

In order to attach your child fragments to your container fragment, consider passing child fragment manager getChildFragmentManager() to your viewpager adapter. (Right now your fragments are attached to same level as your container fragment) .

I found solution.
Adapter class.
Old:

    class PagerAdapter
        extends FragmentStatePagerAdapter {

    PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return TestFragment1.newInstance();
            case 1:
                return TestFragment2.newInstance();
        }
        return null;
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return "Tab1";
            case 1:
                return "Tab2";
            default:
                return null;
        }

    }
}

New:

    class PagerAdapter
        extends FragmentStatePagerAdapter {

    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

Adapter initialization.
Old:

PagerAdapter pagerAdapter = new PagerAdapter(getFragmentManager());
viewPager.setAdapter(pagerAdapter);

New:

PagerAdapter pagerAdapter = new PagerAdapter(getFragmentManager());
pagerAdapter.addFragment(TestFragment1.newInstance(), "tab1");
pagerAdapter.addFragment(TestFragment2.newInstance(), "tab2");
viewPager.setAdapter(pagerAdapter);

And now new question: what's the differense with the first option ?
Now i initializing adapter in container fragment, it's a cause ?
Why didn't work when initializing was in the adapter ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM