2017-09-22 20 views
2

私のアプリでFloatingActionButtonを使用しています。場合によっては必須のコンテンツと重なることもあるので、ユーザーがFABをドラッグしないようにしたいと思っています。Android - Movable/Draggable Floating Action Button(FAB)

ドラッグアンドドロップ機能自体は必要ありません。それは単に動かす必要があります。ドキュメントにはこれは言及されていませんが、私は他のアプリでこのような機能を見たことがあります。

どのように(できればXMLで)コードスニペットをアドバイスしてください。

答えて

8

this answer for another SO questionに基づいて、これは私が持っているコードです。作成した。 (ワーキングクリック機能付き)うまく動作するようですし、FABの親のレイアウトや配置に依存しない...

package com.example; 

import android.content.Context; 
import android.support.design.widget.FloatingActionButton; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.View; 

public class MovableFloatingActionButton extends FloatingActionButton implements View.OnTouchListener { 

    private final static float CLICK_DRAG_TOLERANCE = 10; // Often, there will be a slight, unintentional, drag when the user taps the FAB, so we need to account for this. 

    private float downRawX, downRawY; 
    private float dX, dY; 

    public MovableFloatingActionButton(Context context) { 
     super(context); 
     init(); 
    } 

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

    public MovableFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(); 
    } 

    private void init() { 
     setOnTouchListener(this); 
    } 

    @Override 
    public boolean onTouch(View view, MotionEvent motionEvent){ 

     int action = motionEvent.getAction(); 
     if (action == MotionEvent.ACTION_DOWN) { 

      downRawX = motionEvent.getRawX(); 
      downRawY = motionEvent.getRawY(); 
      dX = view.getX() - downRawX; 
      dY = view.getY() - downRawY; 

      return true; // Consumed 

     } 
     else if (action == 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(0, newX); // Don't allow the FAB past the left hand side of the parent 
      newX = Math.min(parentWidth - viewWidth, newX); // Don't allow the FAB past the right hand side of the parent 

      float newY = motionEvent.getRawY() + dY; 
      newY = Math.max(0, newY); // Don't allow the FAB past the top of the parent 
      newY = Math.min(parentHeight - viewHeight, newY); // Don't allow the FAB past the bottom of the parent 

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

      return true; // Consumed 

     } 
     else if (action == MotionEvent.ACTION_UP) { 

      float upRawX = motionEvent.getRawX(); 
      float upRawY = motionEvent.getRawY(); 

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

      if (Math.abs(upDX) < CLICK_DRAG_TOLERANCE && Math.abs(upDY) < CLICK_DRAG_TOLERANCE) { // A click 
       return performClick(); 
      } 
      else { // A drag 
       return true; // Consumed 
      } 

     } 
     else { 
      return super.onTouchEvent(motionEvent); 
     } 

    } 

} 

そして、ここではXMLです...基本的に

<com.example.MovableFloatingActionButton 
     android:id="@+id/fab" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="bottom|end" 
     android:layout_margin="@dimen/fab_margin" 
     android:src="@drawable/ic_navigate_next_white_24dp"/> 

あなたのXMLのandroid.support.design.widget.FloatingActionButtoncom.example.MovableFloatingActionButtonに置き換えるだけで済みます。

0
あなただけの任意の ViewonTouchをimpletementingことにより、以下のように試すことができ

XML

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:id="@+id/rootlayout" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 

    <android.support.design.widget.FloatingActionButton 
     android:id="@+id/fab" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 

</FrameLayout> 

javaの

public class dragativity extends AppCompatActivity implements View.OnTouchListener{ 

    FloatingActionButton fab; 

    FrameLayout rootlayout; 

    int _xDelta; 
    int _yDelta; 

    @Override 
    protected void onCreate(@Nullable Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.drag); 

     rootlayout = (FrameLayout) findViewById(R.id.rootlayout); 

     fab = (FloatingActionButton) findViewById(R.id.fab); 

     FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(150, 150); 
     fab.setLayoutParams(layoutParams); 
     fab.setOnTouchListener(dragativity.this); 
    } 

    public boolean onTouch(View view, MotionEvent event) { 
     final int X = (int) event.getRawX(); 
     final int Y = (int) event.getRawY(); 
     switch (event.getAction() & MotionEvent.ACTION_MASK) { 
      case MotionEvent.ACTION_DOWN: 
       FrameLayout.LayoutParams lParams = (FrameLayout.LayoutParams) view.getLayoutParams(); 
       _xDelta = X - lParams.leftMargin; 
       _yDelta = Y - lParams.topMargin; 
       break; 
      case MotionEvent.ACTION_UP: 
       break; 
      case MotionEvent.ACTION_POINTER_DOWN: 
       break; 
      case MotionEvent.ACTION_POINTER_UP: 
       break; 
      case MotionEvent.ACTION_MOVE: 
       FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view 
         .getLayoutParams(); 
       layoutParams.leftMargin = X - _xDelta; 
       layoutParams.topMargin = Y - _yDelta; 
       layoutParams.rightMargin = -250; 
       layoutParams.bottomMargin = -250; 
       view.setLayoutParams(layoutParams); 
       break; 
     } 
     rootlayout.invalidate(); 
     return true; 
    } 


} 
+0

ありがとうオマール。私はこのアプローチを試みてきたが、それに運がなかった。私はいくつかのコードが動作している、しかし、秒でそれを投稿します。とにかくありがとう。 –