1. 程式人生 > >Android中GridView中onTouch監聽(1)item實現觸控執行縮放動畫的功能

Android中GridView中onTouch監聽(1)item實現觸控執行縮放動畫的功能

功能:當用戶點選元素,執行圖片縮放動畫,當按住元素並且移開位置離開該元素,之前元素將執行放大回到原狀,而新選中的元素將進行縮放。

效果圖


即:gridview中的元素按住就會下陷變小,移動離開就會變回原樣,點選就會進入跳轉介面

由於為了完整的監聽ontouch事件,即能監聽ACTION_DOWN,MOVE,UP返回值必須為true

但是由於為true導致事件被攔截了,之後的自帶的onItemClickListener的監聽事件不能在使用了

這裡我通過判斷點選時候的位置的item和擡起的item的位置,進行點選事件的判斷

寫了一個工具類,程式碼如下

package com.example.util;

import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.GridView;
import android.widget.Toast;

import com.example.test.R;

public class AnimationUtil {
	// action down按下動畫
	private static Animation downAnimation;
	// action up動畫
	private static Animation upAnimation;
	// 前一個元素
	private static int tempChildViewId = -1;
	// 按下時候的元素,設定為公有方便之後檢視
	public static int downChildViewId = -1;
	// 擡起時候的元素,設定為公有方便之後檢視
	public static int upChildViewId = -2;

	private static boolean isLastView = true;

	/**
	 * 點選每個gridView元素將執行動畫
	 * 
	 * @param v
	 * @param event
	 */
	public static void AnimationAlgorithm(View v, MotionEvent event,
			Context context) {
		// 判斷是不是GridView的v
		if (!(v instanceof GridView))
			return;
		GridView parent = ((GridView) v);
		int count = parent.getChildCount();
		// 沒有元素不做動畫
		if (count == 0)
			return;
		// 獲得每個元素的大小。這裡每個gridView的元素都是相同大小的,取第一個為例。
		int childWidth = parent.getChildAt(0).getWidth() + 10;
		int childHeight = parent.getChildAt(0).getHeight() + 2;
		Log.d("count", "==" + count);
		// 進行事件監聽
		switch (event.getAction()) {
		// 按下的時候,獲得當前元素的id,由於我一行是3個,所以我的y方向上就必須乘以3
		// 例如我按下的是第3個(從第0個開始,第三個為第二行第一列),那麼第三個=點選x的大小/子元素的x的大小+(點選y的大小/子元素的y的大小)*3=0+3=3、
		case MotionEvent.ACTION_DOWN: {
			// 重置
			tempChildViewId = -1;
			downChildViewId = -1;
			upChildViewId = -2;
			isLastView = true;
			// 三目運算子
			int currentChildViewId = ((int) event.getX() / childWidth + (int) event
					.getY() / childHeight * 3) < count ? ((int) event.getX()
					/ childWidth + (int) event.getY() / childHeight * 3) : -1;
			// 開始按沒按在存在的元素中的時候這個動畫不做
			if (currentChildViewId == -1)
				return;
			downAnimation = AnimationUtils.loadAnimation(context,
					R.anim.backgroundanimdown);
			parent.getChildAt(currentChildViewId).startAnimation(downAnimation);
			tempChildViewId = currentChildViewId;
			downChildViewId = currentChildViewId;
			break;
		}
		// 通過位置判斷是哪個item,做對應的動畫
		case MotionEvent.ACTION_MOVE: {
			// 計算出當前chidView的位於gridView中的位置
			int currentChildViewId = ((int) event.getX() / childWidth + (int) event
					.getY() / childHeight * 3) < count ? ((int) event.getX()
					/ childWidth + (int) event.getY() / childHeight * 3) : -1;
			// 當之前一個元素存在,而移動到不存在元素的區域的時候,需要立即將之前圖片擡起
			//由於這個方法只讓他走一次。設定了一個isLastView的boolean引數
			if (tempChildViewId != -1 && currentChildViewId == -1 && isLastView) {
				Log.d("movemove", "movemove");
				isLastView = false;
				upAnimation = AnimationUtils.loadAnimation(context,
						R.anim.backgroundanimup);
				parent.getChildAt(tempChildViewId).startAnimation(upAnimation);
				return;
			}
			if (currentChildViewId == -1)
				return;
			// 當前元素與之前元素相同,不執行變化操作。
			if (currentChildViewId != tempChildViewId) {
				// 表示從不存在的元素移動到存在的元素的時候。只需要做按下操作即可
				if (tempChildViewId == -1) {
					downAnimation = AnimationUtils.loadAnimation(context,
							R.anim.backgroundanimdown);
					parent.getChildAt(currentChildViewId).startAnimation(
							downAnimation);
				} else {
					// 表示從存在的元素移動到另外一個存在的元素的時候。只需要做按下操作即可
					// 原來的動畫變成彈起。之後的那個執行新的動畫
					upAnimation = AnimationUtils.loadAnimation(context,
							R.anim.backgroundanimup);
					parent.getChildAt(tempChildViewId).startAnimation(
							upAnimation);
					downAnimation = AnimationUtils.loadAnimation(context,
							R.anim.backgroundanimdown);
					parent.getChildAt(currentChildViewId).startAnimation(
							downAnimation);
				}
				// 改變前一個元素的位置。
				tempChildViewId = currentChildViewId;
			}
			break;
		}
		// 擡起,鬆手的時候
		case MotionEvent.ACTION_UP: {
			int currentChildViewId = ((int) event.getX() / childWidth + (int) event
					.getY() / childHeight * 3) < count ? ((int) event.getX()
					/ childWidth + (int) event.getY() / childHeight * 3) : -1;
			Log.d("currentChildViewId", currentChildViewId + "");
			// 按下和擡起都在無效位置的話,do nothing
			if (currentChildViewId == -1)
				return;
			// 其他情況下,需要收起當前的動畫
				upAnimation = AnimationUtils.loadAnimation(context,
						R.anim.backgroundanimup);
				parent.getChildAt(currentChildViewId).startAnimation(
						upAnimation);
				upChildViewId = currentChildViewId;
		}
		default:
			break;
		}

	}
}


設定監聽事件,通過判斷按下和擡起時候的位置是否相同進行跳轉

	typeActivity_gridview.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				AnimationUtil.AnimationAlgorithm(v, event, TypeActivity.this);
				// true攔截事件,不會走onclick,這裡自己寫方法吧
				//判斷按下去和擡起是不是同一個元素,是的話執行跳轉
				if (AnimationUtil.downChildViewId == AnimationUtil.upChildViewId) {
					onclickdata();
				}
				return true;
			});

補充兩個xml

backgroundanimup,xml

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="0.8"
    android:fromYScale="0.8"
    android:toXScale="1"
    android:toYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fillAfter="true"
    android:duration="500"
     />
backgroundanimdown,xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="1"
    android:fromYScale="1"
    android:toXScale="0.8"
    android:toYScale="0.8"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fillAfter="true"
    android:duration="300"
     />