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

Posted 安辉就是我

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了app引导页(背景图片切换加各个页面动画效果)相关的知识,希望对你有一定的参考价值。

转载请注明出处:http://blog.csdn.net/lowprofile_coding/article/details/48037095


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


先看效果图:




1.显示三个页面的活动用视图寻呼机去加载三个片段实现,控制点点点的切换,监听观点寻呼机的切换,控制片段动画的开始跟结束,重写了看法寻呼机,实现了背景图片的移动效果。

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

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

<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适配器

/**
 * 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抽象类有两个抽象方法,开启动画跟停止动画所有的碎片都继承这个类Viewpager切换的时候可以更好的控制每个片段开启​​动画,结束动画

/**
 * Fragment抽象类
 * @author ansen
 * 
 */
public abstract class LauncherBaseFragment extends Fragment
	public abstract void  startAnimation();
	public abstract void  stopAnimation();

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

/**
 * 打赏页面
 * @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切换的时候要结束上个片段的动画我是通过布尔变量去控制的

2.背景图片移动的效果之前自己走了很多弯路,后面在网上找了一个demo拿过来用了.因为大家都有开源精神所以这里省了很多功夫

3.图片放大缩小以前居然不知道一个xml动画布局就能搞定.之前一直想办法用两个动画实现


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


点击下载源码


推荐一个的Andr​​oid版的开发者必关注公众号,每周都有原创干货

以上是关于app引导页(背景图片切换加各个页面动画效果)的主要内容,如果未能解决你的问题,请参考以下文章

iOS帅气加载动画通知视图红包助手引导页导航栏朋友圈小游戏等效果源码

android ViewPager实现 跑马灯切换图片+多种切换动画

Android基础控件——ViewPager实现带有动画的引导页

app引导页和启动页有啥区别

基于Bootstrap的步骤引导html页面

android引导页 旋转的效果