仿网易新闻客户端栏目的拖拽,删除,添加效果。在此要感谢vipra,此效果是在这个项目的基础上修改的
先上效果图:
简单说一下实现原理:
首先看一下效果图,分为上下两个GridView,上边的为可以拖拽的GridView,为DragGrid。下边是不可拖拽的普通的GridView。
主要说一下DragGrid(可以拖拽的GridView):重写onInterceptTouchEvent方法,然后设置Item的长按事件,拿到当前的item信息(postion,item的view),并在window层创建item的view的布局,在onTouchEvent方法,处理move事件获取到移动,计算item之间的移动和创建动画。
处理长按事件:
setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView parent, View view,
int position, long id) {
int x = (int) ev.getX();// 长按事件的X位置
int y = (int) ev.getY();// 长按事件的y位置
startPosition = position;// 第一次点击的postion
dragPosition = position;
if (startPosition <= 0) {//TODO 原来是1
return false;
}
View dragViewGroup = getChildAt(dragPosition - getFirstVisiblePosition());
TextView dragTextView = (TextView) dragViewGroup.findViewById(R.id.text_item);
RelativeLayout ri_delete = (RelativeLayout) dragViewGroup.findViewById(R.id.ri_delete);
dragTextView.setSelected(true);
dragTextView.setEnabled(false);
ri_delete.setVisibility(View.INVISIBLE);
itemHeight = dragViewGroup.getHeight();
itemWidth = dragViewGroup.getWidth();
itemTotalCount = DragGrid.this.getCount();
int row = itemTotalCount / nColumns;// 算出行数
Remainder = (itemTotalCount % nColumns);// 算出最后一行多余的数量
if (Remainder != 0) {
nRows = row + 1;
} else {
nRows = row;
}
// 如果特殊的这个不等于拖动的那个,并且不等于-1
if (dragPosition != AdapterView.INVALID_POSITION) {
// 释放的资源使用的绘图缓存。如果你调用buildDrawingCache()手动没有调用setDrawingCacheEnabled(真正的),你应该清理缓存使用这种方法。
win_view_x = windowX - dragViewGroup.getLeft();//VIEW相对自己的X,半斤
win_view_y = windowY - dragViewGroup.getTop();//VIEW相对自己的y,半斤
dragOffsetX = (int) (ev.getRawX() - x);//手指在屏幕的上X位置-手指在控件中的位置就是距离最左边的距离
dragOffsetY = (int) (ev.getRawY() - y);//手指在屏幕的上y位置-手指在控件中的位置就是距离最上边的距离
// dragItemView = dragViewGroup;
dragViewGroup.destroyDrawingCache();
if (ri_delete.getVisibility() == View.GONE) {
ri_delete.setVisibility(View.VISIBLE);
}
dragViewGroup.setDrawingCacheEnabled(true);
//TODO 展示删除按钮
showInnerDeleteIcon();
showDeleteIcon(true);
Bitmap dragBitmap = Bitmap.createBitmap(dragViewGroup.getDrawingCache());
//mVibrator.vibrate(50);//设置震动时间
startDrag(dragBitmap, (int) ev.getRawX(), (int) ev.getRawY());
//隐藏需要移动的item
hideDropItem();
dragViewGroup.setVisibility(View.INVISIBLE);
isMoving = false;
requestDisallowInterceptTouchEvent(true);
return true;
}
return false;
}
});
处理移动:
// 拖动的VIEW下方的POSTION
int dPosition = pointToPosition(x, y);
// 判断下方的POSTION是否是最开始2个不能拖动的
if (dPosition > 0) {//TODO 原来值是1
if ((dPosition == -1) || (dPosition == dragPosition)) {
return;
}
dropPosition = dPosition;
if (dragPosition != startPosition) {
dragPosition = startPosition;
}
int movecount;
//拖动的=开始拖的,并且 拖动的 不等于放下的
if ((dragPosition == startPosition) || (dragPosition != dropPosition)) {
//移需要移动的动ITEM数量
movecount = dropPosition - dragPosition;
} else {
//移需要移动的动ITEM数量为0
movecount = 0;
}
if (movecount == 0) {
return;
}
int movecount_abs = Math.abs(movecount);
if (dPosition != dragPosition) {
//dragGroup设置为不可见
ViewGroup dragGroup = (ViewGroup) getChildAt(dragPosition);
dragGroup.setVisibility(View.INVISIBLE);
float to_x = 1;// 当前下方positon
float to_y;// 当前下方右边positon
//x_vlaue移动的距离百分比(相对于自己长度的百分比)
float x_vlaue = ((float) mHorizontalSpacing / (float) itemWidth) + 1.0f;
//y_vlaue移动的距离百分比(相对于自己宽度的百分比)
float y_vlaue = ((float) mVerticalSpacing / (float) itemHeight) + 1.0f;
Log.d("x_vlaue", "x_vlaue = " + x_vlaue);
for (int i = 0; i < movecount_abs; i++) {
to_x = x_vlaue;
to_y = y_vlaue;
//像左
if (movecount > 0) {
// 判断是不是同一行的
holdPosition = dragPosition + i + 1;
if (dragPosition / nColumns == holdPosition / nColumns) {
to_x = -x_vlaue;
to_y = 0;
} else if (holdPosition % 4 == 0) {
to_x = 3 * x_vlaue;
to_y = -y_vlaue;
System.out.println("=============to_y ="+to_y);
} else {
to_x = -x_vlaue;
to_y = 0;
}
} else {
//向右,下移到上,右移到左
holdPosition = dragPosition - i - 1;
if (dragPosition / nColumns == holdPosition / nColumns) {
to_x = x_vlaue;
to_y = 0;
} else if ((holdPosition + 1) % 4 == 0) {
to_x = -3 * x_vlaue;
to_y = y_vlaue;
} else {
to_x = x_vlaue;
to_y = 0;
}
}
ViewGroup moveViewGroup = (ViewGroup) getChildAt(holdPosition);
Animation moveAnimation = getMoveAnimation(to_x, to_y);
moveViewGroup.startAnimation(moveAnimation);
//如果是最后一个移动的,那么设置他的最后个动画ID为LastAnimationID
if (holdPosition == dropPosition) {
LastAnimationID = moveAnimation.toString();
}
moveAnimation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
isMoving = true;
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
// 如果为最后个动画结束,那执行下面的方法
if (animation.toString().equalsIgnoreCase(LastAnimationID)) {
DragAdapter mDragAdapter = (DragAdapter) getAdapter();
mDragAdapter.exchange(startPosition, dropPosition);
startPosition = dropPosition;
dragPosition = dropPosition;
isMoving = false;
}
}
});
}
}
}
如此,当点击下边的GridView,获取到当前item的位置,然后获取到上传size+1的位置,创建window层view,设置动画。
具体代码可以去我的github自己去看。