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