2017-09-22 13 views
2

J'utilise un FloatingActionButton dans mon application. Parfois, il chevauche le contenu essentiel, donc je voudrais faire en sorte que l'utilisateur puisse faire glisser le FAB hors de son chemin.Android - Bouton d'action flottant mobile/déplaçable (FAB)

Aucune fonctionnalité de glisser-déposer n'est nécessaire en soi. Il doit juste être mobile. Les documents ne mentionnent pas cela, mais je suis sûr que j'ai vu une telle fonctionnalité dans d'autres applications.

Pouvez-vous nous conseiller/fournir un extrait de code sur la façon de le faire (de préférence en XML).

Répondre

8

Basé sur this answer for another SO question c'est le code que j'ai créé. Il semble fonctionner très bien (avec le travail fonctionnalité de clic) et ne dépend pas de la mise en page des parents de FAB ou de positionnement ...

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); 
     } 

    } 

} 

Et voici le 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"/> 

Fondamentalement, vous avez juste besoin de remplacer android.support.design.widget.FloatingActionButton par com.example.MovableFloatingActionButton dans votre fichier XML.

0

vous pouvez essayer comme ci-dessous par juste impletementing onTouch sur tout View,

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

Merci Omar. J'ai essayé cette approche, mais je n'ai pas eu de chance avec ça. J'ai du code qui fonctionne, donc je vais le poster en une seconde. Merci quand même. –