Property Animation之ObjectAnimator動畫樹狀圖上升增長效果

首先先說下自己理解的MVC模式:

M即是model 數據模型對象  V 即是View是視圖顯示數據的地方,通常Model的數據構造View, C即是Controller 負責Model和View交互、

下面看看百度的說法

MMVC 編程模式編輯

MVC 是一種使用 MVC(Model View Controller 模型-視圖-控制器)設計創建 Web 應用程序的模式:[1] 
  • Model(模型)表示應用程序核心(比如數據庫記錄列表)。
  • View(視圖)顯示數據(數據庫記錄)。
  • Controller(控制器)處理輸入(寫入數據庫記錄)。
MVC 模式同時提供了對 HTML、CSS 和 JavaScript 的完全控制。
Model(模型)是應用程序中用於處理應用程序數據邏輯的部分。
  通常模型對象負責在數據庫中存取數據。
View(視圖)是應用程序中處理數據顯示的部分。
  通常視圖是依據模型數據創建的。
Controller(控制器)是應用程序中處理用戶交互的部分。
  通常控制器負責從視圖讀取數據,控制用戶輸入,並向模型發送數據。
MVC 分層有助於管理複雜的應用程序,因爲您可以在一個時間內專門關注一個方面。例如,您可以在不依賴業務邏輯的情況下專注於視圖設計。同時也讓應用程序的測試更加容易。
MVC 分層同時也簡化了分組開發。不同的開發人員可同時開發視圖、控制器邏輯和業務邏輯。

1.下面講一下Property Animation 屬性動畫的擴展動畫ObjectAnimator

         objectAnimatior是 ValueAnimator的子類,

要指定一個對象及該對象的一個屬性,當屬性值計算完成時自動設置爲該對象的相應屬性,即完成了Property Animation的全部兩步操作。實際應用中一般都會用ObjectAnimator來改變某一對象的某一屬性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,應該滿足以下條件:

  • 對象應該有一個setter函數:set<PropertyName>(駝峯命名法)
  • 如上面的例子中,像ofFloat之類的工場方法,第一個參數爲對象名,第二個爲屬性名,後面的參數爲可變參數,如果values…參數只設置了一個值的話,那麼會假定爲目的值,屬性值的變化範圍爲當前值到目的值,爲了獲得當前值,該對象要有相應屬性的getter方法:get<PropertyName>
  • 如果有getter方法,其應返回值類型應與相應的setter方法的參數類型一致。

  如果上述條件不滿足,則不能用ObjectAnimator,應用ValueAnimator代替。

2.下面就objectAnimator的ofObject方法來舉一個例子

    由於是動態圖我就不耗時做動態圖了,具體的內容就是點擊按鈕原先的畫好的樹狀圖緩緩上升。接下來就直接講解例子了



首先我們先來了解ChartView這個類,先從View講解更容易理解:
public class ChartView extends View {
	ShapeDrawable mDrawableagain;
	// 這個類裏面存放了我們的List<Bar>數據也就是我們的樹狀圖數據
	BarChartData barChartData = null;
	Paint paint;

	public ChartView(Context context) {
		super(context);
		paint = new Paint();
		barChartData = new BarChartData();
	}

	// 調用onDraw
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		//循環barChartData對象取出樹狀圖的參數並畫出
		for (int i = 0; i < barChartData.getBarlist().size(); i++) {
			Bar bardataBar = barChartData.getBarlist().get(i);
			paint.setColor(Color.BLUE);
			paint.setStrokeWidth(2);
			canvas.drawRect(bardataBar.getX(), bardataBar.getY(),
					bardataBar.getWidth(), bardataBar.getHeight(), paint);
		}

	}

}
具體的我都是有註釋:
主程序實現C控制MV
public class MainActivity extends Activity {
	private Button startButton;
	ChartView view;
	ValueAnimator bounceAnim = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		LinearLayout container = (LinearLayout) findViewById(R.id.container);
		startButton = (Button) findViewById(R.id.startButton);
		view = new ChartView(this);
		// 繪製樹狀圖的初始數據
		List<Bar> barlist = new ArrayList<Bar>();
		barlist.add(addTreeView(200, 200, 380, 580));
		barlist.add(addTreeView(480, 300, 660, 580));
		barlist.add(addTreeView(760, 100, 940, 580));
		barlist.add(addTreeView(1040, 300, 1220, 580));
		view.barChartData.setBarlist(barlist);
		view.setBackgroundColor(Color.RED);
		container.addView(view);
		startButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// 點擊產生動畫
				createAnimator();
			}
		});

	}

	public void createAnimator() {
		if (bounceAnim == null) {
			// 傳入初狀態與末狀態實現動畫效果
			BarChartData startXY = new BarChartData();
			List<Bar> barlist = new ArrayList<Bar>();
			barlist.add(addTreeView(200, 200, 380, 580));
			barlist.add(addTreeView(480, 300, 660, 580));
			barlist.add(addTreeView(760, 100, 940, 580));
			barlist.add(addTreeView(1040, 300, 1220, 580));
			startXY.setBarlist(barlist);
			BarChartData endXY = new BarChartData();
			List<Bar> barlist2 = new ArrayList<Bar>();
			barlist2.add(addTreeView(200, 100, 380, 580));
			barlist2.add(addTreeView(480, 100, 660, 580));
			barlist2.add(addTreeView(760, 50, 940, 580));
			barlist2.add(addTreeView(1040, 200, 1220, 580));
			endXY.setBarlist(barlist2);
			// 這裏我用的是 ObjectAnimator的 ofObject (Object target, String
			// propertyName, TypeEvaluator evaluator, Object... values)方法
			// ObjectAnimator的構造使用了ofObject形式的工廠方法,傳入了自定義的evaluator對象
			// 第一個參數表示的是屬性變化的對象,而且這個對象要有一個公共的方法setName()方法,裏面的Name有一個propertyName的參數
			// 的值,第二個參數propertyName就是第一個參數被動畫的屬性
			// 第三個參數表示的是 evaluator這個函數返回的結果線性插值的開始和結束值,用分數表示開始和結束之間的比例值
			// 這個對象具體看XYWHEvaluator這個類,最後兩個參數就是第一個對象的初狀態與末狀態。動畫其實主要是看evaluator這個參數
			bounceAnim = ObjectAnimator.ofObject(view.barChartData, "barlist",
					new XYWHEvaluator(), startXY, endXY);
			// 設置動畫的時間
			bounceAnim.setDuration(3000);

			bounceAnim.addUpdateListener(new AnimatorUpdateListener() {
				@Override
				public void onAnimationUpdate(ValueAnimator animation) {
					// 將要變化的參數傳入View中,在對其進行重繪
					view.barChartData.setBarlist(((BarChartData) animation
							.getAnimatedValue()).getBarlist());
					// invalidate 函數的主要作用是請求View樹進行重繪
					view.invalidate();
				}
			});
			// 開始這個動畫
			bounceAnim.start();
		}

	}

	// 存儲數據用的
	private Bar addTreeView(int x, int y, int width, int height) {
		Bar mbardata = new Bar(x, y, width, height);
		mbardata.setX(x);
		mbardata.setY(y);
		mbardata.setWidth(width);
		mbardata.setHeight(height);
		return mbardata;
	}

}
動畫的重要類XYWHEvaluator
// 實現自己的TypeEvaluator
// 傳入fraction和兩個XYHolder類型的對象
// 返回一個XYHolder對象,其座標值爲兩個輸入參數的相應值線性插值的結果
//public abstract T evaluate (float fraction, T startValue, T endValue)
public class XYWHEvaluator implements TypeEvaluator<BarChartData> {
	// 這個類就是動畫的核心,這裏我把BarChartData當作了一個整體裏面封裝了樹狀圖的數據,
	// 需要做的是將BarChartData當作一個對象,我們要抽象出樹狀圖的上升過程
	// 具體實現就是evaluate的動畫公式 result = x0 + t * (v1 - v0),
	// 我們需要的是對樹狀圖取到上升的效果也就是對其的Y軸參數進行修改
	@Override
	public BarChartData evaluate(float fraction, BarChartData startValue,
			BarChartData endValue) {
		// TODO Auto-generated method stub
		BarChartData barChartData = new BarChartData();
		// 構造一個List<bar>的數組,裏面存儲的就是bar的變化值,上升只需要算出Y軸的變化
		List<Bar> listBar = new ArrayList<Bar>();
		for (int i = 0; i < startValue.getBarlist().size(); i++) {
			// 得到Y軸的數值
			Bar bardata = startValue.getBarlist().get(i);
			Bar bardata2 = endValue.getBarlist().get(i);
			// 通過公式算Y軸變化,公式的意思就是物體的初狀態即x0加上fraction×(末狀態與初狀態的差值)
			// 這裏的fraction可以理解爲百分比,這個時段我增長了多少,總增長×百分比加上初狀態就是此時的狀態
			// 這裏的理解僅僅是我自己的理解,有錯的希望指正
			float y = bardata.getY() + fraction
					* (bardata2.getY() - bardata.getY());
			float x = bardata.getX();
			float width = bardata.getWidth();
			float height = bardata.getHeight();
			Bar bar = new Bar(x, y, width, height);
			listBar.add(bar);
		}
		// 將變化後的bar數值放入barChartData中去就實現這個對象某時刻的狀態
		barChartData.setBarlist(listBar);
		return barChartData;
	}
}

對象類
</pre><pre name="code" class="java">package com.example.barview;

import java.util.ArrayList;
import java.util.List;

//這個類就是包含屬性的對象
public class BarChartData {
	// 對List<Bar>進行set與get方法 也就是實現objectanimatior所需要的條件
	private List<Bar> barlist = new ArrayList<Bar>();

	public List<Bar> getBarlist() {
		return barlist;
	}

	public void setBarlist(List<Bar> barlist) {
		this.barlist = barlist;
	}

}

package com.example.barview;

import android.graphics.drawable.ShapeDrawable;

public class Bar {
	float x;
	float y;
	float width;
	float height;

	Bar(float x, float y, float width, float height) {
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
	}

	public float getX() {
		return x;
	}

	public void setX(float f) {
		this.x = f;
	}

	public float getY() {
		return y;
	}

	public void setY(float f) {
		this.y = f;
	}

	public float getWidth() {
		return width;
	}

	public void setWidth(float width) {
		this.width = width;
	}

	public float getHeight() {
		return height;
	}

	public void setHeight(float height) {
		this.height = height;
	}

}

佈局的話我就放了一個Button就不做解釋了
下面看一下大致的效果圖其實有動畫的


效果最後就是柱子慢慢上升。
下面是文件的下載地址:http://download.csdn.net/detail/kluing/7971061




發佈了74 篇原創文章 · 獲贊 7 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章