---
# System prepended metadata

title: '浮動按鈕 (Floating Action Button, FAB) 之移動'
tags: [實作相關]

---

浮動按鈕 (Floating Action Button, FAB) 之移動
===

以下是我的 case，我是寫在 Fragment 裏面:

* 佈局檔
```xml=
...

<!--region 浮動按鈕-->
<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/faBtn_upload"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    android:layout_marginBottom="8dp"
    android:layout_marginEnd="8dp"
    app:srcCompat="@drawable/ic_baseline_add_24" />
<!--endregion-->

...

```

* class
```java=

public class SecondFragment {
    
    private FloatingActionButton faBtn_upload;
    private float dX, dY;
    private float downRawX, downRawY;
    private final static float CLICK_DRAG_TOLERANCE = 10; 


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        // get UI view
        faBtn_upload = (FloatingActionButton) view.findViewById(R.id.faBtn_upload);

        ...

        faBtn_upload.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)view.getLayoutParams();

                switch (motionEvent.getActionMasked()) {
                    case MotionEvent.ACTION_DOWN:
                        downRawX = motionEvent.getRawX();
                        downRawY = motionEvent.getRawY();
                        dX = view.getX() - downRawX;
                        dY = view.getY() - downRawY;

                        // 變更深色背景
                        view.setPressed(true);

                        return true;

                    case MotionEvent.ACTION_MOVE:
                        int viewWidth = view.getWidth();
                        int viewHeight = view.getHeight();

                        View viewParent = (View)view.getParent();
                        int parentWidth = viewParent.getWidth();
                        int parentHeight = viewParent.getHeight();

                        float newX = motionEvent.getRawX() + dX;
                        newX = Math.max(layoutParams.leftMargin, newX); // 不允許超過左邊界
                        newX = Math.min(parentWidth - viewWidth - layoutParams.rightMargin, newX); // 不允許超過右邊界

                        float newY = motionEvent.getRawY() + dY;
                        newY = Math.max(layoutParams.topMargin, newY); // 不允許超過上邊界
                        newY = Math.min(parentHeight - viewHeight - layoutParams.bottomMargin, newY); // 不允許超過下邊界

                        view.animate().x(newX).y(newY).setDuration(0).start();

                        return true;

                    /** 等同於 click 事件 */
                    case MotionEvent.ACTION_UP:
                        final float upRawX = motionEvent.getRawX();
                        final float upRawY = motionEvent.getRawY();

                        final float upDX = upRawX - downRawX;
                        final float upDY = upRawY - downRawY;

                        // 回復背景顏色
                        view.setPressed(false);

                        if (Math.abs(upDX) < CLICK_DRAG_TOLERANCE && Math.abs(upDY) < CLICK_DRAG_TOLERANCE) { // A click
                            logger.info("click float action button");
                            return performClick();
                        }
                        else { // A drag
                            logger.info("just draging float action button");
                            return true; // Consumed
                        }

                    default:
                        return activity.onTouchEvent(motionEvent);
                }

            }

        ...
    }


    private boolean performClick() {
        Toast.makeText(activity, "Clicked!", Toast.LENGTH_SHORT).show();

        // todo: Your Customization (ex: 彈出 Dialog 視窗)

        return true;
    }
                                        
}
```

## Ref.
[Android - Movable/Draggable Floating Action Button (FAB)](https://stackoverflow.com/questions/46370836/android-movable-draggable-floating-action-button-fab/46373935)

###### tags: `實作相關`