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效果长按可拖拽删除数据源,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • android ListView和GridView拖拽移位实现代码

    关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:             首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.说明一点

  • Android自定义View实现可以拖拽的GridView

    先看看效果图 主要思想: 1.监听触碰事件 2.用WindowManager添加拖曳的图片 3.用Collections.swap()交换List数据 自定义代码: public class DragGridVeiw extends GridView { private final int PRESS_TIME = 1000;//长按时间 private int mDownX;//触碰时的X坐标 private int mDownY;//触碰时的Y坐标 private int mMoveX;//

  • Android中在GridView网格视图上实现item拖拽交换的方法

    GridView基础 新建一个HelloGridView的工程 修改main.xml代码如下: <?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width=&q

  • 详解Android使GridView横向水平滚动的实现方式

    Android为我们提供了竖直方向的滚动控件GridView,但如果我们想让它水平滚动起来,就需要自己实现了. 以下使用的测试数据datas集合都为List<ResolveInfo>类型,用来存储手机中的所有App public static List<ResolveInfo> getAppData(Context context) { PackageManager packageManager = context.getPackageManager(); Intent mainI

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

    Android 可拖拽的GridView效果实现, 长按可拖拽和item实时交换 简单修改,完成自己想要的功能:长按,移到垃圾桶,删除数据. 主要思路是: 1.获取到用户长按的操作 2.获取按下的图片的bitmap以及移动的时候动态刷新镜像 3 action_up的时候判断镜像的位置,进入是否删除逻辑 自定义控件 package com.leafact.GridView; import android.app.Activity; import android.content.Context; i

  • JS实现的3D拖拽翻页效果代码

    本文实例讲述了JS实现的3D拖拽翻页效果.分享给大家供大家参考,具体如下: 以前看到一个很火的帖子,拖拽实现的翻页效果,非常的有创意,自己也很喜欢,于是乎就萌发了用自己的方法模仿的想法.感谢原创作者的创意,结果一样,但过程不一样哦.奉上代码,供大家参考. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-3d-drag-page-style-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DT

  • JavaScript 拖拽翻页效果代码

    拖拽翻页效果JavaScript特效-demo by http://www.jb51.net html,body{ width:100%; height:100%; border:0px; margin:0px; overflow:hidden; } #menu{ width:1000px; height:500px; overflow:hidden; background:lightblue; } .page{ position:absolute; width:300px; height:40

  • jquery实现可旋转可拖拽的文字效果代码

    本文实例讲述了jquery实现可旋转可拖拽的文字效果代码.分享给大家供大家参考,具体如下: 运行效果截图如下: 具体代码如下: <html> <head> <title>test</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script type="text/javascript

  • Vue 基于 vuedraggable 实现选中、拖拽、排序效果

    今天有个朋友说要做个效果:Vue实现拖拽排序,要有 checked,输出结果是排序后的,要全选,未选中的不能拖动. 其实我之前基于 Sortable 做过一个类似的效果.也给他看过了,没看太明白,他就自己基于 vuedraggable 实现了一下. 正好有点问题给他解决了一下.废话不多说,先上最终效果:Vue 拖拽排序效果 测试地址.下面就是最终效果图. 效果一:实现选中 和 全选效果 就下面这样,elementUI 官方 Demo.很简单毫无挑战呀. <el-checkbox :indeter

  • vue和H5 draggable实现拖拽并替换效果

    前言 公司项目需要做拖拽替换效果,本人用的vue框架.在网上找了很多资料都是用的 Vue.Draggable(git地址).但这个组件实现的拖拽后插入效果,我倒腾了很久也没有替换效果(如果Vue.Draggable能实现拖拽替换效果的话请大神给我留言). JQ有实现拖拽的插件,我下载过一个插件并看过源码,大致原理是给目标元素设置定位属性,通过监听鼠标mousedown,mouseup事件,再计算鼠标位置变化,然后给元素样式设置偏移值来实现拖拽效果的. H5提供了专门的拖拽API 给元素添加 dr

  • JavaScript实现拖拽和缩放效果

    本文实例为大家分享了JavaScript实现拖拽和缩放效果的具体代码,供大家参考,具体内容如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>拖拽缩放</title> <me

  • 拖拽插件sortable.js实现el-table表格拖拽效果

    目录 问题描述 案例一 简单拖拽 代码附上 案例二 el-table表格拖拽 效果图 代码附上 问题描述 Sortable.js是一款优秀的js拖拽库,因为是原生js写的,所以性能不错,也支持移动端哦.本文举两个案例来学习一下. 案例一 简单拖拽 效果图 代码附上 关于理解看注释哦,运行的话复制粘贴即可 <!DOCTYPE html> <html> <head>     <meta charset="utf-8" />     <t

  • C#自定义鼠标拖拽Drag&Drop效果之基本原理及基本实现代码

    目录 一.前言 二.基本原理 1,设计界面 2,拖拽发起方 3,拖拽接收方 4,实际演示 三.自定义拖拽时鼠标效果 1,界面设计 2,拖拽发起方 3,拖拽接收方 4,GiveFeedback实现鼠标样式切换 4,实际演示 四.源码下载 五.总结 一.前言 拖拽(Drag&Drop),属于是极其常用的基础功能.无论是在系统上.应用上.还是在网页上,拖拽随处可见.同时拖拽时的鼠标效果也很漂亮,像这样: 这样: 还有这样: 等等等等.这些拖拽时的鼠标效果,直观又美观.然后,在我们写程序时,程序确实是支

  • 一文搞懂Android RecyclerView点击展开、折叠效果的实现代码

    RecyclerView是什么 RecycleView是Android5.0后谷歌推出的一个用于在有限的窗口中展示大量数据集的控件,位于support-v7包中.它可以实现与ListView和GridView一样的效果,提供了一种插拔式的体验,高度的解耦,异常的灵活,只需设置其提供的不同的LayoutManager,ItemAnimator和ItemDecoration,就能实现不同的效果. RecyclerView的优点 1.支持局部刷新.    2.可以自定义item增删时的动画.    3

随机推荐