Android實(shí)現(xiàn)可拖拽的GridView效果長(zhǎng)按可拖拽刪除數(shù)據(jù)源
Android 可拖拽的GridView效果實(shí)現(xiàn), 長(zhǎng)按可拖拽和item實(shí)時(shí)交換
簡(jiǎn)單修改,完成自己想要的功能:長(zhǎng)按,移到垃圾桶,刪除數(shù)據(jù)。
主要思路是:
1.獲取到用戶長(zhǎng)按的操作
2.獲取按下的圖片的bitmap以及移動(dòng)的時(shí)候動(dòng)態(tài)刷新鏡像
3 action_up的時(shí)候判斷鏡像的位置,進(jìn)入是否刪除邏輯
自定義控件
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; /** * 長(zhǎng)按能選中item的,丟入垃圾箱的gridView * * @author leafact * */ public class MoveGridView extends GridView { private WindowManager mWindowManager; /** * item鏡像的布局參數(shù) */ private WindowManager.LayoutParams mWindowLayoutParams; /** * 震動(dòng)器 */ private Vibrator mVibrator; // 震動(dòng)的時(shí)間,默認(rèn)為100ms private long vibratorMs = 100; // 設(shè)置長(zhǎng)按時(shí)間為1秒 private long responseMS = 1000; private static boolean isMove = false; // 按下去的x,y private int mDownX = 0; private int mDownY = 0; // 移動(dòng)的時(shí)候的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; /** * 狀態(tài)欄的高度 */ 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); // 獲取狀態(tài)欄的高度 } // 要移動(dòng)的item的位置,默認(rèn)為INVALID_POSITION=-1 private int mMovePosition = INVALID_POSITION; /** * 剛開始拖拽的item對(duì)應(yīng)的View */ private View mStartMoveItemView = null; private ImageView mMoveImageView = null; private Bitmap mMoveBitmap; private Handler mHandler = new Handler(); // 判斷是否能開始移動(dòng)元素 private Runnable mLongClickRunnable = new Runnable() { @Override public void run() { isMove = true; mVibrator.vibrate(vibratorMs); // 根據(jù)我們按下的點(diǎn)顯示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"); // 根據(jù)按下的X,Y坐標(biāo)獲取所點(diǎn)擊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對(duì)象 mMoveBitmap = Bitmap.createBitmap(mStartMoveItemView .getDrawingCache()); // 這一步很關(guān)鍵,釋放繪圖緩存,避免出現(xiàn)重復(fù)的鏡像 mStartMoveItemView.destroyDrawingCache(); break; case MotionEvent.ACTION_MOVE: mMoveX = (int) ev.getX(); mMoveY = (int) ev.getY(); // 如果我們?cè)诎聪碌膇tem上面移動(dòng),只要不超過item的邊界我們就不移除mRunnable // 依然能監(jiān)聽到longClick if (!isTouchInItem(mStartMoveItemView, mMoveX, mMoveY)) { mHandler.removeCallbacks(mLongClickRunnable); } // //禁止Gridview側(cè)邊進(jìn)行滑動(dòng),移動(dòng)的時(shí)候不許發(fā)生側(cè)滑事件 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); } /** * 判斷是否要?jiǎng)h除,滿足條件刪除 */ private void deleteIfNeed() { int y = mUpY - mPoint2ItemTop + mOffset2Top - mStatusHeight; if(y<50){ if(mUninstallListener!=null) mUninstallListener.onUninstallListener(mMovePosition); } } /** * 是否點(diǎn)擊在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; } /** * 創(chuàng)建拖動(dòng)的鏡像 * * @param bitmap * @param downX * 按下的點(diǎn)相對(duì)父控件的X坐標(biāo) * @param downY * 按下的點(diǎn)相對(duì)父控件的X坐標(biāo) */ 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); } /** * 從界面上面移動(dòng)拖動(dòng)鏡像 */ private void removeDragImage() { if (mMoveImageView != null) { mWindowManager.removeView(mMoveImageView); mMoveImageView = null; } } /** * 拖動(dòng)item,在里面實(shí)現(xiàn)了item鏡像的位置更新,item的相互交換以及GridView的自行滾動(dòng) * * @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); // 更新鏡像的位置 } /** * 獲取狀態(tài)欄的高度 * * @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; } /** * 設(shè)置響應(yīng)拖拽的毫秒數(shù),默認(rèn)是1000毫秒 * * @param responseMS */ public void setResponseMS(long responseMS) { this.responseMS = responseMS; } /** * 設(shè)置震動(dòng)時(shí)間的毫秒數(shù),默認(rèn)是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));// 按序號(hào)做ItemText lstImageItem.add(map); } final SimpleAdapter saImageItems = new SimpleAdapter(this, lstImageItem,// 數(shù)據(jù)來源 R.layout.gridview_item, // 動(dòng)態(tài)數(shù)組與ImageItem對(duì)應(yīng)的子項(xiàng) new String[] { "ItemText" }, // ImageItem的XML文件里面的一個(gè)ImageView,兩個(gè)TextView ID new int[] { R.id.ItemText }); // 添加并且顯示 mMoveGridView.setAdapter(saImageItems); //監(jiān)聽到卸載刪除數(shù)據(jù) 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>
總結(jié)
以上所述是小編給大家介紹的Android實(shí)現(xiàn)可拖拽的GridView效果長(zhǎng)按可拖拽刪除數(shù)據(jù)源,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
詳解Android使用OKHttp3實(shí)現(xiàn)下載(斷點(diǎn)續(xù)傳、顯示進(jìn)度)
本篇文章主要介紹了詳解Android使用OKHttp3實(shí)現(xiàn)下載(斷點(diǎn)續(xù)傳、顯示進(jìn)度),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02Android SD卡上文件操作及記錄日志操作實(shí)例分析
這篇文章主要介紹了Android SD卡上文件操作及記錄日志操作的方法,涉及Android針對(duì)SD卡與文件操作的相關(guān)技巧,需要的朋友可以參考下2016-01-01Android基于PhotoView實(shí)現(xiàn)的頭像/圓形裁剪控件
這篇文章主要給大家介紹了關(guān)于Android基于PhotoView實(shí)現(xiàn)的頭像/圓形裁剪控件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07Android實(shí)現(xiàn)旋轉(zhuǎn)動(dòng)畫的兩種方式案例詳解
這篇文章主要介紹了Android實(shí)現(xiàn)旋轉(zhuǎn)動(dòng)畫的兩種方式,需要的朋友可以參考下2021-08-08