转载:http://blog.csdn.net/lowprofile_coding/article/details/48037095
先看效果图:
1.显示三个页面的Activity 用view pager去加载三个fragment实现,控制点点点的切换,监听view pager的切换,控制fragment动画的开始跟结束,重写了view pager,实现了背景图片的移动效果.
/**
* 主Activity
* @author ansen
* @create time 2015-08-07
*/
public class KaKaLauncherActivity extends FragmentActivity {
private GuideViewPager vPager;
private List list = new ArrayList();
private BaseFragmentAdapter adapter;
private ImageView[] tips;
private int currentSelect;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_luancher_main);
//初始化点点点控件
ViewGroup group = (ViewGroup)findViewById(R.id.viewGroup);
tips = new ImageView[3];
for (int i = 0; i < tips.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setLayoutParams(new LayoutParams(10, 10));
if (i == 0) {
imageView.setBackgroundResource(R.drawable.page_indicator_focused);
} else {
imageView.setBackgroundResource(R.drawable.page_indicator_unfocused);
}
tips[i]=imageView;
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
layoutParams.leftMargin = 20;//设置点点点view的左边距
layoutParams.rightMargin = 20;//设置点点点view的右边距
group.addView(imageView,layoutParams);
}
//获取自定义viewpager 然后设置背景图片
vPager = (GuideViewPager) findViewById(R.id.viewpager_launcher);
vPager.setBackGroud(BitmapFactory.decodeResource(getResources(),R.drawable.bg_kaka_launcher));
/**
* 初始化三个fragment 并且添加到list中
*/
RewardLauncherFragment rewardFragment = new RewardLauncherFragment();
PrivateMessageLauncherFragment privateFragment = new PrivateMessageLauncherFragment();
StereoscopicLauncherFragment stereoscopicFragment = new StereoscopicLauncherFragment();
list.add(rewardFragment);
list.add(privateFragment);
list.add(stereoscopicFragment);
adapter = new BaseFragmentAdapter(getSupportFragmentManager(),list);
vPager.setAdapter(adapter);
vPager.setOffscreenPageLimit(2);
vPager.setCurrentItem(0);
vPager.setOnPageChangeListener(changeListener);
}
/**
* 监听viewpager的移动
*/
OnPageChangeListener changeListener=new OnPageChangeListener() {
@Override
public void onPageSelected(int index) {
setImageBackground(index);//改变点点点的切换效果
LauncherBaseFragment fragment=list.get(index);
list.get(currentSelect).stopAnimation();//停止前一个页面的动画
fragment.startAnimation();//开启当前页面的动画
currentSelect=index;
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
@Override
public void onPageScrollStateChanged(int arg0) {}
};
/**
* 改变点点点的切换效果
* @param selectItems
*/
private void setImageBackground(int selectItems) {
for (int i = 0; i < tips.length; i++) {
if (i == selectItems) {
tips[i].setBackgroundResource(R.drawable.page_indicator_focused);
} else {
tips[i].setBackgroundResource(R.drawable.page_indicator_unfocused);
}
}
}
}
2.重写viewpager 在dispatchDraw方法中控制显示的背景图片区域,
/**
* 重写ViewPager 主要做一个切换背景的功能
* @author ansen
* @create time 2015-08-07
*/
public class GuideViewPager extends ViewPager {
private Bitmap bg;
private Paint b = new Paint(1);
public GuideViewPager(Context context) {
super(context);
}
public GuideViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (this.bg != null) {
int width = this.bg.getWidth();
int height = this.bg.getHeight();
int count = getAdapter().getCount();
int x = getScrollX();
// 子View中背景图片需要显示的宽度,放大背景图或缩小背景图。
int n = height * getWidth() / getHeight();
/**
* (width - n) / (count - 1)表示除去显示第一个ViewPager页面用去的背景宽度,剩余的ViewPager需要显示的背景图片的宽度。
* getWidth()等于ViewPager一个页面的宽度,即手机屏幕宽度。在该计算中可以理解为滑动一个ViewPager页面需要滑动的像素值。
* ((width - n) / (count - 1)) /getWidth()也就表示ViewPager滑动一个像素时,背景图片滑动的宽度。
* x * ((width - n) / (count - 1)) / getWidth()也就表示ViewPager滑动x个像素时,背景图片滑动的宽度。
* 背景图片滑动的宽度的宽度可以理解为背景图片滑动到达的位置。
*/
int w = x * ((width - n) / (count - 1)) / getWidth();
canvas.drawBitmap(this.bg, new Rect(w, 0, n + w, height), new Rect( x, 0, x + getWidth(), getHeight()), this.b);
}
super.dispatchDraw(canvas);
}
public void setBackGroud(Bitmap paramBitmap) {
this.bg = paramBitmap;
this.b.setFilterBitmap(true);
}
}
3.主体布局文件 上面放一个自定义的viewpager 下面放一个显示点点的RelativeLayout
4.ViewPager适配器
/**
* Viewpager适配器
* @author apple
*
*/
public class BaseFragmentAdapter extends FragmentStatePagerAdapter {
private Listlist;
public BaseFragmentAdapter(FragmentManager fm, List list) {
super(fm);
this.list = list;
}
public BaseFragmentAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int arg0) {
return list.get(arg0);
}
@Override
public int getCount() {
return list.size();
}
}
5.Fragment抽象类 有两个抽象方法,开启动画跟停止动画 所有的Fragment都继承这个类 Viewpager切换的时候可以更好的控制每个Fragment开启动画,结束动画
/**
* Fragment抽象类
* @author ansen
*
*/
public abstract class LauncherBaseFragment extends Fragment{
public abstract void startAnimation();
public abstract void stopAnimation();
}
6.打赏页Fragment 三个动画效果 硬币向下移动动画+打赏图片缩放动画+改变打赏图片透明度然后隐藏图片
/**
* 打赏页面
* @author ansen
* @create time 2015-08-07
*/
public class RewardLauncherFragment extends LauncherBaseFragment{
private ImageView ivReward;
private ImageView ivGold;
private Bitmap goldBitmap;
private boolean started;//是否开启动画(ViewPage滑动时候给这个变量赋值)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View rooView=inflater.inflate(R.layout.fragment_reward_launcher, null);
ivGold=(ImageView) rooView.findViewById(R.id.iv_gold);
ivReward=(ImageView) rooView.findViewById(R.id.iv_reward);
//获取硬币的高度
goldBitmap=BitmapFactory.decodeResource(getActivity().getResources(),R.drawable.icon_gold);
startAnimation();
return rooView;
}
public void startAnimation(){
started=true;
//向下移动动画 硬币的高度*2+80
TranslateAnimation translateAnimation=new TranslateAnimation(0,0,0,goldBitmap.getHeight()*2+80);
translateAnimation.setDuration(500);
translateAnimation.setFillAfter(true);
ivGold.startAnimation(translateAnimation);
translateAnimation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation){
if(started){
ivReward.setVisibility(View.VISIBLE);
//硬币移动动画结束开启缩放动画
Animation anim=AnimationUtils.loadAnimation(getActivity(),R.anim.reward_launcher);
ivReward.startAnimation(anim);
anim.setAnimationListener(new AnimationListener(){
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
//缩放动画结束 开启改变透明度动画
AlphaAnimation alphaAnimation=new AlphaAnimation(1,0);
alphaAnimation.setDuration(1000);
ivReward.startAnimation(alphaAnimation);
alphaAnimation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
//透明度动画结束隐藏图片
ivReward.setVisibility(View.GONE);
}
});
}
});
}
}
@Override
public void onAnimationRepeat(Animation animation) {}
});
}
@Override
public void stopAnimation(){
started=false;//结束动画时标示符设置为false
ivGold.clearAnimation();//清空view上的动画
}
}
7.私信页面 四个动画效果 并且四个动画都相同,其实只要我们实现了一个,其他的基本都很容易了. 依次实现四个图片的放大然后还原
/**
* 私信
* @author ansen
*/
public class PrivateMessageLauncherFragment extends LauncherBaseFragment{
private ImageView ivLikeVideo,ivThinkReward,ivThisWeek,ivWatchMovie;
private Animation likeAnimation,thinkAnimation,watchAnimation,thisWeekAnimation;
private boolean started;//是否开启动画
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View rooView=inflater.inflate(R.layout.fragment_private_message_launcher, null);
ivLikeVideo=(ImageView) rooView.findViewById(R.id.iv_private_message_like_video);
ivThinkReward=(ImageView) rooView.findViewById(R.id.iv_private_message_think_reward);
ivWatchMovie=(ImageView) rooView.findViewById(R.id.iv_private_message_watch_movie);
ivThisWeek=(ImageView) rooView.findViewById(R.id.private_message_this_week);
return rooView;
}
public void stopAnimation(){
//动画开启标示符设置成false
started=false;
/**
* 清空所有控件上的动画
*/
ivLikeVideo.clearAnimation();
ivThinkReward.clearAnimation();
ivWatchMovie.clearAnimation();
ivThisWeek.clearAnimation();
}
public void startAnimation(){
started=true;
/**
* 每次开启动画前先隐藏控件
*/
ivLikeVideo.setVisibility(View.GONE);
ivThinkReward.setVisibility(View.GONE);
ivWatchMovie.setVisibility(View.GONE);
ivThisWeek.setVisibility(View.GONE);
new Handler().postDelayed(new Runnable() {//延时0.5秒之后开启喜欢视频动画
@Override
public void run(){
if(started)
likeVideoAnimation();
}
},500);
}
/**
* 好喜欢你的视频
*/
private void likeVideoAnimation(){
ivLikeVideo.setVisibility(View.VISIBLE);
likeAnimation = AnimationUtils.loadAnimation(getActivity(),R.anim.private_message_launcher);
ivLikeVideo.startAnimation(likeAnimation);//开启动画
likeAnimation.setAnimationListener(new AnimationListener(){
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {//监听动画结束
if(started)
thinkReward();
}
});
}
/**
* 谢谢你的打赏
*/
private void thinkReward(){
ivThinkReward.setVisibility(View.VISIBLE);
thinkAnimation = AnimationUtils.loadAnimation(getActivity(),R.anim.private_message_launcher);
ivThinkReward.startAnimation(thinkAnimation);
thinkAnimation.setAnimationListener(new AnimationListener(){
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
if(started)
watchMovie();
}
});
}
/**
* 一起看个电影呗
*/
private void watchMovie(){
ivWatchMovie.setVisibility(View.VISIBLE);
watchAnimation = AnimationUtils.loadAnimation(getActivity(),R.anim.private_message_launcher);
ivWatchMovie.startAnimation(watchAnimation);
watchAnimation.setAnimationListener(new AnimationListener(){
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
if(started)
thisWeek();
}
});
}
/**
* 好啊 这周末有空
*/
private void thisWeek(){
ivThisWeek.setVisibility(View.VISIBLE);
thisWeekAnimation = AnimationUtils.loadAnimation(getActivity(),R.anim.private_message_launcher);
ivThisWeek.startAnimation(thisWeekAnimation);
}
}
8.最后一个引导页 就两个动画 图片的放大跟缩小,其实用xml布局的话一个动画就能搞定,跟私信页面的动画差不多.小伙伴写的代码.这里换了一种方式.代码比较多.
/**
* 最后一个
* @author apple
*/
public class StereoscopicLauncherFragment extends LauncherBaseFragment implements OnClickListener{
private static final float ZOOM_MAX = 1.3f;
private static final float ZOOM_MIN = 1.0f;
private ImageView imgView_immediate_experience;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View rooView=inflater.inflate(R.layout.fragment_stereoscopic_launcher, null);
imgView_immediate_experience=(ImageView) rooView.findViewById(R.id.imgView_immediate_experience);
imgView_immediate_experience.setOnClickListener(this);
return rooView;
}
public void playHeartbeatAnimation(){
/**
* 放大动画
*/
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(new ScaleAnimation(ZOOM_MIN, ZOOM_MAX, ZOOM_MIN, ZOOM_MAX, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f));
animationSet.addAnimation(new AlphaAnimation(1.0f, 0.8f));
animationSet.setDuration(500);
animationSet.setInterpolator(new AccelerateInterpolator());
animationSet.setFillAfter(true);
animationSet.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
/**
* 缩小动画
*/
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(new ScaleAnimation(ZOOM_MAX, ZOOM_MIN, ZOOM_MAX,ZOOM_MIN, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f));
animationSet.addAnimation(new AlphaAnimation(0.8f, 1.0f));
animationSet.setDuration(600);
animationSet.setInterpolator(new DecelerateInterpolator());
animationSet.setFillAfter(false);
// 实现心跳的View
imgView_immediate_experience.startAnimation(animationSet);
}
});
// 实现心跳的View
imgView_immediate_experience.startAnimation(animationSet);
}
@Override
public void onClick(View v) {
// Intent intent = new Intent();
// intent.setClass(getActivity(),MainActivity.class);
// startActivity(intent);
// getActivity().finish();
}
@Override
public void startAnimation() {
playHeartbeatAnimation();
}
@Override
public void stopAnimation() {
}
}
最后总结:以上就是三个引导页的核心代码了,还有一些布局文件,动画效果的布局文件我就不一一贴出来的,大家可以去下载我的源码,在这个过程中碰到的几个大的问题说明一下.
1.viewpager切换的时候要结束上个fragment的动画 我是通过boolean变量去控制的
2.背景图片移动的效果 之前自己走了很多弯路,后面在网上找了一个demo拿过来用了.因为大家都有开源精神所以这里省了很多功夫
3.图片放大缩小以前居然不知道一个xml动画布局就能搞定.之前一直想办法用两个动画实现
点击源码下载