溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android如何實現可拖拽的GridView效果長按可拖拽刪除數據源

發布時間:2021-04-16 13:48:15 來源:億速云 閱讀:333 作者:小新 欄目:移動開發

小編給大家分享一下Android如何實現可拖拽的GridView效果長按可拖拽刪除數據源,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

Android 可拖拽的GridView效果實現, 長按可拖拽和item實時交換

簡單修改,完成自己想要的功能:長按,移到垃圾桶,刪除數據。

Android如何實現可拖拽的GridView效果長按可拖拽刪除數據源

主要思路是:

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效果長按可拖拽刪除數據源”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女