app引導(dǎo)頁(yè)(背景圖片切換加各個(gè)頁(yè)面動(dòng)畫(huà)效果)
2018-07-20 來(lái)源:編程學(xué)習(xí)網(wǎng)

前言:不知不覺(jué)中又加班到了10點(diǎn)半,整個(gè)啟動(dòng)頁(yè)面做了一天多的時(shí)間,一共有三個(gè)頁(yè)面,每個(gè)頁(yè)面都有動(dòng)畫(huà)效果,動(dòng)畫(huà)效果調(diào)試起來(lái)麻煩,既要跟ios統(tǒng)一,又要匹配各種不同的手機(jī),然后產(chǎn)品經(jīng)理還有可能在中途改需求,程序員各種苦逼有木有,在這個(gè)過(guò)程中也學(xué)到了蠻多東西的,所以寫(xiě)一篇博客跟大家分享一下.
先看效果圖:
1.顯示三個(gè)頁(yè)面的Activity 用view pager去加載三個(gè)fragment實(shí)現(xiàn),控制點(diǎn)點(diǎn)點(diǎn)的切換,監(jiān)聽(tīng)view pager的切換,控制fragment動(dòng)畫(huà)的開(kāi)始跟結(jié)束,重寫(xiě)了view pager,實(shí)現(xiàn)了背景圖片的移動(dòng)效果.
- /**
- * 主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);
- //初始化點(diǎn)點(diǎn)點(diǎn)控件
- 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;//設(shè)置點(diǎn)點(diǎn)點(diǎn)view的左邊距
- layoutParams.rightMargin = 20;//設(shè)置點(diǎn)點(diǎn)點(diǎn)view的右邊距
- group.addView(imageView,layoutParams);
- }
- //獲取自定義viewpager 然后設(shè)置背景圖片
- vPager = (GuideViewPager) findViewById(R.id.viewpager_launcher);
- vPager.setBackGroud(BitmapFactory.decodeResource(getResources(),R.drawable.bg_kaka_launcher));
- /**
- * 初始化三個(gè)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);
- }
- /**
- * 監(jiān)聽(tīng)viewpager的移動(dòng)
- */
- OnPageChangeListener changeListener=new OnPageChangeListener() {
- @Override
- public void onPageSelected(int index) {
- setImageBackground(index);//改變點(diǎn)點(diǎn)點(diǎn)的切換效果
- LauncherBaseFragment fragment=list.get(index);
- list.get(currentSelect).stopAnimation();//停止前一個(gè)頁(yè)面的動(dòng)畫(huà)
- fragment.startAnimation();//開(kāi)啟當(dāng)前頁(yè)面的動(dòng)畫(huà)
- currentSelect=index;
- }
- @Override
- public void onPageScrolled(int arg0, float arg1, int arg2) {}
- @Override
- public void onPageScrollStateChanged(int arg0) {}
- };
- /**
- * 改變點(diǎn)點(diǎn)點(diǎn)的切換效果
- * @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.重寫(xiě)viewpager 在dispatchDraw方法中控制顯示的背景圖片區(qū)域,
- /**
- * 重寫(xiě)ViewPager 主要做一個(gè)切換背景的功能
- * @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)表示除去顯示第一個(gè)ViewPager頁(yè)面用去的背景寬度,剩余的ViewPager需要顯示的背景圖片的寬度。
- * getWidth()等于ViewPager一個(gè)頁(yè)面的寬度,即手機(jī)屏幕寬度。在該計(jì)算中可以理解為滑動(dòng)一個(gè)ViewPager頁(yè)面需要滑動(dòng)的像素值。
- * ((width - n) / (count - 1)) /getWidth()也就表示ViewPager滑動(dòng)一個(gè)像素時(shí),背景圖片滑動(dòng)的寬度。
- * x * ((width - n) / (count - 1)) / getWidth()也就表示ViewPager滑動(dòng)x個(gè)像素時(shí),背景圖片滑動(dòng)的寬度。
- * 背景圖片滑動(dòng)的寬度的寬度可以理解為背景圖片滑動(dòng)到達(dá)的位置。
- */
- 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.主體布局文件 上面放一個(gè)自定義的viewpager 下面放一個(gè)顯示點(diǎn)點(diǎn)的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();
- &nbsnbsp; }
- }
5.Fragment抽象類(lèi) 有兩個(gè)抽象方法,開(kāi)啟動(dòng)畫(huà)跟停止動(dòng)畫(huà) 所有的Fragment都繼承這個(gè)類(lèi) Viewpager切換的時(shí)候可以更好的控制每個(gè)Fragment開(kāi)啟動(dòng)畫(huà),結(jié)束動(dòng)畫(huà)
- /**
- * Fragment抽象類(lèi)
- * @author ansen
- *
- */
- public abstract class LauncherBaseFragment extends Fragment{
- public abstract void startAnimation();
- public abstract void stopAnimation();
- }
6.打賞頁(yè)Fragment 三個(gè)動(dòng)畫(huà)效果 硬幣向下移動(dòng)動(dòng)畫(huà)+打賞圖片縮放動(dòng)畫(huà)+改變打賞圖片透明度然后隱藏圖片
- /**
- * 打賞頁(yè)面
- * @author ansen
- * @create time 2015-08-07
- */
- public class RewardLauncherFragment extends LauncherBaseFragment{
- private ImageView ivReward;
- private ImageView ivGold;
- private Bitmap goldBitmap;
- private boolean started;//是否開(kāi)啟動(dòng)畫(huà)(ViewPage滑動(dòng)時(shí)候給這個(gè)變量賦值)
- @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;
- //向下移動(dòng)動(dòng)畫(huà) 硬幣的高度*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);
- //硬幣移動(dòng)動(dòng)畫(huà)結(jié)束開(kāi)啟縮放動(dòng)畫(huà)
- 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) {
- //縮放動(dòng)畫(huà)結(jié)束 開(kāi)啟改變透明度動(dòng)畫(huà)
- 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) {
- //透明度動(dòng)畫(huà)結(jié)束隱藏圖片
- ivReward.setVisibility(View.GONE);
- }
- });
- }
- });
- }
- }
- @Override
- public void onAnimationRepeat(Animation animation) {}
- });
- }
- @Override
- public void stopAnimation(){
- started=false;//結(jié)束動(dòng)畫(huà)時(shí)標(biāo)示符設(shè)置為false
- ivGold.clearAnimation();//清空view上的動(dòng)畫(huà)
- }
- }
7.私信頁(yè)面 四個(gè)動(dòng)畫(huà)效果 并且四個(gè)動(dòng)畫(huà)都相同,其實(shí)只要我們實(shí)現(xiàn)了一個(gè),其他的基本都很容易了. 依次實(shí)現(xiàn)四個(gè)圖片的放大然后還原
- /**
- * 私信
- * @author ansen
- */
- public class PrivateMessageLauncherFragment extends LauncherBaseFragment{
- private ImageView ivLikeVideo,ivThinkReward,ivThisWeek,ivWatchMovie;
- private Animation likeAnimation,thinkAnimation,watchAnimation,thisWeekAnimation;
- private boolean started;//是否開(kāi)啟動(dòng)畫(huà)
- @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(){
- //動(dòng)畫(huà)開(kāi)啟標(biāo)示符設(shè)置成false
- started=false;
- /**
- * 清空所有控件上的動(dòng)畫(huà)
- */
- ivLikeVideo.clearAnimation();
- ivThinkReward.clearAnimation();
- ivWatchMovie.clearAnimation();
- ivThisWeek.clearAnimation();
- }
- public void startAnimation(){
- started=true;
- /**
- * 每次開(kāi)啟動(dòng)畫(huà)前先隱藏控件
- */
- ivLikeVideo.setVisibility(View.GONE);
- ivThinkReward.setVisibility(View.GONE);
- ivWatchMovie.setVisibility(View.GONE);
- ivThisWeek.setVisibility(View.GONE);
- new Handler().postDelayed(new Runnable() {//延時(shí)0.5秒之后開(kāi)啟喜歡視頻動(dòng)畫(huà)
- @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);//開(kāi)啟動(dòng)畫(huà)
- likeAnimation.setAnimationListener(new AnimationListener(){
- @Override
- public void onAnimationStart(Animation animation) {}
- @Override
- public void onAnimationRepeat(Animation animation) {}
- @Override
- public void onAnimationEnd(Animation animation) {//監(jiān)聽(tīng)動(dòng)畫(huà)結(jié)束
- 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();
- }
- });
- }
- /**
- * 一起看個(gè)電影唄
- */
- 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();
- }
- });
- }
- /**
- * 好啊 nbsp; 這周末有空
- */
- private void thisWeek(){
- ivThisWeek.setVisibility(View.VISIBLE);
- thisWeekAnimation = AnimationUtils.loadAnimation(getActivity(),R.anim.private_message_launcher);
- ivThisWeek.startAnimation(thisWeekAnimation);
- }
- }
8.最后一個(gè)引導(dǎo)頁(yè) 就兩個(gè)動(dòng)畫(huà) 圖片的放大跟縮小,其實(shí)用xml布局的話一個(gè)動(dòng)畫(huà)就能搞定,跟私信頁(yè)面的動(dòng)畫(huà)差不多.小伙伴寫(xiě)的代碼.這里換了一種方式.代碼比較多.
- /**
- * 最后一個(gè)
- * @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(){
- /**
- * 放大動(dòng)畫(huà)
- */
- 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) {
- /**
- * 縮小動(dòng)畫(huà)
- */
- 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);
- // 實(shí)現(xiàn)心跳的View
- imgView_immediate_experience.startAnimation(animationSet);
- }
- });
- // 實(shí)現(xiàn)心跳的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() {
- }
- }
最后總結(jié):以上就是三個(gè)引導(dǎo)頁(yè)的核心代碼了,還有一些布局文件,動(dòng)畫(huà)效果的布局文件我就不一一貼出來(lái)的,大家可以去下載我的源碼,在這個(gè)過(guò)程中碰到的幾個(gè)大的問(wèn)題說(shuō)明一下.
1.viewpager切換的時(shí)候要結(jié)束上個(gè)fragment的動(dòng)畫(huà) 我是通過(guò)boolean變量去控制的
2.背景圖片移動(dòng)的效果 之前自己走了很多彎路,后面在網(wǎng)上找了一個(gè)demo拿過(guò)來(lái)用了.因?yàn)榇蠹叶加虚_(kāi)源精神所以這里省了很多功夫
3.圖片放大縮小以前居然不知道一個(gè)xml動(dòng)畫(huà)布局就能搞定.之前一直想辦法用兩個(gè)動(dòng)畫(huà)實(shí)現(xiàn)
版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。