之前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>