Android Animation動畫實戰(一): 從布局動畫引入ListView滑動時,每一Item項的顯示動畫

來源:互聯網
上載者:User

標籤:android動畫   布局動畫   listview滑動進入動畫   

前言:

  之前,我已經寫了兩篇博文,給大家介紹了Android的基礎動畫是如何?的,如果還不清楚的,可以點擊查看:Android Animation動畫詳解(一): 補間動畫 及 Android Animation動畫詳解(二): 組合動畫特效 。 已經熟悉了基礎動畫的實現後,便可以試著去實現常見APP中出現過的那些精美的動畫。今天我主要給大家引入一個APP的ListView的動畫效果: 當展示ListView時,Listview的每一個清單項目都按照規定的動畫顯示出來。

  說起來比較抽象,先給大家看一個動畫效果,這是APP窩牛裝修的ListView顯示動畫:


    有木有覺得很酷炫?有木有啊!?


一、Layout Animation

    所謂的布局動畫,其實就是為ViewGroup添加顯示動畫效果,主要用過LayoutAnimationController來控制實現。LayoutAnimationController用於為一個Layout裡面的控制項,或者是一個ViewGroup裡面的控制項設定動畫效果,可以在XML檔案中設定,亦可以在Java代碼中設定。


1.1 在XML檔案中設定布局動畫


  首先,我們在res/anim檔案夾下建立一個list_anim_layout.xml檔案,該檔案就是布局動畫控制器。

<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"    android:delay="30%"    android:animationOrder="random"    android:animation="@anim/slide_right" />

android:delay  子類動畫時間間隔 (延遲)   70% 也可以是一個浮點數 如“1.2”等。
android:animationOrder="random"   子類的顯示方式 random表示隨機。
android:animationOrder 的取值有 
     normal 0   預設
     reverse 1 倒序
     random 2  隨機
android:animation="@anim/slide_right" 表示清單項目顯示時的具體動畫是什麼!

下面,我們定義每一個清單項目顯示時的動畫效果吧,及slide_right.xml:

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"    android:interpolator="@android:anim/accelerate_interpolator">    <translate        android:duration="3000"        android:fromXDelta="100%p"        android:toXDelta="0%p" /></set>

顯示的效果為ListView第一次出現的時候為 item隨機出現 每個Item都是從右邊的地區向左滑動到顯示的地方。

接下來,你只需要把這個布局動畫,指定到ViewGroup上就好了:

<ListView        android:id="@+id/listView"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layoutAnimation="@anim/list_anim_layout"        ></ListView>
就這麼簡單就完成了,快來看下效果吧:




1.2 在Java代碼中實現布局動畫

    在Java代碼中實現布局動畫並無難度,只要熟悉幾個API的使用即可。 關於動畫的定義和上文一致,只是,你不需要再在把控制動畫應用到listview中了,即android:layoutAnimation="@anim/list_anim_layout"這行代碼可以刪除。

    接下來,需要在Java代碼中進行配置:

    private void startLayoutAnim() {        //通過載入XML動畫設定檔案來建立一個Animation對象;        Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_right);        //得到一個LayoutAnimationController對象;        LayoutAnimationController lac = new LayoutAnimationController(animation);        //設定控制項顯示的順序;        lac.setOrder(LayoutAnimationController.ORDER_REVERSE);        //設定控制項顯示間隔時間;        lac.setDelay(1);        //為ListView設定LayoutAnimationController屬性;        listView.setLayoutAnimation(lac);    }


    觀察下,效果和之前使用xml檔案肯定是一致的了。

    

    介紹到這裡,可能有人會有疑問了,博文一開始介紹的“窩牛裝修”的那種效果,是每一個清單項目顯示的時候才會顯示動畫。我們這個確實所有的清單項目的動畫一起都顯示了,只是顯示順序不同而已。 通過我們這種方法,怎麼可能會達到那種效果呢?

    確實,通過布局動畫,沒辦法控制每一個Item在載入時才顯示動畫。那該如何是好呢?

    兄弟們,換個思路吧,如果布局動畫完成不了,何必不直接用簡單的補間動畫,再結合每個清單項目的顯示控制,來實現窩牛裝修列表顯示的效果呢? 

    那有人會問了,怎麼知道每一個清單項目何時才載入嗎?

    你難道忘了BaseAdapter的getView()方法了嗎?

    沒錯,每當一個清單項目顯示時,都會主動調用BaseAdaper的getView()方法。


二、仿窩牛裝修List列表的動畫效果

    首先,我們定義一個動畫資源,該動畫即是清單項目顯示時的動畫:woniu_list_item.xml

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"    android:interpolator="@android:anim/accelerate_interpolator"    >    <!--    woniu list item animation    -->    <translate        android:duration="500"        android:fromXDelta="0"        android:fromYDelta="100"        android:toXDelta="0"        android:toYDelta="0" /></set>

    該平移動畫表示,從下往上,垂直平移100px,時間為500毫秒。

    接下來,我們需要在BaseAdapter的getView()方法裡,去使用該動畫:

import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;public class WoniuListAdapter extends BaseAdapter {    private Context mContext;    private LayoutInflater mInflater;    private List<WoniuSimple> mDatas;    private Animation animation;    public WoniuListAdapter(Context context, List<WoniuSimple> datas) {        mContext = context;        mInflater = LayoutInflater.from(mContext);        mDatas = datas;        animation = AnimationUtils.loadAnimation(mContext, R.anim.woniu_list_item);    }    @Override    public int getCount() {        return (mDatas != null ? mDatas.size() : 0);    }    @Override    public Object getItem(int position) {        return (mDatas != null ? mDatas.get(position) : null);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(final int position, View convertView, ViewGroup parent) {        ViewHolder holder = null;        int type = getItemViewType(position);        if (convertView == null) {            // 下拉項布局            convertView = mInflater.inflate(R.layout.list_item_woniu, null);            holder = new ViewHolder();            holder.tem_img = (ImageView) convertView.findViewById(R.id.tem_img);            holder.text_name = (TextView) convertView.findViewById(R.id.text_name);            holder.text_name = (TextView) convertView.findViewById(R.id.text_name);            convertView.setTag(holder);        } else {            holder = (ViewHolder) convertView.getTag();        }        convertView.startAnimation(animation);        final WoniuSimple materialSimple = mDatas.get(position);        if (materialSimple != null) {//            holder.tem_img.setImageResource(R.mipmap.assist_default_img);//            holder.text_name.setText(materialSimple.name);//            holder.text_mobile.setText(materialSimple.mobile);        }        return convertView;    }    class ViewHolder {        ImageView tem_img;        TextView text_name;        TextView text_mobile;    }}

    我們來簡要分析應用動畫的地方: 1、我們Adapter的構造方法裡載入了之前定義的動畫,活的Animation對象。 2、 我們在getView方法裡,為convertView設定並啟動Animation,即convertView.startAnimation(animation)。

    夠簡單吧,只是這麼兩行代碼,就可以實現在載入每一個View Item時啟動動畫效果。

    可是,我們發現,這並不是非常完美的實現,為啥這麼說呢?

    因為你此刻往上滑動列表,會發現,已經載入過的Item的動畫還會再次啟動執行一次。這個體驗太糟糕了。為啥會出現這種情況啊?

    因為getVIew方法的調用時機會對動畫產生影響。Adapter中的getView方法,會在每一個item處於可見狀態時調用,所以無論你上滑還是下滑,都會重複調用getView方法(這也是ListView為啥在使用時要進行最佳化的地方)。

    所以,為瞭解決剛剛發生的問題,我們可以設定標識,進行判斷,已經載入過的view的動畫不再進行啟動載入。

    完整的代碼如下:

package com.lnyp.layoutanimation;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.HashMap;import java.util.List;import java.util.Map;public class WoniuListAdapter extends BaseAdapter {    private Context mContext;    private LayoutInflater mInflater;    private List<WoniuSimple> mDatas;    private Animation animation;    private Map<Integer, Boolean> isFrist;    public WoniuListAdapter(Context context, List<WoniuSimple> datas) {        mContext = context;        mInflater = LayoutInflater.from(mContext);        mDatas = datas;        animation = AnimationUtils.loadAnimation(mContext, R.anim.woniu_list_item);        isFrist = new HashMap<Integer, Boolean>();    }    @Override    public int getCount() {        return (mDatas != null ? mDatas.size() : 0);    }    @Override    public Object getItem(int position) {        return (mDatas != null ? mDatas.get(position) : null);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(final int position, View convertView, ViewGroup parent) {        ViewHolder holder = null;        int type = getItemViewType(position);        if (convertView == null) {            // 下拉項布局            convertView = mInflater.inflate(R.layout.list_item_woniu, null);            holder = new ViewHolder();            holder.tem_img = (ImageView) convertView.findViewById(R.id.tem_img);            holder.text_name = (TextView) convertView.findViewById(R.id.text_name);            holder.text_name = (TextView) convertView.findViewById(R.id.text_name);            convertView.setTag(holder);        } else {            holder = (ViewHolder) convertView.getTag();        }        // 如果是第一次載入該view,則使用動畫        if (isFrist.get(position) == null || isFrist.get(position)) {            convertView.startAnimation(animation);            isFrist.put(position, false);        }        final WoniuSimple materialSimple = mDatas.get(position);        if (materialSimple != null) {//            holder.tem_img.setImageResource(R.mipmap.assist_default_img);//            holder.text_name.setText(materialSimple.name);//            holder.text_mobile.setText(materialSimple.mobile);        }        return convertView;    }    class ViewHolder {        ImageView tem_img;        TextView text_name;        TextView text_mobile;    }}

     看到了麼,加了一個isFirst進行判斷,這樣,就可以有效控制動畫的顯示了。效果如下:


   

結束:

     本文我主要介紹了兩個部分,一個是Layout Animation布局動畫,使用布局動畫可以控制VIew Groups中的每一個資料的顯示動畫; 還一個就是實戰,仿“窩牛裝修”ListView滑動時每一個Item滑動進入可見狀態的動畫效果。通過這兩個動畫樣本,我相信可以協助大家更好的處理動畫,克服“動畫恐懼症”。


源碼(免費):http://download.csdn.net/detail/zuiwuyuan/9051895


1.1 在XML檔案中設定布局動畫


著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Android Animation動畫實戰(一): 從布局動畫引入ListView滑動時,每一Item項的顯示動畫

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.