android佈局3D旋轉

其實網上的3D旋轉的例子很多,在這裏我只是想把其代碼做一個解釋。

先上圖:


代碼:

TurnAroundActivity

/**
 * 圖片瀏覽器的主Activity。
 * 
 * @author guolin
 */
public class TurnAroundActivity extends Activity {

	/**
	 * 根佈局
	 */
	private RelativeLayout layout;

	/**
	 * 用於展示圖片列表的ListView
	 */
	private ListView picListView;

	/**
	 * 翻轉後的佈局
	 */
	private LinearLayout picture;

	/**
	 * 圖片列表的適配器
	 */
	private PictureAdapter adapter;

	/**
	 * 存放所有圖片的集合
	 */
	private List<Picture> picList = new ArrayList<Picture>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_around);
		// 對圖片列表數據進行初始化操作
		initPics();
		layout = (RelativeLayout) findViewById(R.id.layout);
		picListView = (ListView) findViewById(R.id.pic_list_view);
		picture = (LinearLayout) findViewById(R.id.picture);
		adapter = new PictureAdapter(this, 0, picList);
		picListView.setAdapter(adapter);
		picListView.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				
				// 獲取佈局的中心點位置,作爲旋轉的中心點
				float centerX = layout.getWidth() / 2f;
				float centerY = layout.getHeight() / 2f;
				// 構建3D旋轉動畫對象,旋轉角度爲0到90度,這使得ListView將會從可見變爲不可見
				final Rotate3dAnimation rotation = new Rotate3dAnimation(0, 90, centerX, centerY,
						310.0f, true);
				// 動畫持續時間500毫秒
				rotation.setDuration(500);
				// 動畫完成後保持完成的狀態
				rotation.setFillAfter(true);
				rotation.setInterpolator(new AccelerateInterpolator());
				// 設置動畫的監聽器
				rotation.setAnimationListener(new TurnToImageView());
				layout.startAnimation(rotation);
			}
		});
		picture.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// 獲取佈局的中心點位置,作爲旋轉的中心點
				float centerX = layout.getWidth() / 2f;
				float centerY = layout.getHeight() / 2f;
				// 構建3D旋轉動畫對象,旋轉角度爲360到270度,這使得ImageView將會從可見變爲不可見,並且旋轉的方向是相反的
				final Rotate3dAnimation rotation = new Rotate3dAnimation(360, 270, centerX,
						centerY, 310.0f, true);
				// 動畫持續時間500毫秒
				rotation.setDuration(500);
				// 動畫完成後保持完成的狀態
				rotation.setFillAfter(true);
				rotation.setInterpolator(new AccelerateInterpolator());
				// 設置動畫的監聽器
				rotation.setAnimationListener(new TurnToListView());
				layout.startAnimation(rotation);
			}
		});
	}

	/**
	 * 初始化圖片列表數據。
	 */
	private void initPics() {
		Picture bird = new Picture("Bird", R.drawable.bird);
		picList.add(bird);
		Picture winter = new Picture("Winter", R.drawable.winter);
		picList.add(winter);
		Picture autumn = new Picture("Autumn", R.drawable.autumn);
		picList.add(autumn);
		Picture greatWall = new Picture("Great Wall", R.drawable.great_wall);
		picList.add(greatWall);
		Picture waterFall = new Picture("Water Fall", R.drawable.water_fall);
		picList.add(waterFall);
	}

	/**
	 * 註冊在ListView點擊動畫中的動畫監聽器,用於完成ListView的後續動畫。
	 * 
	 * @author guolin
	 */
	class TurnToImageView implements AnimationListener {

		@Override
		public void onAnimationStart(Animation animation) {
		}

		/**
		 * 當ListView的動畫完成後,還需要再啓動ImageView的動畫,讓ImageView從不可見變爲可見
		 */
		@Override
		public void onAnimationEnd(Animation animation) {
			// 獲取佈局的中心點位置,作爲旋轉的中心點
			float centerX = layout.getWidth() / 2f;
			float centerY = layout.getHeight() / 2f;
			// 將ListView隱藏
			picListView.setVisibility(View.GONE);
			// 將ImageView顯示
			picture.setVisibility(View.VISIBLE);
			picture.requestFocus();
			// 構建3D旋轉動畫對象,旋轉角度爲270到360度,這使得ImageView將會從不可見變爲可見
			final Rotate3dAnimation rotation = new Rotate3dAnimation(270, 360, centerX, centerY,
					310.0f, false);
			// 動畫持續時間500毫秒
			rotation.setDuration(500);
			// 動畫完成後保持完成的狀態
			rotation.setFillAfter(true);
			rotation.setInterpolator(new AccelerateInterpolator());
			layout.startAnimation(rotation);
		}

		@Override
		public void onAnimationRepeat(Animation animation) {
		}

	}

	/**
	 * 註冊在ImageView點擊動畫中的動畫監聽器,用於完成ImageView的後續動畫。
	 * 
	 * @author guolin
	 */
	class TurnToListView implements AnimationListener {

		@Override
		public void onAnimationStart(Animation animation) {
		}

		/**
		 * 當ImageView的動畫完成後,還需要再啓動ListView的動畫,讓ListView從不可見變爲可見
		 */
		@Override
		public void onAnimationEnd(Animation animation) {
			// 獲取佈局的中心點位置,作爲旋轉的中心點
			float centerX = layout.getWidth() / 2f;
			float centerY = layout.getHeight() / 2f;
			// 將ImageView隱藏
			picture.setVisibility(View.GONE);
			// 將ListView顯示
			picListView.setVisibility(View.VISIBLE);
			picListView.requestFocus();
			// 構建3D旋轉動畫對象,旋轉角度爲90到0度,這使得ListView將會從不可見變爲可見,從而回到原點
			final Rotate3dAnimation rotation = new Rotate3dAnimation(90, 0, centerX, centerY,
					310.0f, false);
			// 動畫持續時間500毫秒
			rotation.setDuration(500);
			// 動畫完成後保持完成的狀態
			rotation.setFillAfter(true);
			rotation.setInterpolator(new AccelerateInterpolator());
			layout.startAnimation(rotation);
		}

		@Override
		public void onAnimationRepeat(Animation animation) {
		}

	}

}

關鍵類:
Rotate3dAnimation

/**
 * An animation that rotates the view on the Y axis between two specified
 * angles. This animation also adds a translation on the Z axis (depth) to
 * improve the effect.
 */
public class Rotate3dAnimation extends Animation {
	private final float mFromDegrees;
	private final float mToDegrees;
	private final float mCenterX;
	private final float mCenterY;
	private final float mDepthZ;
	private final boolean mReverse;
	private Camera mCamera;

	/**
	 * Creates a new 3D rotation on the Y axis. The rotation is defined by its
	 * start angle and its end angle. Both angles are in degrees. The rotation
	 * is performed around a center point on the 2D space, definied by a pair of
	 * X and Y coordinates, called centerX and centerY. When the animation
	 * starts, a translation on the Z axis (depth) is performed. The length of
	 * the translation can be specified, as well as whether the translation
	 * should be reversed in time.
	 * 
	 * @param fromDegrees
	 *            the start angle of the 3D rotation
	 * @param toDegrees
	 *            the end angle of the 3D rotation
	 * @param centerX
	 *            the X center of the 3D rotation
	 * @param centerY
	 *            the Y center of the 3D rotation
	 * @param reverse
	 *            true if the translation should be reversed, false otherwise
	 */
	public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX, float centerY,
			float depthZ, boolean reverse) {
		mFromDegrees = fromDegrees;
		mToDegrees = toDegrees;
		mCenterX = centerX;
		mCenterY = centerY;
		mDepthZ = depthZ;
		mReverse = reverse;
	}

	@Override
	public void initialize(int width, int height, int parentWidth, int parentHeight) {
		super.initialize(width, height, parentWidth, parentHeight);
		mCamera = new Camera();
	}

	@Override
	protected void applyTransformation(float interpolatedTime, Transformation t) {
		final float fromDegrees = mFromDegrees;
		float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
		final float centerX = mCenterX;
		final float centerY = mCenterY;
		final Camera camera = mCamera;
		final Matrix matrix = t.getMatrix();
		camera.save();
		//z軸上的景深
		if (mReverse) {
			camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
		} else {
			camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
		}
		camera.rotateY(degrees);
		camera.getMatrix(matrix);
		camera.restore();
		//camera.rotateY(degrees);其實圍繞y軸旋轉的座標點是在(0,0);
		//爲了讓其在圍繞(centerX, centerY)點
		//preTranslate 作用爲在rotateY開始之前先把座標(centerX, centerY)移到中心點
		matrix.preTranslate(-centerX, -centerY);
		//postTranslate 當執行完rotateY後再把中心點移動回來
		matrix.postTranslate(centerX, centerY);
	}
}

layout文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
     >

    <ListView
        android:id="@+id/pic_list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" 
        >
    </ListView>
    
    <LinearLayout 
        android:id="@+id/picture"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:orientation="vertical"
        android:visibility="gone"
        >
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/text"
            android:text="ddddddd"/>
        <ImageView 
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:src="@drawable/bird"
            />
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="ddddddd"/>
        
    </LinearLayout>

</RelativeLayout>
源代碼下載:

android 3D佈局旋轉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章