Android Programming The Big Nerd Ranch Guide, 3rd Edition

(Brent) #1

For the More Curious: Laying Out Views in Code


225

When would you need to implement the PagerAdapter interface yourself? When you want ViewPager
to host something other than Fragments. If you want to host normal View objects in a ViewPager, like a
few images, you implement the raw PagerAdapter interface.


So why is ViewPager not a RecyclerView?


Using a RecyclerView in this case would be a lot of work because you could not use your existing
Fragment. An Adapter expects you to provide a View instantly. However, your FragmentManager
determines when your fragment’s view is created, not you. So when RecyclerView comes knocking at
your Adapter’s door for your fragment’s view, you will not be able to create the fragment and provide
its view immediately.


This is the reason ViewPager exists. Instead of an Adapter, it uses PagerAdapter. PagerAdapter is
more complicated than Adapter because it does more of the work of managing views than Adapter
does. Here are the basics.


Instead of an onBindViewHolder(...) method that returns a view holder and its corresponding view,
PagerAdapter has the following methods:


public Object instantiateItem(ViewGroup container, int position)
public void destroyItem(ViewGroup container, int position, Object object)
public abstract boolean isViewFromObject(View view, Object object)


PagerAdapter.instantiateItem(ViewGroup, int) tells the pager adapter to create an item view for a
given position and add it to a container ViewGroup, and destroyItem(ViewGroup, int, Object) tells
it to destroy that item. Note that instantiateItem(ViewGroup, int) does not say to create the view
right now. The PagerAdapter could create the view at any time after that.


Once the view has been created, ViewPager will notice it at some point. To figure out which
item’s view it is, it calls isViewFromObject(View, Object). The Object parameter is an
object received from a call to instantiateItem(ViewGroup, int). So if ViewPager calls
instantiateItem(ViewGroup, 5) and receives object A, isViewFromObject(View, A) should return
true if the View passed in is for item 5, and false otherwise.


This is a complicated process for the ViewPager, but it is less complicated for the PagerAdapter,
which only needs to be able to create views, destroy views, and identify which object a view comes
from. This loose requirement gives a PagerAdapter implementation enough wiggle room to create and
add a new fragment inside instantiateItem(ViewGroup, int) and return the fragment as the Object
to keep track of. Then isViewFromObject(View, Object) looks like this:


@Override
public boolean isViewFromObject(View view, Object object) {
return ((Fragment)object).getView() == view;
}


Implementing all those PagerAdapter overrides would be a pain to do every time you needed to use
ViewPager. Thank goodness for FragmentPagerAdapter and FragmentStatePagerAdapter.


For the More Curious: Laying Out Views in Code


Throughout this book, you have been creating your views in layout files. It is also possible to create
your views in code.


http://www.ebook3000.com

Free download pdf