Fragment getView() always returning null for Fragments created by a FragmentStatePagerAdapter
Asked Answered
A

1

9

I have been reading a lot about fragments. Have found other people having problems retrieving fragments view because null was always returned but no answer solved my problem. What I'm trying to do is create a image gallery. I have a Fragment that holds a image view. To show the fragments I use a android.support.v4.view.ViewPager. And to feed the ViewPager I use a android.support.v4.app.FragmentStatePagerAdapter.

The problem is that when everything is build and the images are shown I want to save the current shown image to disk. So I need to get the current fragment imageview but I can't because fragment.getView() always is null, the activity associated with the fragment is null too and I can't figure out why is it. Here some code to see if anyone could help here:

This is my Fragment:

public class ImageViewURLFragment extends Fragment 
{
    String _url;

    @Override
    public View onCreateView(LayoutInflater inflater,
            ViewGroup container, Bundle savedInstanceState) 
    {
        // The last two arguments ensure LayoutParams are inflated
        // properly.
        View rootView = new ImageViewURL(getActivity(), _url);

        return rootView;
    }

    public void setImageURL(String imgURL)
    {
        _url=imgURL;
    }
}

And this my adapter:

public class ImageViewURLCustomAdapter extends FragmentStatePagerAdapter 
{
    List<String> _urls=new ArrayList<String>();

    public ImageViewURLCustomAdapter(FragmentManager fm) 
    {
        super(fm);
    }

    @Override
    public Fragment getItem(int i) 
    {
        ImageViewURLFragment fragment = new ImageViewURLFragment();
        fragment.setImageURL(_urls.get(i));

        return fragment;
    }

    public String getItemUrl(int i)
    {
        return _urls.get(i);
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return "OBJECT " + (position + 1);
    }

    public void addImageURL(String url)
    {
        _urls.add(url);
    }
}

And this is the main activity, notice the comment with the get:

public class MainActivity extends FragmentActivity 
{
    ImageViewURLCustomAdapter _iva=null;
    ViewPager _vp=null;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        _iva = new ImageViewURLCustomAdapter(
                        getSupportFragmentManager());
        _iva.addImageURL("http://upload.wikimedia.org/wikipedia/commons/b/b4/Saturn_(planet)_large.jpg");
        _iva.addImageURL("http://planetthreesixty.com/sites/default/files/planet.jpg");

        _vp = (ViewPager) findViewById(R.id.viewpager);
        _vp.setAdapter(_iva);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
    {
        if(item.getItemId()==R.id.saveToSD)
        {
            int index= _vp.getCurrentItem();
            Fragment fragment=_iva.getItem(index);

            //THis is where I need to get fragment view, but always returns null
                    View view= fragment.getView();
            ImageView iv=(ImageView)view.findViewWithTag("imageView");
            Bitmap bmp=iv.getDrawingCache();


        }


        return super.onOptionsItemSelected(item);
    }
}

Sorry for the long sources, I have cleaned everything I could, but I wanted to present all playing parts. Could anybody guess what is hapenning?

Thanks in advance.

Astronomical answered 9/2, 2013 at 15:18 Comment(0)
J
32

So I need to get the current fragment imageview but I can't because fragment.getView() always is null, the activity associated with the fragment is null too and I can't figure out why is it.

That is happening because you're expecting _iva.getItem(index); to return the Fragment that the ViewPager uses for the page corresponding to the specified index. That will not happen as the ViewPager has already called the getItem method to get the fragments it needs and after your call the getItem method you get a new ImageViewURLFragment instance. This new instance isn't tied to the Activity(getActivity() returns null) and its view wasn't created.

As you use a FragmentStatePagerAdapter try the code below to get the currently visible Fragment:

if (item.getItemId()==R.id.saveToSD) {
     int index = _vp.getCurrentItem();
     Fragment fragment = _vp.getAdapter().instantiateItem(_vp, index);
     //...
Jehoash answered 9/2, 2013 at 16:3 Comment(6)
After searching for some more info, I would like to ask how did you get this information about instantiateItem.I mean I have read that this adapter can reuse fragments instead of creating a new one everytime, but where did you find information that we could call instantiateItem directly and that this would return a previous instance of the fragment and not a new one? And on the other hand how would you do this (get current item) for a PageView?. Thanks in advance.Astronomical
@Astronomical If you look at the source code for the FragmentStatePagerAdapter you'll see that the instantiateItem method will either return a cached fragment or a new fragment. In the case when you're looking for the current fragment it will be the cached version. And on the other hand how would you do this (get current item) for a PageView? - I don't understand what you're asking. To get the current fragment from a FragmentStatePagerAdapter you would use my code from the answer.Jehoash
Ok, thanks. I think it is common practice to read android sources for this kind of things. Thanks again for the answer.Astronomical
Excellent! Thank you for this one single line which I was looking for. Fragment fragment = _vp.getAdapter().instantiateItem(_vp, index);Bide
Works fine even beyond the scope of this question. :thumbsup:Izaguirre
THANK YOU!!! I have spend all day looking what was wrong, I didn/t know that getItem() returns new instance of a fragment (( Happy coding!Memberg

© 2022 - 2024 — McMap. All rights reserved.