[Android開發實戰]金山清理大師(獵豹清理大師)一鍵加速快捷方式動畫實現

轉載請註明出處:http://blog.csdn.net/ruils/article/details/16922557

最近有人問我金山清理大師桌面上的一鍵加速的動畫是如何實現的,我下了個金山清理大師裝在手機上,體現了一把,感覺還不錯,所以就花了點時間研究了一下。

先看看效果:


點一下,

 

第一感覺就是在Window中增加View的做法來實現的,像360衛士的懸浮窗那樣,而且這個動畫效果會隨着一鍵加速圖標在桌面上的位置改變而改變,放在什麼地方就從什麼地方開始做動畫,放在左邊屏幕,就會向右邊做動畫,放在右邊屏幕會向左邊做動畫,在自己的代碼中怎麼才能知道自己的圖標所在屏幕的位置呢,百思不得其解,後來看了下Log,才發現其中的奧祕

Log:

I/ActivityManager(595): START u0 {act=android.intent.action.MAIN flg=0x10000000 cmp=com.cleanmaster.mguard_cn/com.cleanmaster.processcleaner.ProcessCleanerActivity bnds=[216,385][376,585]} from pid 866

從log中可以看出,點擊一鍵加速的圖標,實現上是啓動了一個activity,而且還帶有參數:bnds=[216,385][376,585],我去找了下Lanucher中的代碼,

packages/apps/Launcher2/src/com/android/launcher2/

Launcher.java

2001         Object tag = v.getTag();
2002         if (tag instanceof ShortcutInfo) {
2003             // Open shortcut
2004             final Intent intent = ((ShortcutInfo) tag).intent;
2005             int[] pos = new int[2];
2006             v.getLocationOnScreen(pos);
2007             intent.setSourceBounds(new Rect(pos[0], pos[1],
2008                     pos[0] + v.getWidth(), pos[1] + v.getHeight()));
2009 
2010             boolean success = startActivitySafely(v, intent, tag);
2011 
2012             if (success && v instanceof BubbleTextView) {
2013                 mWaitingForResume = (BubbleTextView) v;
2014                 mWaitingForResume.setStayPressed(true);
2015             }
2016         } else if (tag instanceof FolderInfo) {

只有在點擊一個快捷方式的時候,纔會有附帶座標信息,原來這個一鍵加速是個快捷方式!現在明白了,點擊一個快捷方式圖標的時候,Lanucher會把此快捷方式的矩形的座標放在Intent中傳給所啓動的activity。

intent.setSourceBounds
既然知道這個座標是怎麼放的了,那取出來就簡單了:

intent.getSourceBounds();

那接下來就一步一步實現這個動畫

程序中用到的圖片資源,我是從金山清理大師的APK中拿出來的,僅供學習參考之用!


1.首先要添加一個快捷方式到桌面

請參考我寫的另外一篇博客:

[Android開發實戰]添加快捷方式到桌面的兩種方式

2.創建這個快捷方式啓動的Activity.

這個activity得是透明的,我們創建一個Style

    <style name="Transparent">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
    </style>
然後把這個Style應用到這個Activity上:

  <activity
            android:name="com.cleanmanager.AnimationActivity"
            android:theme="@style/Transparent" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </activity>

注意給Activity加上<action android:name="android.intent.action.MAIN" />,因爲這個Activity要從別的程序(Lanucher)中啓動,所以這個Activity要能夠做爲一個啓動的入口。


3. 在onCreate方法中,把動畫所需要的佈局文件顯示在快捷方式所在的位置:

// 取得Lanucher傳過來的所點擊的快捷方式的矩形座標。
		rect = intent.getSourceBounds();
		if (rect == null) {
			finish();
			return;
		}

		Log.d(TAG, rect.toShortString());

		mRelativeLayout = (RelativeLayout) findViewById(R.id.framelayout);
		mShortcut = (RelativeLayout) findViewById(R.id.shortcut);

		backImageView = (ImageView) findViewById(R.id.clean_back);
		roateImageView = (ImageView) findViewById(R.id.clean_rotate);
		// iconmageView = (ImageView) findViewById(R.id.clean_icon);
		textView = (TextView) findViewById(R.id.text);

		// DisplayMetrics dm = new DisplayMetrics();
		int width = getWindowManager().getDefaultDisplay().getWidth();
		int hight = getWindowManager().getDefaultDisplay().getHeight();

		Log.d(TAG, "width = " + width);
		Log.d(TAG, "hight = " + hight);

		RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mShortcut
				.getLayoutParams();
		layoutParams.topMargin = rect.top - (rect.bottom - rect.top) / 4;

		// 判斷快捷方式在屏幕的哪一邊,如果在左邊,伸縮動畫就會向右,如果在右邊,伸縮動畫向左。
		if (rect.left < width / 2) {
			direction = Direction.RIGHT;
			layoutParams.leftMargin = rect.left;

		} else {
			direction = Direction.LEFT;
			layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
			layoutParams.rightMargin = width - rect.right;
			Log.d(TAG, "rightMargin = " + (width - rect.right));
		}

		mRelativeLayout.updateViewLayout(mShortcut, layoutParams);

快捷方式在屏幕左邊的時候,就以左邊爲基準,快捷方式在屏幕右邊的時候,就以右邊爲基準。


4.在onAttachedToWindow的時候,開始做旋轉動畫。 我們模擬金山清理大師正在清理,兩秒鐘之後,清理完了,開始做伸縮了

	@Override
	public void onAttachedToWindow() {
		super.onAttachedToWindow();
		// 旋轉動畫開始
		roateImageView.startAnimation(AnimationUtils.loadAnimation(this,
				R.anim.rotate_anim));

		// 假設垃圾清理了兩秒鐘,然後開如做伸縮動畫。
		mHandler.sendEmptyMessageDelayed(MESSAGE_ROTATE_FINISHED, 2000);
	}

5.把旋轉動畫清除,然後開始拉伸updateWidth();

	private Handler mHandler = new Handler() {

		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case MESSAGE_ROTATE_FINISHED:
				mWidth = backImageView.getWidth();
				Log.d(TAG, "mWidth = " + mWidth);
				updateWidth();
				roateImageView.clearAnimation();
				roateImageView.setVisibility(View.INVISIBLE);
				break;
			case MESSAGE_UPDATE_WIDTH:
				updateWidth();
				break;

			default:
				break;
			}

		};

6.主要是通過不停的加大拉伸ImageView的寬度來實現拉伸動畫。實現方式有很多種,可以自定義View,以後我會講解如何自定義View,這裏用的比較簡單的方式實現的。

定義寬度到達以前寬度的2.5倍就線束動畫,顯示文字。

	private void updateWidth() {
		// 寬度沒有達到原來寬度的2.5度,繼續做動畫
		if (backImageView.getWidth() <= 2.5f * mWidth) {
			RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) backImageView
					.getLayoutParams();
			// 每次增加20的寬度,可以自行設置,和用戶體驗有關係,可自行調整
			layoutParams.width = backImageView.getWidth() + 20;
			mShortcut.updateViewLayout(backImageView, layoutParams);
			// 繼續發更新消息。也可發送delay消息,和用戶體驗有關係,<span style="font-family: Arial, Helvetica, sans-serif;">可自行調整</span>
			mHandler.sendEmptyMessage(MESSAGE_UPDATE_WIDTH);
		} else {
			textView.setVisibility(View.VISIBLE);

		}

	};


看下效果:



點一下,



如果您喜歡這篇文章請點贊哦!

最後附上源碼:

示例源碼下載:http://download.csdn.net/detail/u012379847/6604299

Github地址:https://github.com/seashell752/CleanManager


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