Reputation: 644
In my projects I have several screen(Fragments) and I want to give animation to the fragments elements(views). I have used view pager and viewpager adapter and fragments. The main problems I am facing-
Is there something wrong with the code?
Here is the MainActivity.java code-
public class MainActivity extends FragmentActivity {
ViewPager viewPager;
PagerAdapter adapter;
CirclePageIndicator mIndicator;
private int mWidthScreen;
private int mHeightScreen;
private Bundle bundle;
private List<Fragment> frgScreens;
private int selectedtheme;
private Handler mHandler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewpager_main); // Get the view from viewpager_main.xml
buildargument();
initialisePaging(); // Page creating function
}
private void initialisePaging(int theme) {
viewPager = (ViewPager) findViewById(R.id.pager);
frgScreens = new Vector<Fragment>(); // clearing old entries
viewPager.setOffscreenPageLimit(0);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Loading fragment # position
//Instead of starting animation from onCreate start it from here
//Only for the first time (for page 1) this callback will not trigger
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
frgScreens = this.basicThemes();
// Bind result to ViewPagerAdapter
adapter = new ViewPagerAdapter(this.getSupportFragmentManager(), frgScreens);
this.viewPager.setAdapter(adapter);
}
/*
* Basic fragments
*/
private List<Fragment> basicThemes() {
// declaring fragments Group Basic
Fragment frgBasic1 = Fragment.instantiate(this, Basic1.class.getName());
Fragment frgBasic2 = Fragment.instantiate(this, Basic2.class.getName());
Fragment frgBasic3 = Fragment.instantiate(this, Basic3.class.getName());
Fragment frgBasic4 = Fragment.instantiate(this, Basic4.class.getName());
Fragment frgBasic5 = Fragment.instantiate(this, Basic5.class.getName());
// Passing arguments
frgBasic1.setArguments(bundle);
frgBasic2.setArguments(bundle);
frgBasic3.setArguments(bundle);
frgBasic4.setArguments(bundle);
frgBasic5.setArguments(bundle);
// Loading screens into Fragment list
List<Fragment> frgBasicScreens = new Vector<Fragment>();
frgBasicScreens.add(frgBasic1);
frgBasicScreens.add(frgBasic2);
frgBasicScreens.add(frgBasic3);
frgBasicScreens.add(frgBasic4);
frgBasicScreens.add(frgBasic5);
return frgBasicScreens;
}
private void getScreenHeightWidhth() {
DisplayMetrics localDisplayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics);
this.mWidthScreen = localDisplayMetrics.widthPixels;
this.mHeightScreen = localDisplayMetrics.heightPixels;
mHandler.post(
new DisplayToast(this, "Width Screen:" + mWidthScreen + ". Height Screen: " + mHeightScreen + "."));
}
private void buildargument() {
this.bundle = new Bundle();
bundle.putInt("mWidthScreen", this.mWidthScreen);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public void onDestroy() {
super.onDestroy();
}}
Now ViewPagerAdapter.java
public class ViewPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> screens;
public ViewPagerAdapter(FragmentManager fm, List<Fragment> fragments ) {
super(fm);
this.screens = fragments;
}
@Override
public Fragment getItem(int pos) {
// getting the position of the item
return this.screens.get(pos);
}
@Override
public int getCount() {
// Getting the size of screen passed
return this.screens.size();
}}
skinbase.java is the common class used by all the basics screen some shared methods.
public abstract class SkinsBase extends Fragment
{
protected int mWidthScreen;
protected int mHeightScreen;
public int skinHeight;
public int skinWidth;
public final int textShadowSize = 2;
.................
}
now basic1.java
public class Basic1 extends SkinsBase {
private RelativeLayout mBlueBackground;
private Handler mHandler = new Handler();
private static final String TAG = "Basic1";
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
return null;
}
mContext = container.getContext();
View v = inflater.inflate(R.layout.blank_viewpager_item, container, false);
mLayoutForeground = (RelativeLayout) v.findViewById(R.id.relative);
mBlueBackground = initshape(getResources().getColor(R.color.transparent_blue_80),this.mWidthScreen, (int) (0.10F * this.mWidthScreen), 0,(int) (0.12F *this.mWidthScreen));
this.mLayoutForeground.addView(this.mBlueBackground);
Log.e(TAG, "Inside basic 1 ");
return v;
}
public RelativeLayout initshape(int intColor,int intWidthscreen, int intHeight, int intMerginLeft,int intMerginTop) {
RelativeLayout localRelativeLayout = new RelativeLayout(this.mContext);
localRelativeLayout.setBackgroundColor(intColor);
RelativeLayout.LayoutParams localLayoutParams = new RelativeLayout.LayoutParams(intWidthscreen, intHeight);
localLayoutParams.setMargins(intMerginLeft, intMerginTop, 0, 0);
localRelativeLayout.setLayoutParams(localLayoutParams);
return localRelativeLayout;
}
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
}}
Same way other basic2.java, basic3.java, basic4.java..... are like basic1.java
I need to apply animation to RelativeLayout. Is it possible? And I want the start of the animation when the page loads not before that.
Upvotes: 2
Views: 1379
Reputation: 6263
Overriding setUserVisibleHint()
in each of my pages/fragments worked for me. You can simply call view.startAnimation(animation)
inside your setUserVisibleHint()
. However, there is one problem with this approach:
In fragments,
setUserVisibleHint()
gets called beforeonCreateView()
andonViewCreated
.
The implication of this is that when the fragment starts for the first time and you call view.startAnimation(animation)
inside setUserVisibleHint()
, view and animation would both be null and the app would crash.
How then can you fix this problem?
In each of your pages/fragments, simply declare a global boolean (let's call it fresh_load), use this boolean to check whether the fragment is being loaded for the first time. Here's an illustration:
boolean fresh_load = true;
Animation move;
ImageView car;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_carousel_two, container, false);
// init move and car variables
if(fresh_load) {
car.startAnimation(animation);
fresh_load = false;
}
return view;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if((isVisible() && animation != null) && !fresh_load) {
car.startAnimation(move);
}
}
I hope this helps. Merry coding!
Upvotes: 0
Reputation:
It is the default behavior of view-pager that it preload at-least 1 page from both side of current page. See following links
ViewPager.setOffscreenPageLimit(0) doesn't work as expected
So what you can do is Instead of starting animation onCreate start it from onPageScrolled
callback
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Loading fragment # position
//Instead of starting animation from onCreate start it from here
//Only for the first time (for page 1) this callback will not trigger
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.
This is offered as an optimization. If you know in advance the number of pages you will need to support or have lazy-loading mechanisms in place on your pages, tweaking this setting can have benefits in perceived smoothness of paging animations and interaction. If you have a small number of pages (3-4) that you can keep active all at once, less time will be spent in layout for newly created view subtrees as the user pages back and forth.
You should keep this limit low, especially if your pages have complex layouts. This setting defaults to 1.
Upvotes: 3