ViewDragHelper詳解

一、ViewDragHelper透傳

ViewDragHelper是android官方提供的一個用於拖拽控件的類。在很多場合下,我們需要在一個控件上拖動進行一些交互操作,而ViewDragHelper的出現就使這個過程變得更加簡單。此外,ViewDragHelper還提供了一些透傳的操作,這意味着你可以在ViewDragHelper的回調函數中操作它所依賴的控件,並不需要對控件進行額外的監聽和操作,大大提升了代碼編寫效率。

示例代碼:

public class DragView extends FrameLayout {

    private ViewDragHelper mViewDragHelper;

    public DragView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return false;
            }

            @Override
            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                super.onViewPositionChanged(changedView, left, top, dx, dy);
                // 透傳操作,在View位置改變的時候同步改變背景顏色
                setBackground(Color.RED);
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return mViewDragHelper.shouldInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mViewDragHelper.processTouchEvent(event);
        return true;
    }
}

二、ViewDragHelper Scroll/邊界控制

ViewDragHelper還可以控制控件的滑動範圍以及邊界。在回調函數的onEdgeDragStarted方法中,可以獲取到觸摸邊界的距離以及邊界的方向,在此基礎上可以定義一些邊緣控制操作。

示例代碼:

ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
    // ...

    @Override
    public void onEdgeDragStarted(int edgeFlags, int pointerId) {
        super.onEdgeDragStarted(edgeFlags, pointerId);
        // 邊界控制,在邊界處開始滑動時設置TargetView的位置以及滑動範圍
        mViewDragHelper.captureChildView(mTargetView, pointerId);
        mViewDragHelper.settleCapturedViewAt(0, 0);
        invalidate();
    }

    @Override
    public int clampViewPositionHorizontal(View child, int left, int dx) {
        // 控制水平方向的滑動範圍
        final int leftBound = getPaddingLeft();
        final int rightBound = getWidth() - child.getWidth() - getPaddingRight();
        final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
        return newLeft;
    }

    @Override
    public int clampViewPositionVertical(View child, int top, int dy) {
        // 控制豎直方向的滑動範圍
        final int topBound = getPaddingTop();
        final int bottomBound = getHeight() - child.getHeight() - getPaddingBottom();
        final int newTop = Math.min(Math.max(top, topBound), bottomBound);
        return newTop;
    }

    @Override
    public void onViewReleased(View releasedChild, float xvel, float yvel) {
        // 滑動結束後的回調,可以在這裡進行一些結束操作
    }
});

三、ViewDragHelper使用

在使用ViewDragHelper時,需要將其綁定到要拖拽的控件上,同時在控件的手勢事件監聽中透傳ViewDragHelper的事件,從而達到拖拽控件的目的。

示例代碼:

public class DragView extends FrameLayout {

    private ViewDragHelper mViewDragHelper;

    public DragView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return child.getId() == R.id.target;
            }

            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                return left;
            }

            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                return top;
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return mViewDragHelper.shouldInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mViewDragHelper.processTouchEvent(event);
        return true;
    }

    @Override
    public void computeScroll() {
        if (mViewDragHelper.continueSettling(true)) {
            invalidate();
        }
    }
}

四、ViewDragHelper透傳事件

在使用ViewDragHelper時,可以透傳一些事件,比如點擊事件、長按事件、焦點事件等,從而使拖拽控件的交互更加豐富。

示例代碼:

ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
    // ...

    @Override
    public boolean tryCaptureView(View child, int pointerId) {
        child.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mViewDragHelper.isDragging();
            }
        });

        child.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getContext(), "click", Toast.LENGTH_SHORT).show();
            }
        });

        child.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Toast.makeText(getContext(), "long click", Toast.LENGTH_SHORT).show();
                return true;
            }
        });
        return true;
    }
});

五、ViewDragHelper類

ViewDragHelper是一個輔助類,提供了一些拖拽控件的基本操作和回調函數,這些函數和方法包括:

  • create()方法:創建一個ViewDragHelper實例
  • xVelocity和yVelocity:設置或獲取x軸和y軸方向的速度值
  • shouldInterceptTouchEvent()方法:判斷是否需要在ViewGroup的onInterceptTouchEvent()方法中攔截觸摸事件
  • processTouchEvent()方法:處理觸摸事件
  • settleCapturedViewAt()方法:設置TargetView滑動到指定位置
  • continueSettling()方法:持續動畫滑動
  • callback屬性:ViewDragHelper.Callback回調函數

六、ViewDragHelper右滑

在ViewDragHelper中,可以通過onTouchEvent()方法判斷是否拖動了控件,並根據拖動的方向進行相應操作。例如在右滑時,可以將TargetView向右滑動一個固定的距離。

示例代碼:

public boolean onTouchEvent(MotionEvent event) {
    mViewDragHelper.processTouchEvent(event);
    if (event.getAction() == MotionEvent.ACTION_UP) {
        if (getChildAt(0).getLeft() < getWidth() / 2) {
            mViewDragHelper.settleCapturedViewAt(0, 0);
        } else {
            mViewDragHelper.settleCapturedViewAt(getWidth() - getChildAt(0).getWidth(), 0);
        }
        invalidate();
    }
    return true;
}

七、ViewDragHelper阿拉伯語

在ViewDragHelper使用場景中,可能會出現阿拉伯語的情況,此時可以調用ViewDragHelper的setLayoutDirection()方法,將布局方向設為RTL(Right-to-Left),從而保證阿拉伯語的正確顯示。

示例代碼:

ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
    // ...

    @Override
    public void onEdgeDragStarted(int edgeFlags, int pointerId) {
        super.onEdgeDragStarted(edgeFlags, pointerId);
        setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
        mViewDragHelper.captureChildView(mTargetView, pointerId);
        mViewDragHelper.settleCapturedViewAt(getMeasuredWidth() - mTargetView.getMeasuredWidth(), 0);
        invalidate();
    }
});

八、ViewDragHelper刷新後位置回到

有時候,ViewDragHelper在處理完觸摸事件後會將控件位置恢復到初始位置,此時需要通過在onLayout()方法中計算控件位置,將控件重新放置到目標位置。

示例代碼:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    int childLeft = getPaddingLeft();
    int childTop = getPaddingTop();

    mTargetView.layout(childLeft, childTop, childLeft + mTargetView.getMeasuredWidth(),
            childTop + mTargetView.getMeasuredHeight());
}

九、ViewDragHelper RecyclerView選取

ViewDragHelper在RecyclerView中的使用,可以實現RecyclerView中指定Item的拖拽效果,從而提高用戶交互效果。

示例代碼:

public class ItemTouchHelperCallback extends ItemTouchHelper.Callback {

    private final ItemTouchHelperAdapter mAdapter;

    public ItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
        mAdapter = adapter;
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
    }
}

在RecyclerView中使用ViewDragHelper需要通過調用ItemTouchHelper的attachToRecyclerView()方法,將ItemTouchHelper和RecyclerView綁定起來,在此基礎上可以實現RecyclerViewItem的拖拽效果。

示例代碼:

ItemTouchHelper.Callback callback = new ItemTouchHelperCallback(mAdapter);
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(mRecyclerView);

以上就是ViewDragHelper的詳細介紹,對於想要實現一些拖拽效果的開發者來說,ViewDragHelper絕對是一個非常好用的工具。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/243796.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:58
下一篇 2024-12-12 12:58

相關推薦

  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分布式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • C語言貪吃蛇詳解

    一、數據結構和算法 C語言貪吃蛇主要運用了以下數據結構和算法: 1. 鏈表 typedef struct body { int x; int y; struct body *nex…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性傳感器,能夠同時測量加速度和角速度。它由三個傳感器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web服務器。nginx是一個高性能的反向代理web服務器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25

發表回復

登錄後才能評論