0

I followed this tutorial to implement ViewPager (without creating a tablayout) : https://www.javacodegeeks.com/2013/04/android-tutorial-using-the-viewpager.html

It works, but I have a trouble :

When I try to do findFragmentById(R.id.my_fragment), it returns me null. And I think it's because that in my activity_main.xml there is nothing else than ViewPager

I've tried to add a <fragment> in my activity_main.xml, now I can access my fragment by using findFragmentById(R.id.my_fragment) but my ViewPager doesn't work right now

There is a way to get an access to my Fragment ? I need to access his views.

Here is my activity_main.xml :


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.viewpager.widget.ViewPager
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>`enter code here`

Here is my MainActivity's onCreate


public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView((int) R.layout.activity_main);
        scan_fragment = (ScanFragment) getSupportFragmentManager().findFragmentById(R.id.scan_fragment);
        nfcButton = (ImageButton) findViewById(R.id.nfc_button);
        integrator = new IntentIntegrator(this);
        pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        //
        anim = ObjectAnimator.ofFloat(this.nfcButton, "scaleX", new float[]{0.9f});
        anim2 = ObjectAnimator.ofFloat(this.nfcButton, "scaleY", new float[]{0.9f});
        List<Fragment> fragments = getFragments();
        pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
        ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
        pager.setAdapter(pageAdapter);
    }

    private List<Fragment> getFragments() {
        List<Fragment> fList = new ArrayList<Fragment>();
        fList.add(ScanFragment.newInstance("Fragment 1"));
        fList.add(WebFragment.newInstance("Fragment 2"));
        return fList;
    }

MyPageAdapter


class MyPageAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;

    public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

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


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

The important part of my Fragment :


    public interface OnButtonClickedListener {
        public void onButtonClicked(View view);
    }

    public static final ScanFragment newInstance(String message)
    {
        ScanFragment f = new ScanFragment();
        Bundle bdl = new Bundle(1);
        bdl.putString(EXTRA_MESSAGE, message);
        f.setArguments(bdl);
        return f;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_scan, container, false);
        mainActivity = (MainActivity) getActivity();
        MainActivity.display = 0;
        qrButton = (ImageButton) view.findViewById(R.id.main_button);
        nfcButton = (ImageButton) view.findViewById(R.id.nfc_button);
        anim = ObjectAnimator.ofFloat(this.nfcButton, "scaleX", new float[]{0.9f});
        anim2 = ObjectAnimator.ofFloat(this.nfcButton, "scaleY", new float[]{0.9f});
        nfcButton.setOnClickListener(this);
        qrButton.setOnClickListener(this);
        return view;
    }

And my fragment's XML just contains few buttons and images

andronoob
  • 21
  • 4
  • 1
    please, post your xml and fragment/activity code – Maksym V. Feb 26 '20 at 12:06
  • yep, i've edited my post :) – andronoob Feb 26 '20 at 12:24
  • you can direct use view_pager current item instead of find by id – Avinash Feb 26 '20 at 12:28
  • how that ? for example, from my MainActivity, I'd like to access to a text (for exemple) with which i'm working in my Fragment Like this : ```scan_fragment = (ScanFragment) getSupportFragmentManager().findFragmentById(R.id.scan_fragment);``` Then : ```scan.fragment.my_text = 'foo';``` – andronoob Feb 26 '20 at 12:32
  • i tried this ```List frags = getFragments(); scan_fragment = (ScanFragment) frags.get(0);``` but it still don't works – andronoob Feb 26 '20 at 13:15
  • When i display it : ```D/Debug: ScanFragment{9b35a0f (a97bc6cd-0d3e-464c-98ce-a645b240cb53)}``` So it's not null But if i do ```scan_fragment.mybutton``` it's null... I really don't get it – andronoob Feb 26 '20 at 13:58
  • I'm sorry to disappoint you, but that Tutorial you are following is BROKEN and you should not follow it. See #3 in https://proandroiddev.com/the-seven-actually-10-cardinal-sins-of-android-development-491d2f64c8e0, follow this gist https://gist.github.com/Zhuinden/c643f03a023a9cbe83fff6c75c948d3b#file-myfragmentpageradapter-kt and refer to https://stackoverflow.com/a/54280113/2413303 – EpicPandaForce Feb 26 '20 at 22:34

2 Answers2

0

I'm sorry to disappoint you, but that Tutorial you are following is BROKEN and you should not follow it.

.

class MyFragmentPagerAdapter(
    private val context: Context,
    fragmentManager: FragmentManager
) : FragmentPagerAdapter(fragmentManager) {
    override fun getCount() = 2

    override fun getItem(position: Int) = when(position) {
        0 -> FirstFragment()
        1 -> SecondFragment()
        else -> throw IllegalStateException("Unexpected position $position")
    }

    override fun getPageTitle(position: Int): CharSequence = when(position) {
        0 -> context.getString(R.string.first)
        1 -> context.getString(R.string.second)
        else -> throw IllegalStateException("Unexpected position $position")
    }
}

class ParentFragment: Fragment() {
    override fun onCreateView(...) = ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewPager.adapter = MyFragmentPagerAdapter(requireContext(), childFragmentManager)
        tabLayout.setupWithViewPager(viewPager)
    }
}

And

Fragment fragment = childFragmentManager.findFragmentByTag("android:switcher:" + viewPager.getId() + ":" + fragmentPosition);
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
-1

Perhaps the error occurs because ViewPager does not keep all the fragments active, only the current one and the other 2 at its side in onPause (). The others do not have the views created for the Activity, but we can access them through the ViewPager since the instances of the Fragments have been saved.

I hope the following code can help you:

/******************************************/
    //Your ADAPTER.
    class MyPageAdapter extends FragmentPagerAdapter {

        private List<Fragment> fragments;

        //Your code...


        /**
         * Use this method for get the fragments list.
         */
        public List<Fragment> getFragments(){
            return fragments;
        }

    }


    /******************************************/
    //In your ACTIVITY.
    private List<Fragment> getFragments() {
        pageAdapter.getFragments();
    }

    /**
    * Use this to find a view and cast for your needs.
    */
    private View findById(int fragmentIndex, int viewId){
        Fragment fragment = this.getFragments().get(fragmentIndex);
        View view = ((YourFragment) fragment).getView(); //Casting to YourFragment and catching root view.
        return view.findViewById(viewId);
    }



    /******************************************/
    //In your FRAGMENTS.
    //Must save fragment rootView to access to findById() method. For example:
    public class YourFragment extends Fragment{

        private View view;

        @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                     Bundle savedInstanceState) {
                view = inflater.inflate(R.layout.fragment_scan, container, false);
                //Your code....
                return view;
        }

        public View getView(){
            return view;
        }

    }
jesusd0897
  • 33
  • 7