Android实现可拖拽的GridView效果长按可拖拽删除数据源

Android 可拖拽的GridView效果实现,长按可拖拽和item实时交换

简单修改,完成自己想要的功能:长按,移到垃圾桶,删除数据。

主要思路是:

1.获取用户长按的操作

2.获取按下的图片的bitmap以及移动的时候动态刷新镜像

3 action_up的时候判断镜像的位置,进入是否删除逻辑

自定义控件

package com.leafact.GridView; 
import android.app.Activity; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.PixelFormat; 
import android.graphics.Rect; 
import android.os.Handler; 
import android.os.Vibrator; 
import android.util.AttributeSet; 
import android.view.Gravity; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.WindowManager; 
import android.widget.AdapterView; 
import android.widget.GridView; 
import android.widget.ImageView; 
import android.widget.Toast; 
/** 
 * 长按能选中item的,丢入垃圾箱的gridView 
 * 
 * @author leafact 
 * 
 */ 
public class MoveGridView extends GridView { 
  private WindowManager mWindowManager; 
  /** 
   * item镜像的布局参数 
   */ 
  private WindowManager.LayoutParams mWindowLayoutParams; 
  /** 
   * 震动器 
   */ 
  private Vibrator mVibrator; 
  // 震动的时间,认为100ms 
  private long vibratorMs = 100; 
  // 设置长按时间为1秒 
  private long responseMS = 1000; 
  private static boolean isMove = false; 
  // 按下去的x,y 
  private int mDownX = 0; 
  private int mDownY = 0; 
  // 移动的时候的x,y 
  private int mMoveX = 0; 
  private int mMoveY = 0; 
  // 抬起的x,y 
  private int mUpX = 0; 
  private int mUpY = 0; 
  private int mPoint2ItemTop; 
  private int mPoint2ItemLeft; 
  private int mOffset2Top; 
  private int mOffset2Left; 
  /** 
   * 状态栏的高度 
   */ 
  private int mStatusHeight; 
  public MoveGridView(Context context,AttributeSet attrs) { 
    super(context,attrs); 
    mVibrator = (Vibrator) context 
        .getSystemService(Context.VIBRATOR_SERVICE); 
    mWindowManager = (WindowManager) context 
        .getSystemService(Context.WINDOW_SERVICE); 
    mStatusHeight = getStatusHeight(context); // 获取状态栏的高度 
  } 
  // 要移动的item的位置,认为INVALID_POSITION=-1 
  private int mMovePosition = INVALID_POSITION; 
  /** 
   * 刚开始拖拽的item对应的View 
   */ 
  private View mStartMoveItemView = null; 
  private ImageView mMoveImageView = null; 
  private Bitmap mMoveBitmap; 
  private Handler mHandler = new Handler(); 
  // 判断是否能开始移动元素 
  private Runnable mLongClickRunnable = new Runnable() { 
    @Override 
    public void run() { 
      isMove = true; 
      mVibrator.vibrate(vibratorMs); 
      // 根据我们按下的点显示item镜像 
      createDragImage(mMoveBitmap,mDownX,mDownY); 
    } 
  }; 
  @Override 
  public boolean onTouchEvent(MotionEvent ev) { 
    switch (ev.getAction()) { 
    case MotionEvent.ACTION_DOWN: 
      mDownX = (int) ev.getX(); 
      mDownY = (int) ev.getY(); 
      System.out.println("ACTION_DOWN"); 
      // 根据按下的X,Y坐标获取所点击item的position 
      mMovePosition = pointToPosition(mDownX,mDownY); 
      // 如果选中的为非法的位置。则不处理消息 
      if (mMovePosition == AdapterView.INVALID_POSITION) { 
        break; 
      } 
      mHandler.postDelayed(mLongClickRunnable,responseMS); 
      mStartMoveItemView = getChildAt(mMovePosition 
          - getFirstVisiblePosition()); 
      mPoint2ItemTop = mDownY - mStartMoveItemView.getTop(); 
      mPoint2ItemLeft = mDownX - mStartMoveItemView.getLeft(); 
      mOffset2Top = (int) (ev.getRawY() - mDownY); 
      mOffset2Left = (int) (ev.getRawX() - mDownX); 
      // 开启mMoveItemView绘图缓存 
      mStartMoveItemView.setDrawingCacheEnabled(true); 
      // 获取mMoveItemView在缓存中的Bitmap对象 
      mMoveBitmap = Bitmap.createBitmap(mStartMoveItemView 
          .getDrawingCache()); 
      // 这一步很关键,释放绘图缓存,避免出现重复的镜像 
      mStartMoveItemView.destroyDrawingCache(); 
      break; 
    case MotionEvent.ACTION_MOVE: 
      mMoveX = (int) ev.getX(); 
      mMoveY = (int) ev.getY(); 
      // 如果我们在按下的item上面移动,只要不超过item的边界我们就不移除mRunnable 
      // 依然能监听到longClick 
      if (!isTouchInItem(mStartMoveItemView,mMoveX,mMoveY)) { 
        mHandler.removeCallbacks(mLongClickRunnable); 
      } 
      // //禁止Gridview侧边进行滑动,移动的时候不许发生侧滑事件 
      if (isMove) { 
        onDragItem(mMoveX,mMoveY); 
        return true; 
      } 
      break; 
    case MotionEvent.ACTION_UP: 
      mUpX = (int) ev.getX(); 
      mUpY = (int) ev.getY(); 
      mHandler.removeCallbacks(mLongClickRunnable); 
      if(isMove){ 
        deleteIfNeed(); 
      } 
      removeDragImage(); 
      isMove = false; 
      break; 
    default: 
      break; 
    } 
    return super.onTouchEvent(ev); 
  } 
  /** 
   * 判断是否要删除,满足条件删除 
   */ 
  private void deleteIfNeed() { 
    int y = mUpY - mPoint2ItemTop + mOffset2Top 
        - mStatusHeight; 
    if(y<50){ 
      if(mUninstallListener!=null) 
      mUninstallListener.onUninstallListener(mMovePosition); 
    } 
  } 
  /** 
   * 是否点击在GridView的item上面 
   * 
   * @param itemView 
   * @param x 
   * @param y 
   * @return 
   */ 
  private boolean isTouchInItem(View dragView,int x,int y) { 
    if (dragView == null) { 
      return false; 
    } 
    int leftOffset = dragView.getLeft(); 
    int topOffset = dragView.getTop(); 
    if (x < leftOffset || x > leftOffset + dragView.getWidth()) { 
      return false; 
    } 
    if (y < topOffset || y > topOffset + dragView.getHeight()) { 
      return false; 
    } 
    return true; 
  } 
  /** 
   * 创建拖动的镜像 
   * 
   * @param bitmap 
   * @param downX 
   *      按下的点相对父控件的X坐标 
   * @param downY 
   *      按下的点相对父控件的X坐标 
   */ 
  private void createDragImage(Bitmap bitmap,int downX,int downY) { 
    mWindowLayoutParams = new WindowManager.LayoutParams(); 
    mWindowLayoutParams.format = PixelFormat.TRANSLUCENT; // 图片之外的其他地方透明 
    mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; 
    mWindowLayoutParams.x = downX - mPoint2ItemLeft + mOffset2Left; 
    mWindowLayoutParams.y = downY - mPoint2ItemTop + mOffset2Top 
        - mStatusHeight; 
    mWindowLayoutParams.alpha = 0.55f; // 透明度 
    mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 
    mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 
    mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 
        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 
    mMoveImageView = new ImageView(getContext()); 
    mMoveImageView.setimageBitmap(bitmap); 
    mWindowManager.addView(mMoveImageView,mWindowLayoutParams); 
  } 
  /** 
   * 从界面上面移动拖动镜像 
   */ 
  private void removeDragImage() { 
    if (mMoveImageView != null) { 
      mWindowManager.removeView(mMoveImageView); 
      mMoveImageView = null; 
    } 
  } 
  /** 
   * 拖动item,在里面实现了item镜像的位置更新,item的相互交换以及GridView的自行滚动 
   * 
   * @param x 
   * @param y 
   */ 
  private void onDragItem(int moveX,int moveY) { 
    mWindowLayoutParams.x = moveX - mPoint2ItemLeft + mOffset2Left; 
    mWindowLayoutParams.y = moveY - mPoint2ItemTop + mOffset2Top 
        - mStatusHeight; 
    mWindowManager.updateViewLayout(mMoveImageView,mWindowLayoutParams); // 更新镜像的位置 
  } 
  /** 
   * 获取状态栏的高度 
   * 
   * @param context 
   * @return 
   */ 
  private static int getStatusHeight(Context context) { 
    int statusHeight = 0; 
    Rect localRect = new Rect(); 
    ((Activity) context).getwindow().getDecorView() 
        .getwindowVisibledisplayFrame(localRect); 
    statusHeight = localRect.top; 
    if (0 == statusHeight) { 
      Class<?> localClass; 
      try { 
        localClass = Class.forName("com.android.internal.R$dimen"); 
        Object localObject = localClass.newInstance(); 
        int i5 = Integer.parseInt(localClass 
            .getField("status_bar_height").get(localObject) 
            .toString()); 
        statusHeight = context.getResources().getDimensionPixelSize(i5); 
      } catch (Exception e) { 
        e.printstacktrace(); 
      } 
    } 
    return statusHeight; 
  } 
  /** 
   * 设置响应拖拽的毫秒数,认是1000毫秒 
   * 
   * @param responseMS 
   */ 
  public void setResponseMS(long responseMS) { 
    this.responseMS = responseMS; 
  } 
  /** 
   * 设置震动时间的毫秒数,认是1000毫秒 
   * 
   * @param responseMS 
   */ 
  public void setVibrator(long vibratorMs) { 
    this.vibratorMs = vibratorMs; 
  } 
  public void setonUninstallListener(UninstallListener l){ 
    mUninstallListener=l; 
  }; 
  private UninstallListener mUninstallListener; 
} 

MainActivity.java

package com.example.gridviewmovedemo; 
import java.util.ArrayList; 
import java.util.HashMap; 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemLongClickListener; 
import android.widget.SimpleAdapter; 
import com.leafact.GridView.MoveGridView; 
import com.leafact.GridView.UninstallListener; 
public class MainActivity extends Activity { 
  private MoveGridView mMoveGridView; 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    mMoveGridView = (MoveGridView) findViewById(R.id.gridview); 
    final ArrayList<HashMap<String,Object>> lstimageItem = new ArrayList<HashMap<String,Object>>(); 
    for (int i = 0; i < 10; i++) { 
      HashMap<String,Object> map = new HashMap<String,Object>(); 
      map.put("ItemText","NO." + String.valueOf(i));// 按序号做ItemText 
      lstimageItem.add(map); 
    } 
    final SimpleAdapter saimageItems = new SimpleAdapter(this,lstimageItem,// 数据来源 
        R.layout.gridview_item,// 动态数组与ImageItem对应的子项 
        new String[] { "ItemText" },// ImageItem的XML文件里面的一个ImageView,两个TextView ID 
        new int[] { R.id.ItemText }); 
    // 添加并且显示 
    mMoveGridView.setAdapter(saimageItems); 
    //监听到卸载删除数据 
    mMoveGridView.setonUninstallListener(new UninstallListener() { 
      @Override 
      public void onUninstallListener(int position) { 
        lstimageItem.remove(position); 
        saimageItems.notifyDataSetChanged(); 
      } 
    }); 
  } 
  @Override 
  public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.main,menu); 
    return true; 
  } 
} 

UninstallListener.java

package com.leafact.GridView; 
public interface UninstallListener { 
  void onUninstallListener(int position); 
} 

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  xmlns:tools="http://schemas.android.com/tools" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:background="#fff" 
  android:orientation="vertical" 
  tools:context=".MainActivity" > 
  <RelativeLayout 
    android:layout_width="fill_parent" 
    android:layout_height="100dip" 
    android:background="#ccc" > 
    <TextView 
      android:layout_width="wrap_content" 
      android:layout_height="fill_parent" 
      android:layout_centerHorizontal="true" 
      android:gravity="center" 
      android:text="卸载" 
      android:textColor="#fff" 
      android:textSize="28sp" /> 
  </RelativeLayout> 
  <com.leafact.GridView.MoveGridView 
    android:id="@+id/gridview" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:horizontalSpacing="5dip" 
    android:numColumns="3" 
    android:verticalSpacing="5dip" /> 
</LinearLayout> 

gridview_item.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:background="#2248DD" > 
  <TextView 
    android:id="@+id/ItemText" 
    android:layout_width="wrap_content" 
    android:layout_height="100dip" 
    android:layout_centerHorizontal="true" 
    android:gravity="center" > 
  </TextView> 
</RelativeLayout> 

总结

以上所述是小编给大家介绍的Android实现可拖拽的GridView效果长按可拖拽删除数据源,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...