您的位置:首页 > 移动开发

app引导页(背景图片切换加各个页面动画效果)

2015-12-26 20:02 507 查看
前言:不知不觉中又加班到了10点半,整个启动页面做了一天多的时间,一共有三个页面,每个页面都有动画效果,动画效果调试起来麻烦,既要跟ios统一,又要匹配各种不同的手机,然后产品经理还有可能在中途改需求,程序员各种苦逼有木有,在这个过程中也学到了蛮多东西的,所以写一篇博客跟大家分享一下.

先看效果图:



1.显示三个页面的Activity 用view pager去加载三个fragment实现,控制点点点的切换,监听view pager的切换,控制fragment动画的开始跟结束,重写了view pager,实现了背景图片的移动效果.

[java] view plaincopy

/**

* 主Activity

* @author ansen

* @create time 2015-08-07

*/

public class KaKaLauncherActivity extends FragmentActivity {

private GuideViewPager vPager;

private List<LauncherBaseFragment> list = new ArrayList<LauncherBaseFragment>();

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方法中控制显示的背景图片区域,

[java] view plaincopy

/**

* 重写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

[html] view plaincopy

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

<com.example.view.GuideViewPager

android:id="@+id/viewpager_launcher"

android:layout_width="match_parent"

android:layout_height="match_parent" />

<RelativeLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:orientation="vertical" >

<LinearLayout

android:id="@+id/viewGroup"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:layout_marginBottom="30dp"

android:gravity="center_horizontal"

android:orientation="horizontal" />

</RelativeLayout>

</RelativeLayout>

4.ViewPager适配器

[java] view plaincopy

/**

* Viewpager适配器

* @author apple

*

*/

public class BaseFragmentAdapter extends FragmentStatePagerAdapter {

private List<LauncherBaseFragment>list;

public BaseFragmentAdapter(FragmentManager fm, List<LauncherBaseFragment> 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开启动画,结束动画

[java] view plaincopy

/**

* Fragment抽象类

* @author ansen

*

*/

public abstract class LauncherBaseFragment extends Fragment{

public abstract void startAnimation();

public abstract void stopAnimation();

}

6.打赏页Fragment 三个动画效果 硬币向下移动动画+打赏图片缩放动画+改变打赏图片透明度然后隐藏图片

[java] view plaincopy

/**

* 打赏页面

* @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.私信页面 四个动画效果 并且四个动画都相同,其实只要我们实现了一个,其他的基本都很容易了. 依次实现四个图片的放大然后还原

[java] view plaincopy

/**

* 私信

* @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布局的话一个动画就能搞定,跟私信页面的动画差不多.小伙伴写的代码.这里换了一种方式.代码比较多.

[java] view plaincopy

/**

* 最后一个

* @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动画布局就能搞定.之前一直想办法用两个动画实现

看看时间一篇博客写了一个半小时,都12点了,办公室一个人敲打着键盘,记录着这两天做过的东西,才发现这也是一件很惬意的事情。。。。闪人。。。回家.
推荐下自己创建的android QQ群:202928390 欢迎大家的加入.


点击下载源码

如果你想第一时间看我们的后期文章,扫码关注公众号,每个周末都会推送Android开发实战教程一篇,其余时间我们会推出一些互联网行业新闻,你还等什么,赶快关注吧,既能学到技术,还能长逼格,出任ceo,赢取白富美。。。。。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: