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效果长按可拖拽删除数据源,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对呐喊教程网站的支持!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:notice#nhooo.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。