Chap 11 Challenge - First and Last Buttons


#1

Implemented my UI and added buttons to CrimeFragment. Struggled with hooking up to the ViewPager, but found something that seems to work. Any comments?

    mLastButton = (Button)v.findViewById(R.id.last_crime);
    mLastButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("CrimeFragment", "last");
            ViewPager mViewPager = (ViewPager)getActivity().findViewById(R.id.crime_view_pager);
            mViewPager.setCurrentItem(CrimeLab.get(getActivity()).getCrimes().size()-1);
        }
    });

<


#2

While that would work really well, it breaks the encapsulation because now CrimeFragment has to know about ViewPager. A possible alternative solution could be to subclass CrimeFragment, add the 2 buttons to that subclass and create and interact with that fragment in CrimePagerActivity.

However, the challenge said to “Add two buttons to CrimePagerActivity that allow jumping the ViewPager to the first or last crime instantly.” I assume that the author meant that CrimePagerActivity activity would add the 2 buttons to the CrimeFragment as well as the 2 listeners to go to first or last crimes.

I would like to try to do this but I can’t figure out how to get a reference to the CrimeFragment’s view from the CrimePagerActivity so that the 2 buttons could be added.


#3

Excellent point. It seems like the idea would be to have CrimePagerActivity’s layout file (activity_crime_pager.xml) consist of the ViewPager on top and another layout item with the two buttons on the bottom. Then the buttons need only be defined in CrimePagerActivity. Would this be possible?


#4

Yea, the best way to solve this challenge would be to have those buttons exist at the Activity level rather than the fragment level.

You can add views to your activity’s layout file in addition to the container for the Fragment. So, you could do something like this in the Activity’s layout file:

<FrameLayout...>
  <ViewPager.../>
  <FrameLayout...>
    <Button.../>
    <Button.../>
  </FrameLayout>
</FrameLayout>

#5

Thanks. Off to Studio!


#6

Thanks! That was the hint I was looking for! Also, instead of making my root layout a FrameLayout I used ConstraintLayout which made it easier for me.


#7

Great! ConstraintLayout will work too. It’s a subclass of FrameLayout, so the view positioning behavior will be the same.


#8

If using a FrameLayout (instead of a LinearLayout for example), how do you prevent the ViewPager area from extending down into the FrameLayout area that includes the two Buttons? I can see how to do this with a LinearLayout or ConstraintLayout, but the FrameLayout seems less obvious…


#9

If you do not want the buttons to overlap the ViewPager area, then you would have to switch over to a LinearLayout at the root level. Something like this:

<LinearLayout
  android:orientation="vertical"
  ...>
  <ViewPager
    android:layout_height="0dp"
    android:layout_weight="1"
    .../>
  <FrameLayout
    android:layout_height="wrap_content"
    ...>
    <Button.../>
    <Button.../>
  </FrameLayout>
</LinearLayout>

#10

Ok, that makes sense – thanks!


#11

I suppose mine is highly inefficient :man_facepalming: Your layout is more flatter, whereas mine looks like below:

<RelativeLayout>
    <ViewPager/>
    <LinearLayout>
        <Button/>
        <Button/>
    </LinearLayout>
</RelativeLayout>

Yes, I also decided to control the buttons within the Activity rather than the Fragment. I would like to discuss my answer but I do not know if this is the right place. I do dread giving away spoilers :grin: