天天看點

app引導頁(背景圖檔切換加各個頁面動畫效果)

前言:不知不覺中又加班到了10點半,整個啟動頁面做了一天多的時間,一共有三個頁面,每個頁面都有動畫效果,動畫效果調試起來麻煩,既要跟ios統一,又要比對各種不同的手機,然後産品經理還有可能在中途改需求,程式員各種苦逼有木有,在這個過程中也學到了蠻多東西的,是以寫一篇部落格跟大家分享一下.

先看效果圖:

app引導頁(背景圖檔切換加各個頁面動畫效果)

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<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;  

        public void onpagescrolled(int arg0, float arg1, int arg2) {}  

        public void onpagescrollstatechanged(int arg0) {}  

    };  

     * 改變點點點的切換效果 

     * @param selectitems 

    private void setimagebackground(int selectitems) {  

            if (i == selectitems) {  

                tips[i].setbackgroundresource(r.drawable.page_indicator_focused);  

                tips[i].setbackgroundresource(r.drawable.page_indicator_unfocused);  

}  

2.重寫viewpager   在dispatchdraw方法中控制顯示的背景圖檔區域,

 * 重寫viewpager  主要做一個切換背景的功能 

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);  

    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) {  

    public fragment getitem(int arg0) {  

        return list.get(arg0);  

    public int getcount() {  

        return list.size();  

5.fragment抽象類 有兩個抽象方法,開啟動畫跟停止動畫  所有的fragment都繼承這個類  viewpager切換的時候可以更好的控制每個fragment開啟動畫,結束動畫

 * fragment抽象類 

 *  

public abstract class launcherbasefragment extends fragment{  

    public abstract void  startanimation();  

    public abstract void  stopanimation();  

6.打賞頁fragment  三個動畫效果  硬币向下移動動畫+打賞圖檔縮放動畫+改變打賞圖檔透明度然後隐藏圖檔

 * 打賞頁面 

public class rewardlauncherfragment extends launcherbasefragment{  

    private imageview ivreward;  

    private imageview ivgold;  

    private bitmap goldbitmap;  

    private boolean started;//是否開啟動畫(viewpage滑動時候給這個變量指派)  

    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) {}  

            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) {}    

                        public void onanimationrepeat(animation animation) {}    

                        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) {}  

                                    public void onanimationrepeat(animation animation) {}  

                                    public void onanimationend(animation animation) {  

                                        //透明度動畫結束隐藏圖檔  

                                        ivreward.setvisibility(view.gone);  

                                    }  

                            });  

                        }  

                    });  

                }  

            public void onanimationrepeat(animation animation) {}  

        });  

    public void stopanimation(){  

        started=false;//結束動畫時标示符設定為false  

        ivgold.clearanimation();//清空view上的動畫  

7.私信頁面   四個動畫效果   并且四個動畫都相同,其實隻要我們實作了一個,其他的基本都很容易了.   依次實作四個圖檔的放大然後還原

 * 私信 

public class privatemessagelauncherfragment extends launcherbasefragment{  

    private imageview ivlikevideo,ivthinkreward,ivthisweek,ivwatchmovie;  

    private animation likeanimation,thinkanimation,watchanimation,thisweekanimation;  

    private boolean started;//是否開啟動畫  

        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);  

        //動畫開啟标示符設定成false     

        started=false;  

         * 清空所有控件上的動畫 

        ivlikevideo.clearanimation();  

        ivthinkreward.clearanimation();  

        ivwatchmovie.clearanimation();  

        ivthisweek.clearanimation();  

         * 每次開啟動畫前先隐藏控件 

        ivlikevideo.setvisibility(view.gone);  

        ivthinkreward.setvisibility(view.gone);  

        ivwatchmovie.setvisibility(view.gone);  

        ivthisweek.setvisibility(view.gone);  

        new handler().postdelayed(new runnable() {//延時0.5秒之後開啟喜歡視訊動畫  

            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) {}    

            public void onanimationrepeat(animation animation) {}    

            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(){    

            public void onanimationend(animation animation) {  

                    watchmovie();  

     * 一起看個電影呗 

    private void watchmovie(){  

        ivwatchmovie.setvisibility(view.visible);  

        watchanimation = animationutils.loadanimation(getactivity(),r.anim.private_message_launcher);  

        ivwatchmovie.startanimation(watchanimation);  

        watchanimation.setanimationlistener(new animationlistener(){    

                    thisweek();  

     * 好啊  這周末有空 

    private void thisweek(){  

        ivthisweek.setvisibility(view.visible);  

        thisweekanimation = animationutils.loadanimation(getactivity(),r.anim.private_message_launcher);    

        ivthisweek.startanimation(thisweekanimation);  

8.最後一個引導頁  就兩個動畫  圖檔的放大跟縮小,其實用xml布局的話一個動畫就能搞定,跟私信頁面的動畫差不多.小夥伴寫的代碼.這裡換了一種方式.代碼比較多.

 * 最後一個 

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;  

        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);  

    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() {  

            public void onanimationstart(animation animation) {  

            public void onanimationrepeat(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);  

    }   

    public void onclick(view v) {  

//      intent intent = new intent();  

//      intent.setclass(getactivity(),mainactivity.class);  

//      startactivity(intent);  

//      getactivity().finish();  

    public void startanimation() {  

        playheartbeatanimation();  

    public void stopanimation() {  

最後總結:以上就是三個引導頁的核心代碼了,還有一些布局檔案,動畫效果的布局檔案我就不一一貼出來的,大家可以去下載下傳我的源碼,在這個過程中碰到的幾個大的問題說明一下.

1.viewpager切換的時候要結束上個fragment的動畫   我是通過boolean變量去控制的

2.背景圖檔移動的效果    之前自己走了很多彎路,後面在網上找了一個demo拿過來用了.因為大家都有開源精神是以這裡省了很多功夫

3.圖檔放大縮小以前居然不知道一個xml動畫布局就能搞定.之前一直想辦法用兩個動畫實作

看看時間一篇部落格寫了一個半小時,都12點了,辦公室一個人敲打着鍵盤,記錄着這兩天做過的東西,才發現這也是一件很惬意的事情。。。。閃人。。。回家.

推薦下自己建立的android qq群:202928390 歡迎大家的加入.

<a href="http://www.gongjuxiazai.com/forum.php?mod=viewthread&amp;tid=76&amp;extra=page%3d2" target="_blank">點選下載下傳源碼</a>

繼續閱讀