这几天项目也快结尾了,前几天一直忙着项目,博客也没怎么整理,这几天抓紧补一下。
在5篇博客中已经讲解了项目开发的大部分,剩余的基本就是Coding了,在接下来几篇博客中,我将会挑取项目中的稍微复杂的页面讲解。
源码下载
今天实现的是项目的开机动画。程序在安装后第一次打开时会有开机动画引导,这应该算是项目比较炫酷的一个地方,通过动画的形式向用户展现应用概览,更加人性化。
、动画效果
1. 一共有4页。
2. 当滑动到该页时,动画才开始播放。
3. 当4页全部浏览完毕,在返回浏览时, 动画显示的是最终结果不再重新加载。
动画实现使用的是View Animation中简单的平移,旋转,透明度等,比较简单。因此不会再具体的讲解动画动作的实现,只讲解整体动画实现的大体思路。
动画实现使用的ViewPager嵌套Fragmnet,在Fragment中实现动画的动作。这里在使用ViewPager时就涉及到了ViewPager的预加载问题。
以下是Activity的内容,先看代码,然后逐步分析:
public class WelcomePageActivity extends BaseActivity {
private ViewPager mVeiwPager;//显示Fragment的ViewPager
private List<Fragment> mFragments;//Fragment页面的集合
private FragmentManager mManager;//Fragment的管理器。
private FragmentPageOne mFragmentPageOne;
private FragmentPageTwo mFragmentPageTwo;
private FragmentPageThree mFragmentPageThree;
private FragmentPageFour mFragmentPageFour;
private WelcomePagePagerAdapter mAdapter;//ViewPager的适配器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome_page);
//ViewPager的对象
mVeiwPager = (ViewPager) findViewById(R.id.viewpager_activity_welcome_page);
//ViewPager中放置Fragment的集合
mFragments = new ArrayList<>();
mManager = getSupportFragmentManager();
mFragmentPageOne = new FragmentPageOne();
mFragmentPageTwo = new FragmentPageTwo();
mFragmentPageThree = new FragmentPageThree();
mFragmentPageFour = new FragmentPageFour();
mFragments.add(mFragmentPageOne);
mFragments.add(mFragmentPageTwo);
mFragments.add(mFragmentPageThree);
mFragments.add(mFragmentPageFour);
mAdapter = new WelcomePagePagerAdapter(mManager,mFragments);
mVeiwPager.setOffscreenPageLimit(4);//重要! 此处设置ViewPager的预加载为4页。
mVeiwPager.setAdapter(mAdapter);//设置ViewPager的适配器
mVeiwPager.setCurrentItem(0);//设置ViewPager开始的页面。
}
}
Point One
Activity中设置要显示的四个Fragment页面。
Point One
ViewPager要设置预加载页面为4,通过方法:setOffscreenPageLimit(4)
。
原因:由于我们要显示的是4个页面的动画,ViewPager有默认预加载的功能,默认为预加载一页,但是我们的动画是不允许预加载的,因为如果我们对VIewPager进行了预加载,如果预加载为2页,当我们翻到第一页动画的时候,第2页和第3页的动画也会同时加载,这并不是我们想要的,我们想要的是当翻到该页时该页的动画才开始播放。所以我们在Fragment中要避免预加载的使用。
但是为什么这里我们还是要设置预加载的页面呢?原因是,在我们的第一页动画的Fragment中并没有定义不使用预加载功能,因此,当我们从最后一页往前翻页,翻到第一页是动画还是加载完成的样子,我们设置了ViewPager为4页。可能大家看到这还是有点晕,没关系,往下接着看,当看到“Fragment定义”时,便会明白了。
首先定义一个LauncherBaseFragment 抽象类,定义开始和停止动画两个方法,然后当定义四个Fragment动画页面时,继承这个抽象类:
public abstract class LauncherBaseFragment extends BaseFragment {
public abstract void startAnimation();
public abstract void stopAnimation();
}
(1). FragmentPageOne定义
public class FragmentPageOne extends LauncherBaseFragment {
private View view;//该Fragment的值
private boolean started;//是否开启动画(ViewPage滑动时候给这个变量赋值)
private List<ImageView> mImageViews;//用于存储Image动画图片
//以下是显示的ImageView,通过这些Image实现动画。
private ImageView mImage1;
private ImageView mImage2;
private ImageView mImage3;
private ImageView mImage4;
private ImageView mImage5;
private ImageView mImage6;
private ImageView mImage7;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_setting_about_welcome_page1, null);//该Fragment的View
mImage1 = (ImageView) view.findViewById(R.id.imageview1_activity_setting_about_welcome_page1);
mImage2 = (ImageView) view.findViewById(R.id.imageview2_activity_setting_about_welcome_page1);
mImage3 = (ImageView) view.findViewById(R.id.imageview3_activity_setting_about_welcome_page1);
mImage4 = (ImageView) view.findViewById(R.id.imageview4_activity_setting_about_welcome_page1);
mImage5 = (ImageView) view.findViewById(R.id.imageview5_activity_setting_about_welcome_page1);
mImage6 = (ImageView) view.findViewById(R.id.imageview6_activity_setting_about_welcome_page1);
mImage7 = (ImageView) view.findViewById(R.id.imageview7_activity_setting_about_welcome_page1);
mImageViews = new ArrayList<>();
mImageViews.add(mImage1);
mImageViews.add(mImage2);
mImageViews.add(mImage3);
mImageViews.add(mImage4);
mImageViews.add(mImage5);
mImageViews.add(mImage6);
mImageViews.add(mImage7);
startAnimation();
return view;
}
/** * 实现抽象父类LauncherBaseFragment的开始动画方法 */
@Override
public void startAnimation() {
started = true;
//缩放动画
if (started) {
for (int i = 0; i < mImageViews.size(); i++) {
mImageViews.get(i).setVisibility(View.VISIBLE);
ScaleAnimation animationScale1 = new ScaleAnimation(0.0f, 1.2f, 0.0f, 1.2f);
animationScale1.setDuration(800);//动画播放5秒
mImageViews.get(i).startAnimation(animationScale1);
final int finalI = i;
animationScale1.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
ScaleAnimation animationScale2 = new ScaleAnimation(1.2f, 1f, 1.2f, 1f);
animationScale2.setDuration(200);//动画播放52秒
mImageViews.get(finalI).startAnimation(animationScale2);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
}
}
/** * 实现抽象父类LauncherBaseFragment结束动画的方法。 */
@Override
public void stopAnimation() {
started = false;
}
}
Point One
我们第1页动画实现的效果是:当打开应用时,第1页动画开始加载,当4页动画全部浏览完毕时,我们返回查看时,动画不再重新加载,直接显示最后的结果页面。也就是我们从第4页返回第1页时,第1页不再加载。
Point Two
这一页代码比较简单。我们如果想要实现当返回滑动时,第1页不加载,我们就要去除ViewPager的预加载功能。但是在这里我们并没有去除预加载功能。
原因是:我曾经尝试在第1页也去除预加载功能,但导致的结果就是这一页就不必再显示了。所以我们这里使用预加载4页来完成当返回查看时,显示第1页结果的功能。如果我们预加载的是4页,那么,当我们滑动到第4页时,其余的三页也都加载完毕了。
(2). FragmentPageTwo定义
先上代码:
public class FragmentPageTwo extends LauncherBaseFragment {
private View view;
private boolean started = true;//是否开启动画(ViewPage滑动时候给这个变量赋值)
//执行动画的图片
private ImageView mImage1;
private ImageView mImage2;
private ImageView mImage3;
private ImageView mImage4;
private ImageView mImage5;
private ImageView mImage6;
private ImageView mImage7;
private ImageView mImage8;
private ImageView mImage9;
private ImageView mImage10;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(view==null){
view=inflater.inflate(R.layout.activity_setting_about_welcome_page2, null);
}
//缓存的rootView需要判断是否已经被加过parent, 如果有parent需要从parent删除,要不然会发生这个rootview已经有parent的错误。
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null) {
parent.removeView(view);
}
//获得执行动画的图片对象。
mImage1 = (ImageView) view.findViewById(R.id.imageview1_activity_setting_about_welcome_page2);
mImage2 = (ImageView) view.findViewById(R.id.imageview2_activity_setting_about_welcome_page2);
mImage3 = (ImageView) view.findViewById(R.id.imageview3_activity_setting_about_welcome_page2);
mImage4 = (ImageView) view.findViewById(R.id.imageview4_activity_setting_about_welcome_page2);
mImage5 = (ImageView) view.findViewById(R.id.imageview5_activity_setting_about_welcome_page2);
mImage6 = (ImageView) view.findViewById(R.id.imageview6_activity_setting_about_welcome_page2);
mImage7 = (ImageView) view.findViewById(R.id.imageview7_activity_setting_about_welcome_page2);
mImage8 = (ImageView) view.findViewById(R.id.imageview8_activity_setting_about_welcome_page2);
mImage9 = (ImageView) view.findViewById(R.id.imageview9_activity_setting_about_welcome_page2);
mImage10 = (ImageView) view.findViewById(R.id.imageview10_activity_setting_about_welcome_page2);
return view;
}
@Override
public void startAnimation() {
if(started){
//楼房的动画
Bitmap bitmapImageShop = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.wel2_shop);
TranslateAnimation translateAnimationShop = new TranslateAnimation(0, 0, -bitmapImageShop.getHeight(), 0);
translateAnimationShop.setDuration(500);//动画播放5秒
mImage1.setVisibility(View.VISIBLE);
mImage1.startAnimation(translateAnimationShop);
translateAnimationShop.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//显示道路一
mImage2.setVisibility(View.VISIBLE);
//森林的动画
Bitmap bitmapImageForest = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.wel2_forest);
TranslateAnimation translateAnimationForest = new TranslateAnimation(0, 0, -bitmapImageForest.getHeight(), 0);
translateAnimationForest.setDuration(500);//动画播放5秒
mImage3.setVisibility(View.VISIBLE);
mImage3.startAnimation(translateAnimationForest);
translateAnimationForest.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//显示道路二
mImage4.setVisibility(View.VISIBLE);
//男孩的动画
Bitmap bitmapImageBoy = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.wel2_boy);
TranslateAnimation translateAnimationBoy = new TranslateAnimation(-bitmapImageBoy.getWidth(), 0, 0, 0);
translateAnimationBoy.setDuration(500);//动画播放5秒
mImage5.setVisibility(View.VISIBLE);
mImage5.startAnimation(translateAnimationBoy);
translateAnimationBoy.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//电脑的动画
Bitmap bitmapImageComputer = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.wel2_computer);
AlphaAnimation alphaAnimationComputer = new AlphaAnimation(0.0f,1.0f);
alphaAnimationComputer.setDuration(200);//动画播放5秒
mImage6.setVisibility(View.VISIBLE);
mImage6.startAnimation(alphaAnimationComputer);
alphaAnimationComputer.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//显示道路三
mImage7.setVisibility(View.VISIBLE);
//药品的动画
Bitmap bitmapImageInjection = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.wel2_injection);
TranslateAnimation translateAnimationInjection = new TranslateAnimation(bitmapImageInjection.getWidth(), 0, 0, 0);
translateAnimationInjection.setDuration(500);//动画播放5秒
mImage8.setVisibility(View.VISIBLE);
mImage8.startAnimation(translateAnimationInjection);
translateAnimationInjection.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
mImage9.setVisibility(View.VISIBLE);
Bitmap bitmapImageMoney = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.wel2_money);
AlphaAnimation alphaAnimationMoney = new AlphaAnimation(0.0f,1.0f);
alphaAnimationMoney.setDuration(200);//动画播放5秒
mImage10.setVisibility(View.VISIBLE);
mImage10.startAnimation(alphaAnimationMoney);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
}
@Override
public void stopAnimation() {
started = false;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
if (isVisibleToUser) {
//fragment可见时加载数据
startAnimation();
stopAnimation();
} else {
//不可见时不执行操作
}
super.setUserVisibleHint(isVisibleToUser);
}
}
Point
为了实现当滑动到该页面时,页面动画才加载的效果,这里我们去除了预加载功能:
1.首先判断View是否已被加载,如果已加载,则先移除(这里只是为了防止view已存在parent而报错)。
if(view==null){
view=inflater.inflate(R.layout.activity_setting_about_welcome_page2, null);
}
//缓存的View需要判断是否已经被加过parent, 如果有parent需要从parent删除,要不然会发生这个view已经有parent的错误。
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null) {
parent.removeView(view);
}
2.为了防止预加载,我们需要重写下面这个方法:
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
if (isVisibleToUser) {
//fragment可见时加载数据
startAnimation();//当Fragment可见时,执行动画,结束后执行停止动画方法。
stopAnimation();
} else {
//不可见时不执行操作
}
super.setUserVisibleHint(isVisibleToUser);
}
接下来的两个页面FragmentPageThree和FragmentPageFour与FragmentPageTwo实现是相同的就是,startAnimation()方法中动画效果的实现是不同的。这里不再重复讲解。
源码下载