前言:不知不覺中又加班到了10點半,整個啟動頁面做了一天多的時間,一共有三個頁面,每個頁面都有動畫效果,動畫效果調試起來麻煩,既要跟ios統一,又要比對各種不同的手機,然後産品經理還有可能在中途改需求,程式員各種苦逼有木有,在這個過程中也學到了蠻多東西的,是以寫一篇部落格跟大家分享一下.
先看效果圖:
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&tid=76&extra=page%3d2" target="_blank">點選下載下傳源碼</a>