android ListView和GridView拖拽移位具体实现及拓展

关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:

               

首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.

说明一点,我没有那么有才,我也是看别人代码,然后自己整理下.在这里就简单记载一下.

首先对touch事件的处理,从应用中,我们可以得出,在我们点击后面拖拉图标后,就会创建一个item的影像视图.并且可以移动该影像,而此时的ListView不应该有touch事件.

onInterceptTouchEvent方法.

/***
	 * touch事件拦截 
	 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// 按下
		if (ev.getAction() == MotionEvent.ACTION_DOWN) {
			int x = (int) ev.getX();// 获取相对与ListView的x坐标
			int y = (int) ev.getY();// 获取相应与ListView的y坐标
			dragSrcPosition = dragPosition = pointToPosition(x, y);
			// 无效不进行处理
			if (dragPosition == AdapterView.INVALID_POSITION) {
				return super.onInterceptTouchEvent(ev);
			}

			// 获取当前位置的视图(可见状态)
			ViewGroup itemView = (ViewGroup) getChildAt(dragPosition
					- getFirstVisiblePosition());

			// 获取到的dragPoint其实就是在你点击指定item项中的高度.
			dragPoint = y - itemView.getTop();
			// 这个值是固定的:其实就是ListView这个控件与屏幕最顶部的距离(一般为标题栏+状态栏).
			dragOffset = (int) (ev.getRawY() - y);

			// 获取可拖拽的图标
			View dragger = itemView.findViewById(R.id.iv_drag_list_item_2);

			// x > dragger.getLeft() - 20这句话为了更好的触摸(-20可以省略)
			if (dragger != null && x > dragger.getLeft() - 20) {

				upScrollBounce = getHeight() / 3;// 取得向上滚动的边际,大概为该控件的1/3
				downScrollBounce = getHeight() * 2 / 3;// 取得向下滚动的边际,大概为该控件的2/3

				itemView.setDrawingCacheEnabled(true);// 开启cache.
				Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());// 根据cache创建一个新的bitmap对象.
				startDrag(bm, y);// 初始化影像
			}
			// return false;
		}

		return super.onInterceptTouchEvent(ev);
	}

这个方法的作用很简单:当我们摁下的如果是可拖拽的图标,那么进行初始化该Item的映像试图.

而在这里如果大家对WindowManager和WindowManager.LayoutParams不熟悉的朋友先去参考下这篇文章,要对WindowManager有一定的了解,简单的会应用.

接下来我们看onTouchEvent事件:

/**
	 * 触摸事件处理
	 */
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		// item的view不为空,且获取的dragPosition有效
		if (dragImageView != null && dragPosition != INVALID_POSITION) {
			int action = ev.getAction();
			switch (action) {
			case MotionEvent.ACTION_UP:
				int upY = (int) ev.getY();
				stopDrag();
				onDrop(upY);
				break;
			case MotionEvent.ACTION_MOVE:
				int moveY = (int) ev.getY();
				onDrag(moveY);

				break;
			case MotionEvent.ACTION_DOWN:
				break;
			default:
				break;
			}
			return true;// 取消ListView滑动.
		}

		return super.onTouchEvent(ev);
	}
简单说明: 首先在Touch中,我们要进行判断,是否点击的是拖动图标,如果是的话,那么对ACTION_MOVE and ACTION_UP相应事件进行处理,并且返回true or false.作用:取消ListView自身的Touch事件.如果不是的话,执行ListView 本身的Touch事件.

大致就介绍这么多,具体的实现,还是大家看源码吧,我注释的还算清晰,只要大家仔细看的话,一定可以掌握的,为什么这么说呢,技术只有在掌握了情况下才可以进行拓展.

对了,提醒大家要理解这三句话:

getRawX()和getRawY():获得的是相对屏幕的位置.
getX()和getY():获得的永远是相对view的触摸位置 坐标这两个值不会超过view的长度和宽度)。
getLeft getTopgetBottom,
  • 51
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 101
    评论
Android 中,我们经常使用 ListView 来展示一些数据。当我们滑动 ListView 时,如果需要记录当前滚动的位置,并在下次打开时恢复到上次滚动的位置,该怎么做呢?下面是一种完美的实现方法。 首先,在 Activity 中定义一个变量来记录当前滚动的位置: ```java private int mLastFirstVisibleItem = 0; ``` 然后,在 ListView 的监听器中获取当前的滚动位置: ```java listView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (view.getId() == listView.getId()) { final int currentFirstVisibleItem = listView.getFirstVisiblePosition(); if (currentFirstVisibleItem > mLastFirstVisibleItem) { // 向上滚动 } else if (currentFirstVisibleItem < mLastFirstVisibleItem) { // 向下滚动 } mLastFirstVisibleItem = currentFirstVisibleItem; } } }); ``` 接下来,在 Activity 的 onResume() 方法中获取上次滚动的位置并恢复: ```java @Override protected void onResume() { super.onResume(); // 恢复滚动位置 if (mLastFirstVisibleItem != 0) { listView.setSelectionFromTop(mLastFirstVisibleItem, 0); } } ``` 最后,在 Activity 的 onPause() 方法中保存当前滚动的位置: ```java @Override protected void onPause() { super.onPause(); // 保存滚动位置 mLastFirstVisibleItem = listView.getFirstVisiblePosition(); } ``` 至此,ListView 滚动位置的记录和恢复就完成了。这种方法适用于一般的 ListView,如果你使用了自定义的 Adapter 或者 ViewHolder,需要根据实际情况做出相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 101
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值