http://www.cnblogs.com/yishaochu/p/5078577.html
前言:不知不觉中又加班到了10点半,整个启动页面做了一天多的时间,一共有三个页面,每个页面都有动画效果,动画效果调试起来麻烦,既要跟ios统一,又要匹配各种不同的手机,然后产品经理还有可能在中途改需求,程序员各种苦逼有木有,在这个过程中也学到了蛮多东西的,所以写一篇博客跟大家分享一下.
先看效果图:
1.显示三个页面的Activity 用view pager去加载三个fragment实现,控制点点点的切换,监听view pager的切换,控制fragment动画的开始跟结束,重写了view pager,实现了背景图片的移动效果.
/**
2. * 主Activity
3. * @author ansen
4. * @create time 2015-08-07
5. */
6.public class KaKaLauncherActivity extends FragmentActivity {
7. private GuideViewPager vPager;
8. private List<LauncherBaseFragment> list = new ArrayList<LauncherBaseFragment>();
9. private BaseFragmentAdapter adapter;
10.
11. private ImageView[] tips;
12. private int currentSelect;
13.
14. @Override
15. protected void onCreate(Bundle savedInstanceState) {
16. super.onCreate(savedInstanceState);
17. setContentView(R.layout.activity_luancher_main);
18.
19. //初始化点点点控件
20. ViewGroup group = (ViewGroup)findViewById(R.id.viewGroup);
21. tips = new ImageView[3];
22. for (int i = 0; i < tips.length; i++) {
23. ImageView imageView = new ImageView(this);
24. imageView.setLayoutParams(new LayoutParams(10, 10));
25. if (i == 0) {
26. imageView.setBackgroundResource(R.drawable.page_indicator_focused);
27. } else {
28. imageView.setBackgroundResource(R.drawable.page_indicator_unfocused);
29. }
30. tips[i]=imageView;
31.
32. LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
33. layoutParams.leftMargin = 20;//设置点点点view的左边距
34. layoutParams.rightMargin = 20;//设置点点点view的右边距
35. group.addView(imageView,layoutParams);
36. }
37.
38. //获取自定义viewpager 然后设置背景图片
39. vPager = (GuideViewPager) findViewById(R.id.viewpager_launcher);
40. vPager.setBackGroud(BitmapFactory.decodeResource(getResources(),R.drawable.bg_kaka_launcher));
41.
42. /**
43. * 初始化三个fragment 并且添加到list中
44. */
45. RewardLauncherFragment rewardFragment = new RewardLauncherFragment();
46. PrivateMessageLauncherFragment privateFragment = new PrivateMessageLauncherFragment();
47. StereoscopicLauncherFragment stereoscopicFragment = new StereoscopicLauncherFragment();
48. list.add(rewardFragment);
49. list.add(privateFragment);
50. list.add(stereoscopicFragment);
51.
52. adapter = new BaseFragmentAdapter(getSupportFragmentManager(),list);
53. vPager.setAdapter(adapter);
54. vPager.setOffscreenPageLimit(2);
55. vPager.setCurrentItem(0);
56. vPager.setOnPageChangeListener(changeListener);
57. }
58.
59. /**
60. * 监听viewpager的移动
61. */
62. OnPageChangeListener changeListener=new OnPageChangeListener() {
63. @Override
64. public void onPageSelected(int index) {
65. setImageBackground(index);//改变点点点的切换效果
66. LauncherBaseFragment fragment=list.get(index);
67.
68. list.get(currentSelect).stopAnimation();//停止前一个页面的动画
69. fragment.startAnimation();//开启当前页面的动画
70.
71. currentSelect=index;
72. }
73.
74. @Override
75. public void onPageScrolled(int arg0, float arg1, int arg2) {}
76. @Override
77. public void onPageScrollStateChanged(int arg0) {}
78. };
79.
80. /**
81. * 改变点点点的切换效果
82. * @param selectItems
83. */
84. private void setImageBackground(int selectItems) {
85. for (int i = 0; i < tips.length; i++) {
86. if (i == selectItems) {
87. tips[i].setBackgroundResource(R.drawable.page_indicator_focused);
88. } else {
89. tips[i].setBackgroundResource(R.drawable.page_indicator_unfocused);
90. }
91. }
92. }
93.}
2.重写viewpager 在dispatchDraw方法中控制显示的背景图片区域,
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2. xmlns:tools="http://schemas.android.com/tools"
3. android:layout_width="match_parent"
4. android:layout_height="match_parent" >
5.
6. <com.example.view.GuideViewPager
7. android:id="@+id/viewpager_launcher"
8. android:layout_width="match_parent"
9. android:layout_height="match_parent" />
10.
11. <RelativeLayout
12. android:layout_width="fill_parent"
13. android:layout_height="wrap_content"
14. android:orientation="vertical" >
15.
16. <LinearLayout
17. android:id="@+id/viewGroup"
18. android:layout_width="fill_parent"
19. android:layout_height="wrap_content"
20. android:layout_alignParentBottom="true"
21. android:layout_marginBottom="30dp"
22. android:gravity="center_horizontal"
23. android:orientation="horizontal" />
24. </RelativeLayout>
25.
26.</RelativeLayout>
4.ViewPager适配器
1./**
2. * Viewpager适配器
3. * @author apple
4. *
5. */
6.public class BaseFragmentAdapter extends FragmentStatePagerAdapter {
7. private List<LauncherBaseFragment>list;
8. public BaseFragmentAdapter(FragmentManager fm, List<LauncherBaseFragment> list) {
9. super(fm);
10. this.list = list;
11. }
12.
13. public BaseFragmentAdapter(FragmentManager fm) {
14. super(fm);
15. }
16.
17. @Override
18. public Fragment getItem(int arg0) {
19. return list.get(arg0);
20. }
21.
22. @Override
23. public int getCount() {
24. return list.size();
25. }
26.}
5.Fragment抽象类 有两个抽象方法,开启动画跟停止动画 所有的Fragment都继承这个类 Viewpager切换的时候可以更好的控制每个Fragment开启动画,结束动画
/**
2. * Fragment抽象类
3. * @author ansen
4. *
5. */
6.public abstract class LauncherBaseFragment extends Fragment{
7. public abstract void startAnimation();
8. public abstract void stopAnimation();
9.}
6.打赏页Fragment 三个动画效果 硬币向下移动动画+打赏图片缩放动画+改变打赏图片透明度然后隐藏图片
/**
2. * 打赏页面
3. * @author ansen
4. * @create time 2015-08-07
5. */
6.public class RewardLauncherFragment extends LauncherBaseFragment{
7. private ImageView ivReward;
8. private ImageView ivGold;
9.
10. private Bitmap goldBitmap;
11. private boolean started;//是否开启动画(ViewPage滑动时候给这个变量赋值)
12.
13. @Override
14. public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
15. View rooView=inflater.inflate(R.layout.fragment_reward_launcher, null);
16. ivGold=(ImageView) rooView.findViewById(R.id.iv_gold);
17. ivReward=(ImageView) rooView.findViewById(R.id.iv_reward);
18.
19. //获取硬币的高度
20. goldBitmap=BitmapFactory.decodeResource(getActivity().getResources(),R.drawable.icon_gold);
21. startAnimation();
22. return rooView;
23. }
24.
25. public void startAnimation(){
26. started=true;
27.
28. //向下移动动画 硬币的高度*2+80
29. TranslateAnimation translateAnimation=new TranslateAnimation(0,0,0,goldBitmap.getHeight()*2+80);
30. translateAnimation.setDuration(500);
31. translateAnimation.setFillAfter(true);
32.
33. ivGold.startAnimation(translateAnimation);
34. translateAnimation.setAnimationListener(new AnimationListener() {
35. @Override
36. public void onAnimationStart(Animation animation) {}
37. @Override
38. public void onAnimationEnd(Animation animation){
39. if(started){
40. ivReward.setVisibility(View.VISIBLE);
41. //硬币移动动画结束开启缩放动画
42. Animation anim=AnimationUtils.loadAnimation(getActivity(),R.anim.reward_launcher);
43. ivReward.startAnimation(anim);
44. anim.setAnimationListener(new AnimationListener(){
45. @Override
46. public void onAnimationStart(Animation animation) {}
47. @Override
48. public void onAnimationRepeat(Animation animation) {}
49. @Override
50. public void onAnimationEnd(Animation animation) {
51. //缩放动画结束 开启改变透明度动画
52. AlphaAnimation alphaAnimation=new AlphaAnimation(1,0);
53. alphaAnimation.setDuration(1000);
54. ivReward.startAnimation(alphaAnimation);
55. alphaAnimation.setAnimationListener(new AnimationListener() {
56. @Override
57. public void onAnimationStart(Animation animation) {}
58. @Override
59. public void onAnimationRepeat(Animation animation) {}
60. @Override
61. public void onAnimationEnd(Animation animation) {
62. //透明度动画结束隐藏图片
63. ivReward.setVisibility(View.GONE);
64. }
65. });
66. }
67. });
68. }
69. }
70. @Override
71. public void onAnimationRepeat(Animation animation) {}
72. });
73. }
74.
75. @Override
76. public void stopAnimation(){
77. started=false;//结束动画时标示符设置为false
78. ivGold.clearAnimation();//清空view上的动画
79. }
80.}
7.私信页面 四个动画效果 并且四个动画都相同,其实只要我们实现了一个,其他的基本都很容易了. 依次实现四个图片的放大然后还原
/**
2. * 私信
3. * @author ansen
4. */
5.public class PrivateMessageLauncherFragment extends LauncherBaseFragment{
6. private ImageView ivLikeVideo,ivThinkReward,ivThisWeek,ivWatchMovie;
7.
8. private Animation likeAnimation,thinkAnimation,watchAnimation,thisWeekAnimation;
9.
10. private boolean started;//是否开启动画
11.
12. @Override
13. public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
14. View rooView=inflater.inflate(R.layout.fragment_private_message_launcher, null);
15.
16. ivLikeVideo=(ImageView) rooView.findViewById(R.id.iv_private_message_like_video);
17. ivThinkReward=(ImageView) rooView.findViewById(R.id.iv_private_message_think_reward);
18. ivWatchMovie=(ImageView) rooView.findViewById(R.id.iv_private_message_watch_movie);
19. ivThisWeek=(ImageView) rooView.findViewById(R.id.private_message_this_week);
20. return rooView;
21. }
22.
23. public void stopAnimation(){
24. //动画开启标示符设置成false
25. started=false;
26. /**
27. * 清空所有控件上的动画
28. */
29. ivLikeVideo.clearAnimation();
30. ivThinkReward.clearAnimation();
31. ivWatchMovie.clearAnimation();
32. ivThisWeek.clearAnimation();
33. }
34.
35.
36. public void startAnimation(){
37. started=true;
38.
39. /**
40. * 每次开启动画前先隐藏控件
41. */
42. ivLikeVideo.setVisibility(View.GONE);
43. ivThinkReward.setVisibility(View.GONE);
44. ivWatchMovie.setVisibility(View.GONE);
45. ivThisWeek.setVisibility(View.GONE);
46.
47. new Handler().postDelayed(new Runnable() {//延时0.5秒之后开启喜欢视频动画
48. @Override
49. public void run(){
50. if(started)
51. likeVideoAnimation();
52. }
53. },500);
54. }
55.
56. /**
57. * 好喜欢你的视频
58. */
59. private void likeVideoAnimation(){
60. ivLikeVideo.setVisibility(View.VISIBLE);
61.
62. likeAnimation = AnimationUtils.loadAnimation(getActivity(),R.anim.private_message_launcher);
63. ivLikeVideo.startAnimation(likeAnimation);//开启动画
64. likeAnimation.setAnimationListener(new AnimationListener(){
65. @Override
66. public void onAnimationStart(Animation animation) {}
67. @Override
68. public void onAnimationRepeat(Animation animation) {}
69. @Override
70. public void onAnimationEnd(Animation animation) {//监听动画结束
71. if(started)
72. thinkReward();
73. }
74. });
75. }
76.
77. /**
78. * 谢谢你的打赏
79. */
80. private void thinkReward(){
81. ivThinkReward.setVisibility(View.VISIBLE);
82. thinkAnimation = AnimationUtils.loadAnimation(getActivity(),R.anim.private_message_launcher);
83. ivThinkReward.startAnimation(thinkAnimation);
84. thinkAnimation.setAnimationListener(new AnimationListener(){
85. @Override
86. public void onAnimationStart(Animation animation) {}
87. @Override
88. public void onAnimationRepeat(Animation animation) {}
89. @Override
90. public void onAnimationEnd(Animation animation) {
91. if(started)
92. watchMovie();
93. }
94. });
95. }
96.
97. /**
98. * 一起看个电影呗
99. */
100. private void watchMovie(){
101. ivWatchMovie.setVisibility(View.VISIBLE);
102. watchAnimation = AnimationUtils.loadAnimation(getActivity(),R.anim.private_message_launcher);
103. ivWatchMovie.startAnimation(watchAnimation);
104. watchAnimation.setAnimationListener(new AnimationListener(){
105. @Override
106. public void onAnimationStart(Animation animation) {}
107. @Override
108. public void onAnimationRepeat(Animation animation) {}
109. @Override
110. public void onAnimationEnd(Animation animation) {
111. if(started)
112. thisWeek();
113. }
114. });
115. }
116.
117. /**
118. * 好啊 这周末有空
119. */
120. private void thisWeek(){
121. ivThisWeek.setVisibility(View.VISIBLE);
122. thisWeekAnimation = AnimationUtils.loadAnimation(getActivity(),R.anim.private_message_launcher);
123. ivThisWeek.startAnimation(thisWeekAnimation);
124. }
125.}
8.最后一个引导页 就两个动画 图片的放大跟缩小,其实用xml布局的话一个动画就能搞定,跟私信页面的动画差不多.小伙伴写的代码.这里换了一种方式.代码比较多.
/**
2. * 最后一个
3. * @author apple
4. */
5.public class StereoscopicLauncherFragment extends LauncherBaseFragment implements OnClickListener{
6. private static final float ZOOM_MAX = 1.3f;
7. private static final float ZOOM_MIN = 1.0f;
8.
9. private ImageView imgView_immediate_experience;
10.
11. @Override
12. public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
13. View rooView=inflater.inflate(R.layout.fragment_stereoscopic_launcher, null);
14. imgView_immediate_experience=(ImageView) rooView.findViewById(R.id.imgView_immediate_experience);
15. imgView_immediate_experience.setOnClickListener(this);
16. return rooView;
17. }
18.
19. public void playHeartbeatAnimation(){
20. /**
21. * 放大动画
22. */
23. AnimationSet animationSet = new AnimationSet(true);
24. animationSet.addAnimation(new ScaleAnimation(ZOOM_MIN, ZOOM_MAX, ZOOM_MIN, ZOOM_MAX, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f));
25. animationSet.addAnimation(new AlphaAnimation(1.0f, 0.8f));
26.
27. animationSet.setDuration(500);
28. animationSet.setInterpolator(new AccelerateInterpolator());
29. animationSet.setFillAfter(true);
30.
31. animationSet.setAnimationListener(new AnimationListener() {
32. @Override
33. public void onAnimationStart(Animation animation) {
34. }
35.
36. @Override
37. public void onAnimationRepeat(Animation animation) {
38. }
39.
40. @Override
41. public void onAnimationEnd(Animation animation) {
42. /**
43. * 缩小动画
44. */
45. AnimationSet animationSet = new AnimationSet(true);
46. animationSet.addAnimation(new ScaleAnimation(ZOOM_MAX, ZOOM_MIN, ZOOM_MAX,ZOOM_MIN, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f));
47. animationSet.addAnimation(new AlphaAnimation(0.8f, 1.0f));
48. animationSet.setDuration(600);
49. animationSet.setInterpolator(new DecelerateInterpolator());
50. animationSet.setFillAfter(false);
51. // 实现心跳的View
52. imgView_immediate_experience.startAnimation(animationSet);
53. }
54. });
55. // 实现心跳的View
56. imgView_immediate_experience.startAnimation(animationSet);
57. }
58.
59. @Override
60. public void onClick(View v) {
61.// Intent intent = new Intent();
62.// intent.setClass(getActivity(),MainActivity.class);
63.// startActivity(intent);
64.// getActivity().finish();
65. }
66.
67. @Override
68. public void startAnimation() {
69. playHeartbeatAnimation();
70. }
71.
72. @Override
73. public void stopAnimation() {
74.
75. }
76.}
最后总结:以上就是三个引导页的核心代码了,还有一些布局文件,动画效果的布局文件我就不一一贴出来的,大家可以去下载我的源码,在这个过程中碰到的几个大的问题说明一下.
1.viewpager切换的时候要结束上个fragment的动画 我是通过boolean变量去控制的
2.背景图片移动的效果 之前自己走了很多弯路,后面在网上找了一个demo拿过来用了.因为大家都有开源精神所以这里省了很多功夫
3.图片放大缩小以前居然不知道一个xml动画布局就能搞定.之前一直想办法用两个动画实现