Android中GridView中onTouch监听(2)自己写的Scroll滑动判断

这篇博客讲述了在Android的GridView中遇到的OnTouch事件拦截问题,导致无法下拉滑动。通过分析并使用getScrollY()和setScrollY(int y),作者提供了解决方案,使得在元素过多需要滑动时可以正常操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前Android中GridView中onTouch监听(1)每个item进行点击缩放动画的制作以及点击事件的监听的文章中

由于OnTouch返回值为true,导致当元素过多时(即需要下滑的时候),下滑是操作不了的,事件被拦截了

这里就需要自己的判断,主要涉及到的是GridView中的getScrollY(),setScrollY(int y),这里需要修改之前的代码。

==============================================================================

代码修改为

package com.example.util;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.util.DisplayMetrics;
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 com.example.passwordhousekeeper.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;

<span style="color:#ff0000;">	// preY按下时候的y坐标
	private static float preY;
	private static int phoneHeightPixels;</span>

	/**
	 * 点击每个gridView元素将执行动画
	 * 
	 * @param v
	 * @param event
	 * 
	 */
	@SuppressLint("NewApi")
	public static void AnimationAlgorithm(View v, MotionEvent event,
			Activity 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;
	<span style="color:#ff0000;">		// 如果元素超过屏幕大小,还要进行滑动操作,按下的时候获得Y轴最大值
			DisplayMetrics dm = new DisplayMetrics();
			context.getWindowManager().getDefaultDisplay().getMetrics(dm);
			// 获得手机的宽度和高度像素单位为px
			phoneHeightPixels = dm.heightPixels;
			preY = event.getY();</span>

			// 三目运算符
			int currentChildViewId = ((int) event.getX() / childWidth + ((int) event
					.getY() + parent.getScrollY()) / childHeight * 3) < count ? ((int) event
					.getX() / childWidth + ((int) event.getY() + parent
					.getScrollY()) / 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中的位置,加入<span style="font-family: Arial, Helvetica, sans-serif;">getScrollY() 来元素的位置 </span>
<span style="color:#ff0000;">			int currentChildViewId = ((int) event.getX() / childWidth + ((int) event
					.getY() + parent.getScrollY()) / childHeight * 3) < count ? ((int) event
					.getX() / childWidth + ((int) event.getY() + parent
					.getScrollY()) / childHeight * 3)
					: -1;</span>
			// 当之前一个元素存在,而移动到不存在元素的区域的时候,需要立即将之前图片抬起
			// 由于这个方法只让他走一次。设置了一个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;
			}
			// 需要进行滑动判断
			<span style="color:#ff0000;">if (parent.getChildAt(0).getHeight() * ((count - 1) / 3 + 1) + 184 > phoneHeightPixels) {
				// 说明需要加入滑动事件
				// 此时用户向上滑动,需要下滑
				Log.d("parent.getScrollY()", parent.getScrollY() + "");
				if (preY > event.getY()) {
					if (parent.getScrollY() < (parent.getChildAt(0).getHeight()
							* ((count - 1) / 3 + 1) + 184 - phoneHeightPixels))
						parent.setScrollY((int) (preY - event.getY())
								+ parent.getScrollY());

				} else if (preY < event.getY() && parent.getScrollY() > 0) {
					// 向下滑动 当为负数的时候就设置为0
					int y = parent.getScrollY() - (int) (event.getY() - preY) >= 0 ? parent
							.getScrollY() - (int) (event.getY() - preY)
							: 0;
					parent.setScrollY(y);
				}
				preY = event.getY();
				// 元素被删除了,但是parent.getScrollY()>0的时候,用户往下滑,应该ScrollY=0才行
			} else if (preY < event.getY() && parent.getScrollY() >= 0) {
				// 向下滑动
				int y = parent.getScrollY() - (int) (event.getY() - preY) >= 0 ? parent
						.getScrollY() - (int) (event.getY() - preY)
						: 0;
				parent.setScrollY(y);
				preY = event.getY();
			}</span>
			break;
		}
		// 抬起,松手的时候
		case MotionEvent.ACTION_UP: {
			int currentChildViewId = ((int) event.getX() / childWidth + ((int) event
					.getY() + parent.getScrollY()) / childHeight * 3) < count ? ((int) event
					.getX() / childWidth + ((int) event.getY() + parent
					.getScrollY()) / 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;
		}

	}
}

1.preY表示的是 用户ACTION_DOWN时候的位置,用来判断 是往上还是往下的滑动 

2.获得系统手机的分辨率 

	<span style="color:#ff0000;">		// 如果元素超过屏幕大小,还要进行滑动操作,按下的时候获得Y轴最大值
			DisplayMetrics dm = new DisplayMetrics();
			context.getWindowManager().getDefaultDisplay().getMetrics(dm);
			// 获得手机的宽度和高度像素单位为px
			phoneHeightPixels = dm.heightPixels;
			preY = event.getY();</span>
3.在 ACTION_MOVE的时候进行滑动的判断 

由于有了滑动的距离,元素的位置变了

<span style="color:#ff0000;">			int currentChildViewId = ((int) event.getX() / childWidth + ((int) event
					.getY() + parent.getScrollY()) / childHeight * 3) < count ? ((int) event
					.getX() / childWidth + ((int) event.getY() + parent
					.getScrollY()) / childHeight * 3)
					: -1;</span>
在滑动判断的时候,如果需要滑动的距离小于(最大元素所在y轴-手机Y轴的分辨率)

继续实现滑动。

<span style="color:#ff0000;">					if (parent.getScrollY() < (parent.getChildAt(0).getHeight()
							* ((count - 1) / 3 + 1) + 184 - phoneHeightPixels))
						parent.setScrollY((int) (preY - event.getY())
								+ parent.getScrollY());</span>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值