Reputation: 5571
I have a ViewPager with a FragmentPageAdapter. When a fragment is displayed, I want it to start an animation (fade-in a view in the fragment).
However, the animation runs inconsistently, it runs on every few pages when I swipe left/right. I think I need to start the animation on the onPageSelected event but I can't figure out how to get the fragment and start the animation.
My code is below. TourFragment is the fragment I add to the ViewPager using the FragmentPageAdapter while TourActivty contains the ViewPager.
TourFragment
public class TourFragment extends Fragment {
Tour tour;
ImageView ivTitle;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_tour,
container, false);
RelativeLayout rlImageContainer = (RelativeLayout) v.findViewById(R.id.tour_image_container);
Resources resources = getActivity().getResources();
ivTitle = (ImageView) v.findViewById(R.id.tour_title);
ivTitle.setImageDrawable(resources.getDrawable(tour.getDrawableTitleId()));
Animation fadeInAnimation = AnimationUtils.loadAnimation(getActivity(), R.anim.fadein);
ivTitle.startAnimation(fadeInAnimation );
return v;
}
@Override
public void onResume() {
super.onResume();
Animation fadeInAnimation = AnimationUtils.loadAnimation(getActivity(), R.anim.fadein);
ivTitle.startAnimation(fadeInAnimation );
}
public static Fragment newInstance(Tour tour) {
TourFragment f = new TourFragment();
f.tour = tour;
return f;
}
}
TourActivity
public class TourActivity extends FragmentActivity {
MyPageAdapter pageAdapter;
String tourType;
Drawable drawableSelected;
Drawable drawableNotSelected;
LinearLayout llIndicators;
int prevPagePosition = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tour);
List<Fragment> fragments = getFragments();
pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
pager.setAdapter(pageAdapter);
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int i, float v, int i2) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int i) {
}
});
}
private List<Fragment> getFragments(){
List<Fragment> fList = new ArrayList<Fragment>();
List<Tour> tours = new ArrayList<Tour>();
messages = getResources().getStringArray(R.array.guess_tour_messages);
Tour tour = new Tour();
tour.setDrawableImageId(R.drawable.tu_guest_image_1);
tour.setDrawableTitleId(R.drawable.tu_guest_text_1);
tour.setMessage(messages[0]);
tour.setPageIndex(0);
tour.setTotalPages(messages.length);
tours.add(tour);
tour = new Tour();
tour.setDrawableImageId(R.drawable.tu_guest_image_2);
tour.setDrawableTitleId(R.drawable.tu_guest_text_2);
tour.setMessage(messages[1]);
tour.setPageIndex(1);
tour.setTotalPages(messages.length);
tours.add(tour);
tour = new Tour();
tour.setDrawableImageId(R.drawable.tu_guest_image_3);
tour.setDrawableTitleId(R.drawable.tu_guest_text_3);
tour.setMessage(messages[2]);
tour.setPageIndex(2);
tour.setTotalPages(messages.length);
tours.add(tour);
tour = new Tour();
tour.setDrawableImageId(R.drawable.tu_guest_image_4);
tour.setDrawableTitleId(R.drawable.tu_guest_text_4);
tour.setMessage(messages[3]);
tour.setPageIndex(3);
tour.setTotalPages(messages.length);
tours.add(tour);
for (Tour tour : tours) {
fList.add(TourFragment.newInstance(tour));
}
return fList;
}
}
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();
}
}
Upvotes: 2
Views: 6545
Reputation: 2161
I had a similar problem and here what solved it: Animation of nested fragment within ViewPager fragment is triggered before render
In context of your case the same solution would look like this:
java:
v.post(new Runnable() {
@Override
public void run() {
ivTitle.startAnimation(fadeInAnimation)
}
})
kotlin:
v.post(Runnable {
ivTitle.startAnimation(fadeInAnimation)
})
It ensures that the view is indeed drawn
Upvotes: 0
Reputation: 578
You should use in your fragment
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
Log.v(TAG, "run now");
Animation animationFadeIn = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_view);
iv.startAnimation(animationFadeIn);
animationFadeIn.setFillAfter(true);
}
else { }
}
Upvotes: 5
Reputation: 5571
I figured it out.
On onPageSelected, I used getView from the fragment to get the view that I want to animate.
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int i, float v, int i2) {
}
@Override
public void onPageSelected(int position) {
View v = pageAdapter.getItem(position).getView();
ImageView ivTitle = (ImageView) v.findViewById(R.id.tour_title);
Animation fadeInAnimation = AnimationUtils.loadAnimation(TourActivity.this, R.anim.fadein);
ivTitle.startAnimation(fadeInAnimation );
}
@Override
public void onPageScrollStateChanged(int i) {
}
});
Upvotes: 1
Reputation: 444
Inside of your FragmentPagerAdapter
implementation you you need to override public Object instantiateItem(viewGroup container, int index)
. In the base class fragments are only added with a FragmentManager
instance when the adapter is first created. Whenever you page away the offscreen fragments are detached but not removed. The FragmentManager
caches the instances with a tag on the object. They are then attached when they are paged back to. The default implementation of instantiateItem
item tags each Fragment
inside of the FragmentAdapter
with a hardcoded tag. You need to tag each Fragment
you use with a unique tag. With this is place you can retrieve fragment instances from any FragmentManager
instance in your app with public abstract Fragment findFragmentByTag (String tag)
.
String[] tags = {"tag1", "tag2", "tag3", "tag4", "tag5"};
@Override
public Object instantiateItem(ViewGroup container, int index) {
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = fm.findFragmentByTag(tags[index]);
if (fragment == null) {
fragment = getItem(index);
ft.add(container.getId(), fragment, mTags[index]);
}
else {
ft.attach(fragment);
}
ft.commit();
return fragment;
}
public String getTag(int index) {
return mTags[index];
}
You should be able to access the the instances in onPageSelected
now.
Upvotes: 0