編輯:關於Android編程
關於布局動畫是針對ViewGroup而言的,意指ViewGroup在增加子View或者刪除子View時其子View的過渡動畫,在android官網有這麼一個簡單的例子,其效果如下,接下來我們就通過這個例子來入門
??事實上,實現上面ViewGroup的布局動畫非常簡單,我們只要給子View所在的ViewGroup的xml中添加下面的屬性即可:
android:animateLayoutChanges="true"
??通過設置以上代碼,當ViewGroup在添加View時,子View會呈現出過渡的動畫效果,這個動畫效果是android默認的顯示效果,而且無法使用自定義的動畫來替換這個效果,不過還是有其他方式可以實現自定義的過渡動畫滴,這個我們後面會分析,下面看看android官方給的demo的代碼實現:
activity_layout_changes.xml布局文件
<framelayout android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"></framelayout>
??布局代碼比較簡單,使用了一個ScrollView包裹了LinearLayout布局並在LinearLayout中添加了屬性android:animateLayoutChanges="true",啟動了android自帶的布局動畫,之所以使用ScrollView,是為了在添加子View多時可以進行滑動,而TextView只不過在沒有子view時一個提示語。接著看看子View的布局文件list_item_example.xml
??主要控件有用於顯示每個子View內容的TextView和用於響應刪除子View事件的ImageButton,最後就是Activity的實現:
LayoutChangesActivity.java
package com.example.android.animationsdemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* This sample demonstrates how to use system-provided, automatic layout transitions. Layout
* transitions are animations that occur when views are added to, removed from, or changed within
* a {@link ViewGroup}.
*
*
In this sample, the user can add rows to and remove rows from a vertical * {@link android.widget.LinearLayout}.
*/ public class LayoutChangesActivity extends Activity { private ViewGroup mContainerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout_changes); mContainerView = (ViewGroup) findViewById(R.id.container); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); //響應添加事件的menu getMenuInflater().inflate(R.menu.activity_layout_changes, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class)); return true; case R.id.action_add_item: //添加子View findViewById(android.R.id.empty).setVisibility(View.GONE); addItem(); return true; } return super.onOptionsItemSelected(item); } private void addItem() { //實例化一個子View final ViewGroup newView = (ViewGroup) LayoutInflater.from(this).inflate( R.layout.list_item_example, mContainerView, false); // 隨機設置子View的內容 ((TextView) newView.findViewById(android.R.id.text1)).setText( COUNTRIES[(int) (Math.random() * COUNTRIES.length)]); //設置刪除按鈕的監聽 newView.findViewById(R.id.delete_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mContainerView.removeView(newView); // If there are no rows remaining, show the empty view. if (mContainerView.getChildCount() == 0) { findViewById(android.R.id.empty).setVisibility(View.VISIBLE); } } }); //添加子View mContainerView.addView(newView, 0); } /** * A static list of country names. */ private static final String[] COUNTRIES = new String[]{ "Belgium", "France", "Italy", "Germany", "Spain", "Austria", "Russia", "Poland", "Croatia", "Greece", "Ukraine", }; }
??代碼比較簡單,mContainerView作為子View的承載容器,我們可以不斷添加子View,也可以移除子View,由於我們在布局文件中啟動了android自帶的布局動畫,所以在添加子View或移除子View都會有過度動畫,現在運行程序,效果如下:
這就是android中最簡單的布局動畫
布局動畫實之layoutAnimation
??除了上面的布局動畫外,有時我們可能需要第一次加載ListView或者GridView的時候能有個動畫的過度效果,以便達到更好的體驗,如下ListView加載子View的效果:
??事實上實現這種效果也比較簡單,我們只需要在ListView的布局文件中添加android:layoutAnimation=”@anim/layout”屬性即可。接下來給出實現步驟:
實現動畫效果
left_into.xml
這個比較簡單,就一個平移和透明度的效果,接著創建layout_animation.xml
這裡簡單介紹一下layoutAnimation標簽屬性:
屬性名
含義
android:delay
delay的單位為秒,表示子View進入的延長時間
android:animationOrder
子類的進入方式 ,其取值有,normal 0 默認 ,reverse 1 倒序 ,random 2 隨機
android:animation
子view要執行的具體動畫的文件,自定義即可
然後設置給listView控件即可,activity_listview.xml:
android:layoutAnimation="@anim/layout_animation"
>
ListViewActivity.java代碼如下:
package com.example.android.animationsdemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by zejian
* Time 16/9/17.
* Description:
*/
public class ListViewActivity extends Activity {
private ListView listView;
private List list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview);
listView= (ListView) findViewById(R.id.listView);
initData();
listView.setAdapter(new Myadpter());
}
public void initData(){
list = new ArrayList<>();
for(int i=1;i<30;i++){
list.add("布局動畫listView測試_"+i);
}
}
private class Myadpter extends BaseAdapter{
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv= new TextView(ListViewActivity.this);
tv.setTextSize(20);
tv.setHeight(100);
tv.setText(list.get(position));
return tv;
}
}
}
??執行以上代碼,效果就是前面我們給出listView進入的動態效果,這裡特別注意的是,動畫只在listView子View第一次進入時有效,如果後面動態給listView添加子View時,此動畫效果無效,當然除了通過xml設置外,我們還可以通過代碼動態設置,代碼范例如下,這裡就不演示了。
//通過加載XML動畫設置文件來創建一個Animation對象,子View進入的動畫
Animation animation=AnimationUtils.loadAnimation(this, R.anim.left_into);
//得到一個LayoutAnimationController對象;
LayoutAnimationController lac=new LayoutAnimationController(animation);
//設置控件顯示的順序;
lac.setOrder(LayoutAnimationController.ORDER_REVERSE);
//設置控件顯示間隔時間;
lac.setDelay(0.5f);
//為ListView設置LayoutAnimationController屬性;
listView.setLayoutAnimation(lac);
??通過AnimationUtils.loadAnimation加載子View的動畫來並返回一個Animation對象,然後將Animation對象設置到LayoutAnimationController中並返回LayoutAnimationController對象,配置LayoutAnimationController對象的一些屬性,最後設置到ListView中,其中LayoutAnimationController對應layoutAnimation標簽,這裡需要注意的是layoutAnimation動畫不僅僅限於ListView,GridView中,也可用於一切ViewGroup中。
布局動畫實之LayoutTransition
??前面我們說過ViewGroup在設置
android:animateLayoutChanges="true"後在添加或者刪除子view時可以啟用系統帶著的動畫效果,但這種效果無法通過自定義動畫去替換。不過還好android官方為我們提供了LayoutTransition類,通過LayoutTransition就可以很容易為ViewGroup在添加或者刪除子view設置自定義動畫的過渡效果了。
??LayoutTransition類用於當前布局容器中需要View添加,刪除,隱藏,顯示時設置布局容器子View的過渡動畫。也就是說利用LayoutTransition,可以分別為需添加或刪除的View對象在移動到新的位置的過程添加過渡的動畫效果。我們可以通過setLayoutTransition()方法為布局容器ViewGroup設置LayoutTransition對象,代碼如下:
//初始化容器動畫
LayoutTransition mTransitioner = new LayoutTransition();
container.setLayoutTransition(mTransitioner);
一般地,Layout中的子View對象有四種動畫變化的形式,如下:
屬性值
含義
LayoutTransition.APPEARING
子View添加到容器中時的過渡動畫效果。
LayoutTransition.CHANGE_APPEARING
子View添加到容器中時,其他子View位置改變的過渡動畫
LayoutTransition.DISAPPEARING
子View從容器中移除時的過渡動畫效果。
LayoutTransition.CHANGE_DISAPPEARING
子View從容器中移除時,其它子view位置改變的過渡動畫
LayoutTransition.CHANGING
子View在容器中位置改變時的過渡動畫,不涉及刪除或者添加操作
下面給出一個例子,先看布局文件activity_layout_animation.xml
比較簡單不啰嗦,接著看看LayoutAnimationActivity.java
package com.example.android.animationsdemo;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
/**
* Created by zejian
* Time 16/9/17.
* Description:
*/
public class LayoutAnimationActivity extends Activity {
private int i = 0;
private LinearLayout container;
private LayoutTransition mTransitioner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout_animation);
container = (LinearLayout) findViewById(R.id.container);
//構建LayoutTransition
mTransitioner = new LayoutTransition();
//設置給ViewGroup容器
container.setLayoutTransition(mTransitioner);
setTransition();
}
private void setTransition() {
/**
* 添加View時過渡動畫效果
*/
ObjectAnimator addAnimator = ObjectAnimator.ofFloat(null, "rotationY", 0, 90,0).
setDuration(mTransitioner.getDuration(LayoutTransition.APPEARING));
mTransitioner.setAnimator(LayoutTransition.APPEARING, addAnimator);
/**
* 移除View時過渡動畫效果
*/
ObjectAnimator removeAnimator = ObjectAnimator.ofFloat(null, "rotationX", 0, -90, 0).
setDuration(mTransitioner.getDuration(LayoutTransition.DISAPPEARING));
mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, removeAnimator);
/**
* view 動畫改變時,布局中的每個子view動畫的時間間隔
*/
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
mTransitioner.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30);
/**
*LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING的過渡動畫效果
* 必須使用PropertyValuesHolder所構造的動畫才會有效果,不然無效!使用ObjectAnimator是行不通的,
* 發現這點時真特麼惡心,但沒想到更惡心的在後面,在測試效果時發現在構造動畫時,”left”、”top”、”bottom”、”right”屬性的
* 變動是必須設置的,至少設置兩個,不然動畫無效,問題是我們即使這些屬性不想變動!!!也得設置!!!
* 我就問您惡不惡心!,因為這裡不想變動,所以設置為(0,0)
*
*/
PropertyValuesHolder pvhLeft =
PropertyValuesHolder.ofInt("left", 0, 0);
PropertyValuesHolder pvhTop =
PropertyValuesHolder.ofInt("top", 0, 0);
PropertyValuesHolder pvhRight =
PropertyValuesHolder.ofInt("right", 0, 0);
PropertyValuesHolder pvhBottom =
PropertyValuesHolder.ofInt("bottom", 0, 0);
/**
* view被添加時,其他子View的過渡動畫效果
*/
PropertyValuesHolder animator = PropertyValuesHolder.ofFloat("scaleX", 1, 1.5f, 1);
final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhBottom, animator).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));
//設置過渡動畫
mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);
/**
* view移除時,其他子View的過渡動畫
*/
PropertyValuesHolder pvhRotation =
PropertyValuesHolder.ofFloat("scaleX", 1, 1.5f, 1);
final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhBottom, pvhRotation).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);
}
public void addView(View view) {
i++;
Button button = new Button(this);
button.setText("布局動畫_" + i);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
container.addView(button, Math.min(1, container.getChildCount()), params);
}
public void removeView(View view) {
if (i > 0)
container.removeViewAt(0);
}
}
??簡單分析一下,LayoutTransition.APPEARING和LayoutTransition.DISAPPEARING的情況下直接使用屬性動畫來設置過渡動畫效果即可,而對於LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必須使用PropertyValuesHolder所構造的動畫才會有效果,不然無效,真特麼惡心, ,但沒想到更惡心的在後面,在測試效果時發現在構造動畫時,”left”、”top”、”bottom”、”right”屬性的變動是必須設置的,至少設置兩個,不然動畫無效,最坑爹的是我們即使這些屬性不想變動!!!也得設置!!!我就問您惡不惡心!,那麼我們不想改變這四個屬性時該如何設置呢?這時只要傳遞的可變參數都一樣就行如下面的(0,0)也可以是(100,100)即可(坑爹啊!測試半天才發現,一直在考慮代碼有沒有問題,最後發現時特麼的也是醉了…….):
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top",0,0);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("left",100,100);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("bottom",0,0);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("right",0,0);
??還有點需要注意的是在使用的ofInt,ofFloat中的可變參數值時,第一個值和最後一個值必須相同,不然此屬性將不會有動畫效果,比如下面首位相同是有效的
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top",100,0,100);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top",0,100,0);
但是如果是下面的設置就是無效的:
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("left",0,100);
??關於PropertyValuesHolder,後面我會分開單獨一篇來分析,這裡我們只需知道PropertyValuesHolder構造的動畫可以設置給ObjectAnimator.ofPropertyValuesHolder()便可以產生響應的動畫效果即可,該方法原型如下:
public static ObjectAnimator ofPropertyValuesHolder(Object target, PropertyValuesHolder... values)
??最後我們通過setAniamtor的方法設置LayoutTransition的5種狀態下的過渡動畫,最後運行一下程序,效果如下:
最後這裡小結一下LayoutTransition的一些常用函數:
函數名稱
說明
setAnimator(int transitionType, Animator animator)
設置不同狀態下的動畫過渡,transitionType取值為, APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING 、CHANGING
setDuration(long duration)
設置所有動畫完成所需要的時長
setDuration(int transitionType, long duration)
設置特定type類型動畫時長,transitionType取值為, APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING 、CHANGING
setStagger(int transitionType, long duration)
設置特定type類型動畫的每個子item動畫的時間間隔 ,transitionType取值為: APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING、CHANGING
setInterpolator(int transitionType, TimeInterpolatZ喎?/kf/ware/vc/" target="_blank" class="keylink">vciBpbnRlcnBvbGF0b3IpPC9jb2RlPjwvY29kZT48L3RkPg0KCTx0ZD48Y29kZT48Y29kZT7J6NbDzNi2qHR5cGXA4NDNtq+7rbXEsuXWtcb3LCB0cmFuc2l0aW9uVHlwZcih1rXOqjogQVBQRUFSSU5HoaJESVNBUFBFQVJJTkehokNIQU5HRV9BUFBFQVJJTkehokNIQU5HRV9ESVNBUFBFQVJJTkehokNIQU5HSU5HPC9jb2RlPjwvY29kZT48L3RkPg0KCTwvdHI+DQoJPHRyPg0KCTx0ZD48Y29kZT48Y29kZT5zZXRTdGFydERlbGF5KGludCB0cmFuc2l0aW9uVHlwZSwgbG9uZyBkZWxheSk8L2NvZGU+PC9jb2RlPjwvdGQ+DQoJPHRkPjxjb2RlPjxjb2RlPsno1sPM2LaodHlwZcDg0M22r7uttcS2r7ut0dPKsSB0cmFuc2l0aW9uVHlwZcih1rXOqiwgQVBQRUFSSU5HoaJESVNBUFBFQVJJTkehokNIQU5HRV9BUFBFQVJJTkehokNIQU5HRV9ESVNBUFBFQVJJTkcgoaJDSEFOR0lORzwvY29kZT48L2NvZGU+PC90ZD4NCgk8L3RyPg0KCTx0cj4NCgk8dGQ+PGNvZGU+PGNvZGU+YWRkVHJhbnNpdGlvbkxpc3RlbmVyKFRyYW5zaXRpb25MaXN0ZW5lciBsaXN0ZW5lcik8L2NvZGU+PC9jb2RlPjwvdGQ+DQoJPHRkPjxjb2RlPjxjb2RlPsno1sO84Mz9xvdUcmFuc2l0aW9uTGlzdGVuZXI8L2NvZGU+PC9jb2RlPjwvdGQ+DQoJPC90cj4NCjwvdGJvZHk+DQo8L3RhYmxlPg0KPHA+PGNvZGU+PGNvZGU+udjT2rzgzP3G973Tv9pUcmFuc2l0aW9uTGlzdGVuZXLUrdDNyOfPwqO6PC9jb2RlPjwvY29kZT48L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;">
/**
* This interface is used for listening to starting and ending events for transitions.
*/
public interface TransitionListener {
/**
* 監聽LayoutTransition當前對應的transitionType類型動畫開始
* @param transition LayoutTransition對象實例
* @param container LayoutTransition綁定的容器-container
* @param view 當前在做動畫的View對象
* @param transitionType LayoutTransition類型,取值有:APPEARING、DISAPPEARING、
* CHANGE_APPEARING、CHANGE_DISAPPEARING、CHANGING
*/
public void startTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType);
/**
* 監聽LayoutTransition當前對應的transitionType類型動畫結束
* @param transition LayoutTransition對象實例
* @param container LayoutTransition綁定的容器-container
* @param view 當前在做動畫的View對象
* @param transitionType LayoutTransition類型,取值有:APPEARING、DISAPPEARING、
* CHANGE_APPEARING、CHANGE_DISAPPEARING、CHANGING
*/
public void endTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType);
}
??注釋比較清晰,就不過多說明,我們如果想在某種transitionType類型動畫開或者結束時設置某些操作,便可實現該接口,測試效果也比較簡單,這裡就不舉例了。ok~,關於布局動畫就先了解這麼多吧。
使用實現了單選功能的ListView,不要問為什麼不使用RecyclerView,RecyclerView真的做得不如ListView和GridView完善全面,但是Re
一.概述1.Android Studio中做混淆,基本就是對Proguard-rules.pro文件的操作。混淆的過程也是有規律可循 2.寫出適合自己代碼的混淆規則 3.
今天練手一下,一起來畫個太極圖吧~最終效果如下:最終效果一般都是先講原理,我就反其道而行,先講實現吧。1.繼承實現初始化方法繼承View,實現基本的構造函數:public
本文實例講述了Android簡單實現自定義流式布局的方法。分享給大家供大家參考,具體如下:首先來看一下 手淘HD - 商品詳情 - 選擇商品屬性 頁面的UI商品有很多尺碼