http://www.cnblogs.com/qianxudetianxia/archive/2011/06/20/2084886.html
根据前面文章中ListView拖拽的实现原理,我们也是很容易实现推拽GridView的,下面我就以相同步骤实现基本的GridView拖拽效果。
因为GridView不用做分组处理,代码处理起来更简洁,而且原理前面已经讲解清楚了,代码中只是简单的过下,必要的地方简单的注释一下。
1.主界面DragGridActivity.
01 | public class DragGridActivity extends Activity { |
03 | private static List<String> list = null ; |
05 | private DragGridAdapter adapter = null ; |
08 | public void onCreate(Bundle savedInstanceState) { |
09 | super .onCreate(savedInstanceState); |
10 | setContentView(R.layout.drag_grid_activity); |
15 | DragGridView dragGridView = (DragGridView)findViewById(R.id.drag_grid); |
16 | adapter = new DragGridAdapter( this , list); |
17 | dragGridView.setAdapter(adapter); |
20 | public void initData(){ |
22 | list = new ArrayList<String>(); |
24 | for ( int i= 0 ; i< 12 ; i++){ |
25 | list.add( "grid_" +i% 12 ); |
2.主界面UI布局drag_grid_activity.xml.
01 | <?xml version= "1.0" encoding= "utf-8" ?> |
03 | android:orientation= "vertical" |
04 | android:layout_width= "fill_parent" |
05 | android:layout_height= "fill_parent" |
06 | android:background= "#ffffff" |
07 | android:padding= "10dip" |
09 | <com.fengjian.test.DragGridView |
10 | android:id= "@+id/drag_grid" |
11 | android:layout_width= "fill_parent" |
12 | android:layout_height= "wrap_content" |
13 | android:cacheColorHint= "#00000000" |
14 | android:numColumns= "3" |
15 | android:stretchMode= "columnWidth" |
16 | android:verticalSpacing= "5dip" |
17 | android:horizontalSpacing= "20dip" |
18 | android:background= "#ffffff" /> |
3.列表项布局drag_grid_item.xml.
<?xml version= "1.0" encoding= "utf-8" ?> |
android:layout_width= "fill_parent" |
android:layout_height= "wrap_content" |
android:paddingLeft= "5dip" |
android:paddingRight= "5dip" > |
<ImageView android:id= "@+id/drag_grid_item_image" |
android:src= "@drawable/grid_icon" |
android:layout_margin= "5dip" |
android:layout_alignParentTop= "true" |
android:layout_width= "fill_parent" |
android:layout_height= "wrap_content" /> |
<ImageView android:id= "@+id/drag_grid_item_drag" |
android:src= "@drawable/grid_drag" |
android:layout_alignParentTop= "true" |
android:layout_alignParentRight= "true" |
android:layout_width= "wrap_content" |
android:layout_height= "wrap_content" /> |
4.自定义适配器DragGridAdapter,继承ArrayAdapter<String>.
01 | public static class DragGridAdapter extends ArrayAdapter<String>{ |
03 | public DragGridAdapter(Context context, List<String> objects) { |
04 | super (context, 0 , objects); |
06 | public List<String> getList(){ |
11 | public View getView( int position, View convertView, ViewGroup parent) { |
12 | View view = convertView; |
14 | view = LayoutInflater.from(getContext()).inflate(R.layout.drag_grid_item, null ); |
19 | Field f= (Field)R.drawable. class .getDeclaredField(getItem(position)); |
20 | int i=f.getInt(R.drawable. class ); |
21 | ImageView imageview= (ImageView)view.findViewById(R.id.drag_grid_item_image); |
22 | imageview.setImageResource(i); |
23 | } catch (SecurityException e) { |
25 | } catch (NoSuchFieldException e) { |
27 | } catch (IllegalArgumentException e) { |
29 | } catch (IllegalAccessException e) { |
5.自定义视图类DragGridView,继承GridView.
public class DragGridView extends GridView { |
private ImageView dragImageView; |
private int dragSrcPosition; |
private int dragPosition; |
private WindowManager windowManager; |
private WindowManager.LayoutParams windowParams; |
private int scaledTouchSlop; |
private int upScrollBounce; |
private int downScrollBounce; |
public DragGridView(Context context, AttributeSet attrs) { |
6.
重写触控拦截事件方法onInterceptTouchEvent().
02 | public boolean onInterceptTouchEvent(MotionEvent ev) { |
03 | if (ev.getAction()==MotionEvent.ACTION_DOWN){ |
04 | int x = ( int )ev.getX(); |
05 | int y = ( int )ev.getY(); |
07 | dragSrcPosition = dragPosition = pointToPosition(x, y); |
08 | if (dragPosition==AdapterView.INVALID_POSITION){ |
09 | return super .onInterceptTouchEvent(ev); |
12 | ViewGroup itemView = (ViewGroup) getChildAt(dragPosition-getFirstVisiblePosition()); |
13 | dragPointX = x - itemView.getLeft(); |
14 | dragPointY = y - itemView.getTop(); |
15 | dragOffsetX = ( int ) (ev.getRawX() - x); |
16 | dragOffsetY = ( int ) (ev.getRawY() - y); |
18 | View dragger = itemView.findViewById(R.id.drag_grid_item_drag); |
20 | if (dragger!= null &&dragPointX>dragger.getLeft()&&dragPointX<dragger.getRight()&&dragPointY>dragger.getTop()&&dragPointY<dragger.getBottom()+ 20 ){ |
22 | upScrollBounce = Math.min(y-scaledTouchSlop, getHeight()/ 4 ); |
23 | downScrollBounce = Math.max(y+scaledTouchSlop, getHeight()* 3 / 4 ); |
25 | itemView.setDrawingCacheEnabled( true ); |
26 | Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache()); |
31 | return super .onInterceptTouchEvent(ev); |
startDrag和stopDrag方法如下:
01 | public void startDrag(Bitmap bm, int x, int y){ |
04 | windowParams = new WindowManager.LayoutParams(); |
05 | windowParams.gravity = Gravity.TOP|Gravity.LEFT; |
06 | windowParams.x = x - dragPointX + dragOffsetX; |
07 | windowParams.y = y - dragPointY + dragOffsetY; |
08 | windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT; |
09 | windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT; |
10 | windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
11 | | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
12 | | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
13 | | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; |
14 | windowParams.format = PixelFormat.TRANSLUCENT; |
15 | windowParams.windowAnimations = 0 ; |
17 | ImageView imageView = new ImageView(getContext()); |
18 | imageView.setImageBitmap(bm); |
19 | windowManager = (WindowManager)getContext().getSystemService( "window" ); |
20 | windowManager.addView(imageView, windowParams); |
21 | dragImageView = imageView; |
24 | public void onDrag( int x, int y){ |
25 | if (dragImageView!= null ){ |
26 | windowParams.alpha = 0 .8f; |
27 | windowParams.x = x - dragPointX + dragOffsetX; |
28 | windowParams.y = y - dragPointY + dragOffsetY; |
29 | windowManager.updateViewLayout(dragImageView, windowParams); |
32 | int tempPosition = pointToPosition(x, y); |
33 | if (tempPosition!=INVALID_POSITION){ |
34 | dragPosition = tempPosition; |
38 | if (y<upScrollBounce||y>downScrollBounce){ |
40 | setSelection(dragPosition); |
7.重写onTouchEvent()方法.
02 | public boolean onTouchEvent(MotionEvent ev) { |
03 | if (dragImageView!= null &&dragPosition!=INVALID_POSITION){ |
04 | int action = ev.getAction(); |
06 | case MotionEvent.ACTION_UP: |
07 | int upX = ( int )ev.getX(); |
08 | int upY = ( int )ev.getY(); |
12 | case MotionEvent.ACTION_MOVE: |
13 | int moveX = ( int )ev.getX(); |
14 | int moveY = ( int )ev.getY(); |
21 | return super .onTouchEvent(ev); |
其中onDrag方法如下:
01 | public void onDrag( int x, int y){ |
02 | if (dragImageView!= null ){ |
03 | windowParams.alpha = 0 .8f; |
04 | windowParams.x = x - dragPointX + dragOffsetX; |
05 | windowParams.y = y - dragPointY + dragOffsetY; |
06 | windowManager.updateViewLayout(dragImageView, windowParams); |
09 | int tempPosition = pointToPosition(x, y); |
10 | if (tempPosition!=INVALID_POSITION){ |
11 | dragPosition = tempPosition; |
15 | if (y<upScrollBounce||y>downScrollBounce){ |
17 | setSelection(dragPosition); |
8.放下影像,数据更新。
在onDrop方法中实现:
01 | public void onDrop( int x, int y){ |
04 | int tempPosition = pointToPosition(x, y); |
05 | if (tempPosition!=INVALID_POSITION){ |
06 | dragPosition = tempPosition; |
10 | if (y<getChildAt( 0 ).getTop()){ |
13 | } else if (y>getChildAt(getChildCount()- 1 ).getBottom()||(y>getChildAt(getChildCount()- 1 ).getTop()&&x>getChildAt(getChildCount()- 1 ).getRight())){ |
15 | dragPosition = getAdapter().getCount()- 1 ; |
19 | if (dragPosition!=dragSrcPosition&&dragPosition>- 1 &&dragPosition<getAdapter().getCount()){ |
20 | DragGridAdapter adapter = (DragGridAdapter)getAdapter(); |
21 | String dragItem = adapter.getItem(dragSrcPosition); |
22 | adapter.remove(dragItem); |
23 | adapter.insert(dragItem, dragPosition); |
24 | Toast.makeText(getContext(), adapter.getList().toString(), Toast.LENGTH_SHORT).show(); |
10.最终效果图如下:
图1
图2
这篇文章也算是前面文章的一个补充和扩展。