浮動按鈕 (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: `實作相關`