亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

android ListView和GridView拖拽移位實現代碼

2020-04-11 12:39:47
字體:
來源:轉載
供稿:網友

關于ListView拖拽移動位置,想必大家并不陌生,比較不錯的軟件都用到如此功能了.如:搜狐,網易,百度等,但是相比來說還是百度的用戶體驗較好,不偏心了,下面看幾個示例:
/      /      /

首先說一下:拖拽ListView的item就不應該可以任意移動,只應該在ListView所在的范圍內,而網易的你看看我都可以移動到狀態欄了,雖然你做了處理,但是用戶體驗我個人感覺不好,在看看百度的,不僅控制了移動范圍,更不錯的百度的移動起來會時時的換位,看起來相當的形象,所以我認為這樣相當的棒.
說明一點,我沒有那么有才,我也是看別人代碼,然后自己整理下.在這里就簡單記載一下.
首先對touch事件的處理,從應用中,我們可以得出,在我們點擊后面拖拉圖標后,就會創建一個item的影像視圖.并且可以移動該影像,而此時的ListView不應該有touch事件.
onInterceptTouchEvent方法.
[java]

復制代碼 代碼如下:

/***
* 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事件:
[java]
復制代碼 代碼如下:

/**
* 觸摸事件處理
*/
@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 , getTop, getBottom,getRight, 這個指的是該控件相對于父控件的距離.
源碼:
[java] 
復制代碼 代碼如下:

package com.jj.drag;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;

import com.jj.drag.MainActivity.DragListAdapter;

/***
* 自定義拖拽ListView
*
* @author zhangjia
*
*/
public class DragListView extends ListView {

private WindowManager windowManager;// windows窗口控制類
private WindowManager.LayoutParams windowParams;// 用于控制拖拽項的顯示的參數

private int scaledTouchSlop;// 判斷滑動的一個距離,scroll的時候會用到(24)

private ImageView dragImageView;// 被拖拽的項(item),其實就是一個ImageView
private int dragSrcPosition;// 手指拖動項原始在列表中的位置
private int dragPosition;// 手指點擊準備拖動的時候,當前拖動項在列表中的位置.

private int dragPoint;// 在當前數據項中的位置
private int dragOffset;// 當前視圖和屏幕的距離(這里只使用了y方向上)

private int upScrollBounce;// 拖動的時候,開始向上滾動的邊界
private int downScrollBounce;// 拖動的時候,開始向下滾動的邊界

private final static int step = 1;// ListView 滑動步伐.

private int current_Step;// 當前步伐.

/***
* 構造方法
*
* @param context
* @param attrs
*/
public DragListView(Context context, AttributeSet attrs) {
super(context, attrs);
}

/***
* 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 super.onInterceptTouchEvent(ev);
}

/**
* 觸摸事件處理
*/
@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);
}

/**
* 準備拖動,初始化拖動項的圖像
*
* @param bm
* @param y
*/
private void startDrag(Bitmap bm, int y) {
// stopDrag();
/***
* 初始化window.
*/
windowParams = new WindowManager.LayoutParams();
windowParams.gravity = Gravity.TOP;
windowParams.x = 0;
windowParams.y = y - dragPoint + dragOffset;
windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE// 不需獲取焦點
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE// 不需接受觸摸事件
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON// 保持設備常開,并保持亮度不變。
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;// 窗口占滿整個屏幕,忽略周圍的裝飾邊框(例如狀態欄)。此窗口需考慮到裝飾邊框的內容。

// windowParams.format = PixelFormat.TRANSLUCENT;// 默認為不透明,這里設成透明效果.
windowParams.windowAnimations = 0;// 窗口所使用的動畫設置

ImageView imageView = new ImageView(getContext());
imageView.setImageBitmap(bm);
windowManager = (WindowManager) getContext().getSystemService("window");
windowManager.addView(imageView, windowParams);
dragImageView = imageView;

}

/**
* 拖動執行,在Move方法中執行
*
* @param y
*/
public void onDrag(int y) {
int drag_top = y - dragPoint;// 拖拽view的top值不能<0,否則則出界.
if (dragImageView != null && drag_top >= 0) {
windowParams.alpha = 0.5f;// 透明度
windowParams.y = y - dragPoint + dragOffset;// 移動y值.//記得要加上dragOffset,windowManager計算的是整個屏幕.(標題欄和狀態欄都要算上)
windowManager.updateViewLayout(dragImageView, windowParams);// 時時移動.
}
// 為了避免滑動到分割線的時候,返回-1的問題
int tempPosition = pointToPosition(0, y);
if (tempPosition != INVALID_POSITION) {
dragPosition = tempPosition;

}
doScroller(y);
}

/***
* ListView的移動.
* 要明白移動原理:當映像移動到下端的時候,ListView向上滑動,當映像移動到上端的時候,ListView要向下滑動。正好和實際的相反.
*
*/

public void doScroller(int y) {
Log.e("jj", "y=" + y);
Log.e("jj", "upScrollBounce=" + upScrollBounce);
// ListView需要下滑
if (y < upScrollBounce) {
current_Step = step + (upScrollBounce - y) / 10;// 時時步伐
}// ListView需要上滑
else if (y > downScrollBounce) {
current_Step = -(step + (y - downScrollBounce)) / 10;// 時時步伐
} else {
current_Step = 0;
}

// 獲取你拖拽滑動到位置及顯示item相應的view上(注:可顯示部分)(position)
View view = getChildAt(dragPosition - getFirstVisiblePosition());
// 真正滾動的方法setSelectionFromTop()
setSelectionFromTop(dragPosition, view.getTop() + current_Step);

}

/**
* 停止拖動,刪除影像
*/
public void stopDrag() {
if (dragImageView != null) {
windowManager.removeView(dragImageView);
dragImageView = null;
}
}

/**
* 拖動放下的時候
*
* @param y
*/
public void onDrop(int y) {

// 為了避免滑動到分割線的時候,返回-1的問題
int tempPosition = pointToPosition(0, y);
if (tempPosition != INVALID_POSITION) {
dragPosition = tempPosition;
}

// 超出邊界處理(如果向上超過第二項Top的話,那么就放置在第一個位置)
if (y < getChildAt(0).getTop()) {
// 超出上邊界
dragPosition = 0;
// 如果拖動超過最后一項的最下邊那么就防止在最下邊
} else if (y > getChildAt(getChildCount() - 1).getBottom()) {
// 超出下邊界
dragPosition = getAdapter().getCount() - 1;
}

// 數據交換
if (dragPosition < getAdapter().getCount()) {
DragListAdapter adapter = (DragListAdapter) getAdapter();
adapter.update(dragSrcPosition, dragPosition);
}

}

}

下面我說下適配器:
[java] 
復制代碼 代碼如下:

/***
* 自定義適配器
*
* @author zhangjia
*
*/
class DragListAdapter extends BaseAdapter {
private ArrayList<String> arrayTitles;
private ArrayList<Integer> arrayDrawables;
private Context context;

public DragListAdapter(Context context, ArrayList<String> arrayTitles,
ArrayList<Integer> arrayDrawables) {
this.context = context;
this.arrayTitles = arrayTitles;
this.arrayDrawables = arrayDrawables;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
/***
* 在這里盡可能每次都進行實例化新的,這樣在拖拽ListView的時候不會出現錯亂.
* 具體原因不明,不過這樣經過測試,目前沒有發現錯亂。雖說效率不高,但是做拖拽LisView足夠了。
*/
view = LayoutInflater.from(context).inflate(
R.layout.drag_list_item, null);

TextView textView = (TextView) view
.findViewById(R.id.tv_drag_list_item_text);
ImageView imageView = (ImageView) view
.findViewById(R.id.iv_drag_list_item_1);
imageView.setImageResource(arrayDrawables.get(position));
textView.setText(arrayTitles.get(position));
return view;
}

/***
* 動態修改ListVIiw的方位.
*
* @param start
* 點擊移動的position
* @param down
* 松開時候的position
*/
public void update(int start, int down) {
// 獲取刪除的東東.
String title = arrayTitles.get(start);
int drawable_id = arrayDrawables.get(start);

arrayTitles.remove(start);// 刪除該項
arrayDrawables.remove(start);// 刪除該項

arrayTitles.add(down, title);// 添加刪除項
arrayDrawables.add(down, drawable_id);// 添加刪除項

notifyDataSetChanged();// 刷新ListView
}

@Override
public int getCount() {

return Title.length;
}

@Override
public Object getItem(int position) {
return Title[position];
}

@Override
public long getItemId(int position) {
return position;
}

}


這里不過多解釋了,相信大家都看的明白.如果疑問請留言.
展示下運行效果:

效果看起來還行吧,如果覺得不錯的話,記得要贊一個哦.

下面我們接著修改,模擬百度嘛,誰讓百度這么牛叉呢.
思路:點中拖拉圖標的時候,每次移動只要dragPosition發生改變,也就是我移動到了下一個位置,那么此時我就進行交換執行update.并且除了第一次移動外,在每次交換后要除去映射源的顯示,這樣用戶覺得這里的空位就是就是為我準備的,比較人性化.
實現起來并不復雜,前提是你得掌握上面的操作.
源碼如下;
[java]

復制代碼 代碼如下:

package com.jj.drag;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;

import com.jj.drag.MainActivity.DragListAdapter;

public class DragListView extends ListView {

private WindowManager windowManager;// windows窗口控制類
private WindowManager.LayoutParams windowParams;// 用于控制拖拽項的顯示的參數

private int scaledTouchSlop;// 判斷滑動的一個距離,scroll的時候會用到(24)

private ImageView dragImageView;// 被拖拽的項(item),其實就是一個ImageView
private int dragSrcPosition;// 手指拖動項原始在列表中的位置
private int dragPosition;// 手指點擊準備拖動的時候,當前拖動項在列表中的位置.

private int dragPoint;// 在當前數據項中的位置
private int dragOffset;// 當前視圖和屏幕的距離(這里只使用了y方向上)

private int upScrollBounce;// 拖動的時候,開始向上滾動的邊界
private int downScrollBounce;// 拖動的時候,開始向下滾動的邊界

private final static int step = 1;// ListView 滑動步伐.

private int current_Step;// 當前步伐.

private int temChangId;// 臨時交換id

private boolean isLock;// 是否上鎖.

public void setLock(boolean isLock) {
this.isLock = isLock;
}

public DragListView(Context context, AttributeSet attrs) {
super(context, attrs);
scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

/***
* touch事件攔截 在這里我進行相應攔截,
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// 按下
if (ev.getAction() == MotionEvent.ACTION_DOWN && !isLock) {
int x = (int) ev.getX();// 獲取相對與ListView的x坐標
int y = (int) ev.getY();// 獲取相應與ListView的y坐標
temChangId = 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.setBackgroundColor(Color.BLUE);
itemView.setDrawingCacheEnabled(true);// 開啟cache.
Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());// 根據cache創建一個新的bitmap對象.
startDrag(bm, y);// 初始化影像
}
return false;
}

return super.onInterceptTouchEvent(ev);
}

/**
* 觸摸事件處理
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
// item的view不為空,且獲取的dragPosition有效
if (dragImageView != null && dragPosition != INVALID_POSITION
&& !isLock) {
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);
}

/**
* 準備拖動,初始化拖動項的圖像
*
* @param bm
* @param y
*/
private void startDrag(Bitmap bm, int y) {
// stopDrag();
/***
* 初始化window.
*/
windowParams = new WindowManager.LayoutParams();
windowParams.gravity = Gravity.TOP;
windowParams.x = 0;
windowParams.y = y - dragPoint + dragOffset;
windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE// 不需獲取焦點
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE// 不需接受觸摸事件
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON// 保持設備常開,并保持亮度不變。
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;// 窗口占滿整個屏幕,忽略周圍的裝飾邊框(例如狀態欄)。此窗口需考慮到裝飾邊框的內容。

// windowParams.format = PixelFormat.TRANSLUCENT;// 默認為不透明,這里設成透明效果.
windowParams.windowAnimations = 0;// 窗口所使用的動畫設置

ImageView imageView = new ImageView(getContext());
imageView.setImageBitmap(bm);
windowManager = (WindowManager) getContext().getSystemService("window");
windowManager.addView(imageView, windowParams);
dragImageView = imageView;

}

/**
* 拖動執行,在Move方法中執行
*
* @param y
*/
public void onDrag(int y) {
int drag_top = y - dragPoint;// 拖拽view的top值不能<0,否則則出界.
if (dragImageView != null && drag_top >= 0) {
windowParams.alpha = 0.5f;
windowParams.y = y - dragPoint + dragOffset;
windowManager.updateViewLayout(dragImageView, windowParams);// 時時移動.
}
// 為了避免滑動到分割線的時候,返回-1的問題
int tempPosition = pointToPosition(0, y);
if (tempPosition != INVALID_POSITION) {
dragPosition = tempPosition;
}

onChange(y);// 時時交換

doScroller(y);// listview移動.
}

/***
* ListView的移動.
* 要明白移動原理:當我移動到下端的時候,ListView向上滑動,當我移動到上端的時候,ListView要向下滑動。正好和實際的相反.
*
*/

public void doScroller(int y) {
// Log.e("jj", "y=" + y);
// Log.e("jj", "upScrollBounce=" + upScrollBounce);
// ListView需要下滑
if (y < upScrollBounce) {
current_Step = step + (upScrollBounce - y) / 10;// 時時步伐
}// ListView需要上滑
else if (y > downScrollBounce) {
current_Step = -(step + (y - downScrollBounce)) / 10;// 時時步伐
} else {
current_Step = 0;
}

// 獲取你拖拽滑動到位置及顯示item相應的view上(注:可顯示部分)(position)
View view = getChildAt(dragPosition - getFirstVisiblePosition());
// 真正滾動的方法setSelectionFromTop()
setSelectionFromTop(dragPosition, view.getTop() + current_Step);

}

/**
* 停止拖動,刪除影像
*/
public void stopDrag() {
if (dragImageView != null) {
windowManager.removeView(dragImageView);
dragImageView = null;
}
}

/***
* 拖動時時change
*/
private void onChange(int y) {
// 數據交換
if (dragPosition < getAdapter().getCount()) {
DragListAdapter adapter = (DragListAdapter) getAdapter();
adapter.isHidden = false;
if (dragPosition != temChangId) {
adapter.update(temChangId, dragPosition);
temChangId = dragPosition;// 將點擊最初所在位置position付給臨時的,用于判斷是否換位.
}
}

// 為了避免滑動到分割線的時候,返回-1的問題
int tempPosition = pointToPosition(0, y);
if (tempPosition != INVALID_POSITION) {
dragPosition = tempPosition;
}

// 超出邊界處理(如果向上超過第二項Top的話,那么就放置在第一個位置)
if (y < getChildAt(0).getTop()) {
// 超出上邊界
dragPosition = 0;
// 如果拖動超過最后一項的最下邊那么就防止在最下邊
} else if (y > getChildAt(getChildCount() - 1).getBottom()) {
// 超出下邊界
dragPosition = getAdapter().getCount() - 1;
}

}

/**
* 拖動放下的時候
*
* @param y
*/
public void onDrop(int y) {
// 數據交換
if (dragPosition < getAdapter().getCount()) {
DragListAdapter adapter = (DragListAdapter) getAdapter();
adapter.isHidden = false;
adapter.notifyDataSetChanged();// 刷新.
}
}

}

因為我們要時時交換位置,所以將原先的拖動方法onDrop方法移動到onChange中.具體的還是看源碼吧.
另外的就是對適配器的修改,因為你要對特殊的item進行隱藏之類的操作,這些代碼我就不寫了,我會將案例上傳網上,不懂的可以下載源碼.
好了還是我們來觀看下效果吧.

怎么樣,這個效果看起來要比上面那個效果更人性化點吧,我的操作或許有點快,不信的話,你自己手機體驗一下吧.
關于ListView拖拽就說到這里,如有不足請大家自己創新.

下面我們接著對GridView的拖拽簡單說明.因為這些在項目中我們都會用到,所以既然做到就做全面點吧.好了大家接著往下看吧.
首先說明,原理一樣,都是拖動映像,記錄拖動位置,然后調用notifyDataSetChanged更新UI.
而GridView不同的是你要根據x,y值共同獲取點擊的position和移動至的position,而ListView因為不涉及x坐標.
嗯,最初的原始移動我就不給大家展示了,效果也不是很友好,我直接展示時時更新的那種方法.效果類是與上面那個時時更新ListView一樣。
原理也一樣.下面我們直接看代碼吧.
[java]

復制代碼 代碼如下:

package com.jj.draggrid;

import java.util.logging.Handler;

import com.jj.draggrid.MainActivity.DragGridAdapter;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

/***
* 自定義拖拽GridView
*
* @author zhangjia
*
*/

public class DragGridView extends GridView {

private WindowManager windowManager;// windows窗口控制類
private WindowManager.LayoutParams windowParams;// 用于控制拖拽項的顯示的參數

private int scaledTouchSlop;// 判斷滑動的一個距離,scroll的時候會用到(24)

private ImageView dragImageView;// 被拖拽的項(item),其實就是一個ImageView
private int dragSrcPosition;// 手指拖動項原始在列表中的位置
private int dragPosition;// 手指點擊準備拖動的時候,當前拖動項在列表中的位置.

private int dragPointX;// 在當前數據項中的位置
private int dragPointY;// 在當前數據項中的位置
private int dragOffsetX;// 當前視圖和屏幕的距離(這里只使用了x方向上)
private int dragOffsetY;// 當前視圖和屏幕的距離(這里只使用了y方向上)

private int upScrollBounce;// 拖動的時候,開始向上滾動的邊界
private int downScrollBounce;// 拖動的時候,開始向下滾動的邊界

private int temChangId;// 臨時交換id

private boolean isDoTouch = false;// touch是否可用

private boolean isHide = false;// 是否隱藏

private Handler handler;

public void setDoTouch(boolean isDoTouch) {
this.isDoTouch = isDoTouch;
}

public DragGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

if (ev.getAction() == MotionEvent.ACTION_DOWN) {
int x = (int) ev.getX();
int y = (int) ev.getY();

temChangId = dragSrcPosition = dragPosition = pointToPosition(x, y);

if (dragPosition == AdapterView.INVALID_POSITION) {
return super.onInterceptTouchEvent(ev);
}

ViewGroup itemView = (ViewGroup) getChildAt(dragPosition
- getFirstVisiblePosition());

dragPointX = x - itemView.getLeft();
dragPointY = y - itemView.getTop();
dragOffsetX = (int) (ev.getRawX() - x);
dragOffsetY = (int) (ev.getRawY() - y);

View dragger = itemView.findViewById(R.id.drag_grid_item);

/***
* 判斷是否選中拖動圖標
*/
if (dragger != null && dragPointX > dragger.getLeft()
&& dragPointX < dragger.getRight()
&& dragPointY > dragger.getTop()
&& dragPointY < dragger.getBottom() + 20) {

upScrollBounce = getHeight() / 4;
downScrollBounce = getHeight() * 3 / 4;

itemView.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());
startDrag(bm, x, y);// 初始話映像

dragger.setVisibility(View.INVISIBLE);// 隱藏該項.
}
}

return super.onInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {

if (dragImageView != null && dragPosition != INVALID_POSITION
&& isDoTouch) {
int action = ev.getAction();
switch (action) {
/***
*
*/
case MotionEvent.ACTION_UP:
int upX = (int) ev.getX();
int upY = (int) ev.getY();
stopDrag();// 刪除映像
onDrop(upX, upY);// 松開
// isDoTouch = false;
break;
/***
* 拖拽item
*
*/
case MotionEvent.ACTION_MOVE:
int moveX = (int) ev.getX();
int moveY = (int) ev.getY();
onDrag(moveX, moveY);// 拖拽
break;
case MotionEvent.ACTION_DOWN:
int downX = (int) ev.getX();
int downY = (int) ev.getY();
onHide(downX, downY);// 隱藏該項
break;
default:
break;
}
return true;
}

return super.onTouchEvent(ev);
}

/**
* 準備拖動,初始化拖動項的圖像
*
* @param bm
* @param y
*/
public void startDrag(Bitmap bm, int x, int y) {

windowParams = new WindowManager.LayoutParams();
windowParams.gravity = Gravity.TOP | Gravity.LEFT;
windowParams.x = x - dragPointX + dragOffsetX;
windowParams.y = y - dragPointY + dragOffsetY;
windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

windowParams.windowAnimations = 0;

ImageView imageView = new ImageView(getContext());
imageView.setImageBitmap(bm);
windowManager = (WindowManager) getContext().getSystemService("window");
windowManager.addView(imageView, windowParams);
dragImageView = imageView;

}

/***
* 拖動時時change
*/
private void onChange(int x, int y) {
// 獲取適配器
DragGridAdapter adapter = (DragGridAdapter) getAdapter();
// 數據交換
if (dragPosition < getAdapter().getCount()) {
// 不相等的情況下要進行換位,相等的情況下說明正在移動
if (dragPosition != temChangId) {
adapter.update(temChangId, dragPosition);// 進行換位
temChangId = dragPosition;// 將點擊最初所在位置position付給臨時的,用于判斷是否換位.
}

}

// 為了避免滑動到分割線的時候,返回-1的問題
int tempPosition = pointToPosition(x, y);
if (tempPosition != INVALID_POSITION) {
dragPosition = tempPosition;
}

}

/***
* 拖動執行,在Move方法中執行
*
* @param x
* @param y
*/
public void onDrag(int x, int y) {
// 移動
if (dragImageView != null) {
windowParams.alpha = 0.8f;
windowParams.x = x - dragPointX + dragOffsetX;
windowParams.y = y - dragPointY + dragOffsetY;
windowManager.updateViewLayout(dragImageView, windowParams);
}

onChange(x, y);// 時時交換

// 滾動
if (y < upScrollBounce || y > downScrollBounce) {
// 使用setSelection來實現滾動
setSelection(dragPosition);
}

}

/***
* 隱藏該選項
*/
private void onHide(int x, int y) {
// 獲取適配器
DragGridAdapter adapter = (DragGridAdapter) getAdapter();
// 為了避免滑動到分割線的時候,返回-1的問題
int tempPosition = pointToPosition(x, y);
if (tempPosition != INVALID_POSITION) {
dragPosition = tempPosition;
}
adapter.setIsHidePosition(dragPosition);

}

/**
* 停止拖動,刪除影像
*/
public void stopDrag() {
if (dragImageView != null) {
windowManager.removeView(dragImageView);
dragImageView = null;
}
}

/***
* 拖動放下的時候
*
* @param x
* @param y
*/
public void onDrop(int x, int y) {

DragGridAdapter adapter = (DragGridAdapter) getAdapter();
adapter.setIsHidePosition(-1);// 不進行隱藏

}

}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
26uuu另类亚洲欧美日本一| 中文字幕视频一区二区在线有码| 国产精品日韩欧美| 成人在线激情视频| 91av在线免费观看视频| 亚洲最大中文字幕| 亚洲女成人图区| 欧美黄色片在线观看| 国产精品极品美女粉嫩高清在线| 欧美电影在线免费观看网站| 色婷婷av一区二区三区在线观看| 中文字幕日韩在线视频| 国产精品久久久久999| 久久6免费高清热精品| 2019中文字幕免费视频| 亚洲精品日韩丝袜精品| 久久久免费观看视频| 国产精品com| 国产精品嫩草视频| 国产精品一二三视频| 久久久久免费视频| 亚洲国产一区二区三区在线观看| 91九色蝌蚪国产| 久久久亚洲精选| 91视频国产一区| 亚洲国产美女久久久久| 亚洲三级免费看| 亚洲偷熟乱区亚洲香蕉av| 正在播放欧美一区| 最近中文字幕mv在线一区二区三区四区| 国产亚洲视频中文字幕视频| 亚洲最大成人在线| 91热福利电影| 欧美性猛交视频| 久久久久久97| 日韩免费看的电影电视剧大全| 中文字幕一区二区精品| 亚洲日本成人网| 中文字幕一区日韩电影| 亚洲乱码一区二区| 亚洲永久在线观看| 亚洲欧美精品suv| 91社区国产高清| 国产精品久久久久久久久粉嫩av| 国产精品久久97| 日韩在线免费观看视频| 91精品国产免费久久久久久| 久久这里只有精品视频首页| 91国语精品自产拍在线观看性色| 亚洲无限av看| 日韩精品久久久久久久玫瑰园| 亚洲一区二区三区久久| 亚洲色图日韩av| 韩国三级日本三级少妇99| 亚洲第五色综合网| 国产精品自产拍在线观看中文| 久久99精品久久久久久噜噜| 中文字幕日韩欧美| 亚洲va男人天堂| 欧亚精品在线观看| 亚洲自拍偷拍网址| 色悠悠久久久久| 日韩免费av片在线观看| 国产视频精品自拍| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲天堂av在线免费| 国产偷亚洲偷欧美偷精品| 18性欧美xxxⅹ性满足| 日韩av黄色在线观看| 欧美丝袜一区二区三区| 久久在线免费观看视频| 日韩精品视频免费专区在线播放| 精品一区二区三区三区| 久久久噜噜噜久久中文字免| 91精品国产自产在线| 亚洲人成在线一二| 日本一区二三区好的精华液| 久久影视电视剧凤归四时歌| 久久免费国产视频| 在线观看成人黄色| 97色在线视频观看| 一区二区成人精品| 国产va免费精品高清在线| 国自产精品手机在线观看视频| 有码中文亚洲精品| 国产福利视频一区二区| 欧美电影在线观看完整版| 中文字幕日韩专区| 国产精品丝袜一区二区三区| 成人写真视频福利网| 精品久久香蕉国产线看观看gif| 国产精品精品一区二区三区午夜版| 欧美最猛黑人xxxx黑人猛叫黄| 欧美日韩国产色视频| 韩曰欧美视频免费观看| 国产美女久久久| 国产精品久久久久久久久免费| 国产精品99久久久久久白浆小说| 亚洲成色777777在线观看影院| 国产mv免费观看入口亚洲| 91精品综合久久久久久五月天| 91精品国产九九九久久久亚洲| 欧美影院久久久| 亚洲午夜性刺激影院| 日韩av免费看网站| 欧洲日韩成人av| 亚洲天堂影视av| 最新69国产成人精品视频免费| 97在线精品国自产拍中文| 亚洲第一黄色网| 成人有码视频在线播放| 国产精品视频xxxx| 成人精品aaaa网站| 国产伦精品免费视频| 欧美成人精品在线播放| 一区二区三区视频观看| 国产精品国产三级国产aⅴ9色| 欧美有码在线观看| 久久久精品在线观看| 日本久久亚洲电影| 日韩有码在线观看| 日韩av在线看| 精品久久香蕉国产线看观看gif| 欧美一级视频免费在线观看| 久久97精品久久久久久久不卡| 中文字幕欧美在线| 日韩视频免费大全中文字幕| 亚洲精品国产精品国自产观看浪潮| 久久影院在线观看| 欧美精品在线视频观看| 亚洲人永久免费| 国产成人精品一区二区| 亚洲欧美激情四射在线日| 久久久久久久av| www.色综合| 欧美日韩第一页| 国产精品视频专区| 亚洲自拍偷拍区| 欧美激情一二区| 成人观看高清在线观看免费| 亚洲成人aaa| 成人伊人精品色xxxx视频| 国产欧美日韩综合精品| 91国内揄拍国内精品对白| 欧美在线激情网| 亚洲人免费视频| 亚洲视频在线观看免费| 亚洲精品按摩视频| 国产精品欧美风情| 日日摸夜夜添一区| 精品激情国产视频| 欧美日本中文字幕| 欧洲午夜精品久久久| 久久不射热爱视频精品| 欧美大成色www永久网站婷| 久久大大胆人体| 青草青草久热精品视频在线观看| 色伦专区97中文字幕| 久久影视电视剧免费网站清宫辞电视| 中文字幕精品影院| 久久成人精品视频| 亚洲欧美日韩区| 亚洲男人的天堂网站| 亚洲激情视频网|