Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 仿Win8的metro的UI界面(上)

Android 仿Win8的metro的UI界面(上)

編輯:關於Android編程

 

昨晚沒事手機下載了一些APP,發現現在仿win8的主界面越來越多,在大家見慣了類GridView或者類Tab後,給人一種耳目一新的感覺。今天在eoe上偶然發現已經有人實現了這個功能的源碼(地址:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=327557),馬上下載跑了一下,效果很炫,但是有些bug,比如點擊速度特別快時圖像會被放大,以及點擊時會觸發兩次點擊事件。

本例子基於eoe中這位大神的實現,做了一些簡化,和bug的修復。

效果:

\

首先普及一個小知識點:

我們在項目中有時候需要一個緩慢的梯度數據,例如:控件的寬度以一定的比例增加,然後以相同的比例還原到原來的長度。

 

package com.zhy._01;

public class Test2
{
	public static void main(String[] args)
	{
		float val = 1; 
		float s = 0.85f;
		int i = 0;
		s = (float) Math.sqrt(1 / s);
                System.out.println(val);
		while (i < 5)
		{
			val = val *s ;
			System.out.println(val);
			i++;
		}
		 s = 0.85f;
		i = 0;
		s = (float) Math.sqrt(s);
		while (i < 5)
		{
			val = val *s ;
			System.out.println(val);
			i++;
		}

	}
}

輸出結果:

 

 

1.0
1.0846523
1.1764706
1.2760615
1.384083
1.5012488
1.384083
1.2760615
1.1764706
1.0846523
1.0

很完美吧,基本是個對稱的梯度數據,梯度的幅度由代碼中的s覺得,越接近1幅度越小,反之則反之。

 

 

好了下面開始代碼:

1、布局文件

 




    

        

            

                

                
            

            
        

        
    


布局文件,完成了上面效果圖的靜態效果,如果你不需要添加點擊動畫,或者只需要很簡單的點擊效果,那麼就已經完成這樣的菜單的編寫,再添加個backgroud自定義下點擊效果就好了。當然,我們這裡有個比較柔和的點擊動畫,有自定義的ImageView完成。

 

2、MyImageView.java

 

package com.ljp.ani01;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;

public class MyImageView extends ImageView
{

	private static final String TAG = MyImageView;

	private static final int SCALE_REDUCE_INIT = 0;
	private static final int SCALING = 1;
	private static final int SCALE_ADD_INIT = 6;

	/**
	 * 控件的寬
	 */
	private int mWidth;
	/**
	 * 控件的高
	 */
	private int mHeight;
	/**
	 * 控件的寬1/2
	 */
	private int mCenterWidth;
	/**
	 * 控件的高 1/2
	 */
	private int mCenterHeight;
	/**
	 * 設置一個縮放的常量
	 */
	private float mMinScale = 0.85f;
	/**
	 * 縮放是否結束
	 */
	private boolean isFinish = true;

	public MyImageView(Context context)
	{
		this(context, null);
	}

	public MyImageView(Context context, AttributeSet attrs)
	{
		this(context, attrs, 0);
	}

	public MyImageView(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
	}

	/**
	 * 必要的初始化
	 */
	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom)
	{
		super.onLayout(changed, left, top, right, bottom);
		if (changed)
		{
			mWidth = getWidth() - getPaddingLeft() - getPaddingRight();
			mHeight = getHeight() - getPaddingTop() - getPaddingBottom();

			mCenterWidth = mWidth / 2;
			mCenterHeight = mHeight / 2;

			Drawable drawable = getDrawable();
			BitmapDrawable bd = (BitmapDrawable) drawable;
			bd.setAntiAlias(true);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		switch (event.getAction())
		{
		case MotionEvent.ACTION_DOWN:
			float X = event.getX();
			float Y = event.getY();
			mScaleHandler.sendEmptyMessage(SCALE_REDUCE_INIT);
			break;
		case MotionEvent.ACTION_UP:
			mScaleHandler.sendEmptyMessage(SCALE_ADD_INIT);
			break;
		}
		return true;
	}

	/**
	 * 控制縮放的Handler
	 */
	private Handler mScaleHandler = new Handler()
	{
		private Matrix matrix = new Matrix();
		private int count = 0;
		private float s;
		/**
		 * 是否已經調用了點擊事件
		 */
		private boolean isClicked;

		public void handleMessage(android.os.Message msg)
		{
			matrix.set(getImageMatrix());
			switch (msg.what)
			{
			case SCALE_REDUCE_INIT:
				if (!isFinish)
				{
					mScaleHandler.sendEmptyMessage(SCALE_REDUCE_INIT);
				} else
				{
					isFinish = false;
					count = 0;
					s = (float) Math.sqrt(Math.sqrt(mMinScale));
					beginScale(matrix, s);
					mScaleHandler.sendEmptyMessage(SCALING);
				}
				break;
			case SCALING:
				beginScale(matrix, s);
				if (count < 4)
				{
					mScaleHandler.sendEmptyMessage(SCALING);
				} else
				{
					isFinish = true;
					if (MyImageView.this.mOnViewClickListener != null && !isClicked)
					{
						isClicked = true;
						MyImageView.this.mOnViewClickListener.onViewClick(MyImageView.this);
					} else
					{
						isClicked = false;
					}
				}
				count++;

				break;
			case 6:
				if (!isFinish)
				{
					mScaleHandler.sendEmptyMessage(SCALE_ADD_INIT);
				} else
				{
					isFinish = false;
					count = 0;
					s = (float) Math.sqrt(Math.sqrt(1.0f / mMinScale));
					beginScale(matrix, s);
					mScaleHandler.sendEmptyMessage(SCALING);
				}
				break;
			}
		}
	};

	protected void sleep(int i)
	{
		try
		{
			Thread.sleep(i);
		} catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 縮放
	 * 
	 * @param matrix
	 * @param scale
	 */
	private synchronized void beginScale(Matrix matrix, float scale)
	{
		matrix.postScale(scale, scale, mCenterWidth, mCenterHeight);
		setImageMatrix(matrix);
	}

	/**
	 * 回調接口
	 */
	private OnViewClickListener mOnViewClickListener;

	public void setOnClickIntent(OnViewClickListener onViewClickListener)
	{
		this.mOnViewClickListener = onViewClickListener;
	}

	public interface OnViewClickListener
	{
		void onViewClick(MyImageView view);
	}

}
代碼不算復雜,主要就是對onTouchEvent的Action_Down和Action_Up的監聽,然後通過Handler結合matrix完成縮放的效果。這裡簡單說一個mScaleHandler裡面代碼的邏輯,當檢測到ACTION_DOWN事件,會判斷當前縮放是否完成,如果完成了則添加縮小的效果,如果沒有,則一直檢測。ACTION_UP也是同樣的過程。縮放的梯度就用到了文章開始介紹的小知識點。

 

有人會覺得使用Handler比較麻煩,這裡一直使用Handler.sendMsg的原因是,利用了這個消息隊列,隊列先進先出,保證動畫效果的流暢。因為ACTION_DOWN_與ACTION_UP一瞬點完成的,其實動畫還在進行。如果你在onTouchEvent中用while集合sleep完成動畫,會出現卡死,監聽不到Up事件等問題。


3、主Activity

 

package com.ljp.ani01;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

public class TestRolateAnimActivity extends Activity
{
	MyImageView joke;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		joke = (MyImageView) findViewById(R.id.c_joke);
		joke.setOnClickIntent(new MyImageView.OnViewClickListener()
		{

			@Override
			public void onViewClick(MyImageView view)
			{
				Toast.makeText(TestRolateAnimActivity.this, Joke, 1000).show();
			}
		});
	}
	
	
}

利用提供的回調接口注冊了點擊事件。這裡說明一下,現在為ImageView設置OnClickLIstener是沒有作用的,因為自定義的ImageView的onTouchEvent直接返回了true,不會往下執行click事件,如果你希望通過OnClickLIstener進行注冊,你可以把ontouchevent裡面返回值改成super.ontouchevent(event),並且需要將ImageView的clickable設置為true。這些都是Ontouch事件的傳播機制,不了解的google下,還是很有必要的。

 

 

如果你覺得這篇文章對你有用,可以頂一個~~

 

源碼下載點擊此處

 

 

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved