Android - 可移动/可拖动的浮动操作按钮(FAB)

31

我在我的应用程序中使用了FloatingActionButton。偶尔会与重要内容重叠,因此我希望用户可以将FAB移到一边。

不需要拖放功能,只需要可移动即可。文档没有提到这一点,但我确定我在其他应用程序中看到过这种功能。

您能否提供建议/代码片段来执行此操作(最好是在XML中)?

11个回答

75

根据另一个SO问题的回答,这是我创建的代码。它似乎很好地工作了(具有工作的点击功能),并且不依赖于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;
import android.view.ViewGroup;

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){

        ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)view.getLayoutParams();

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

            float newY = motionEvent.getRawY() + dY;
            newY = Math.max(layoutParams.topMargin, newY); // Don't allow the FAB past the top of the parent
            newY = Math.min(parentHeight - viewHeight - layoutParams.bottomMargin, 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.FloatingActionButton替换为com.example.MovableFloatingActionButton


你是否在CoordinatorLayout中使用了MovableFloatingActionButton - ban-geoengineering
1
你能否在一个新的问题中发布你的问题和代码,然后在这里发布链接? - ban-geoengineering
这对我不起作用。在上面的代码能够运行的地方,缺少了哪些代码? - Miguel Tomás
这对我来说完美地运行了。谢谢你挽救了今天。 - Theophilus Abiola Alamu
它可以在屏幕区域内移动,但会阻止触摸屏幕背景(在FAB区域内移动)。 是否可能使FAB可移动并保持背景视图区域可触摸? - Zainal Fahrudin
显示剩余7条评论

6

试试这个:

public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
  float dX;
  float dY;
  int lastAction;

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

    final View dragView = findViewById(R.id.draggable_view);
    dragView.setOnTouchListener(this);
  }

  @Override
  public boolean onTouch(View view, MotionEvent event) {
    switch (event.getActionMasked()) {
      case MotionEvent.ACTION_DOWN:
        dX = view.getX() - event.getRawX();
        dY = view.getY() - event.getRawY();
        lastAction = MotionEvent.ACTION_DOWN;
        break;

      case MotionEvent.ACTION_MOVE:
        view.setY(event.getRawY() + dY);
        view.setX(event.getRawX() + dX);
        lastAction = MotionEvent.ACTION_MOVE;
        break;

      case MotionEvent.ACTION_UP:
        if (lastAction == MotionEvent.ACTION_DOWN)
          Toast.makeText(DraggableView.this, "Clicked!", Toast.LENGTH_SHORT).show();
        break;

      default:
        return false;
    }
    return true;
  }
}

还有XML:

<ImageButton
        android:id="@+id/draggable_view"
        android:background="@mipmap/ic_launcher"
        android:layout_gravity="bottom|right"
        android:layout_marginBottom="20dp"
        android:layout_marginEnd="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

您可以使任何视图具备可拖动和可点击功能。


5

根据 @ban-geoengineering 的回答,我进行了更新,实现了类似 Facebook 聊天气泡的左右重力及涟漪效果。由于在代码块中消耗了触摸事件,所以我创建了自定义点击监听器,以确保涟漪效果清晰可见。

    <com.sample.DraggableFloatingActionButton
    android:id="@+id/connect_to_support_fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_marginLeft="@dimen/spacing_10pt"
    android:layout_marginRight="@dimen/spacing_10pt"
    android:layout_marginBottom="@dimen/spacing_16pt"
    android:clickable="true"
    android:focusable="true"
    app:backgroundTint="@color/colorGreen"
    app:fabSize="normal"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:rippleColor="@color/colorWhite"
    app:srcCompat="@drawable/ic_live_support"
    app:tint="@color/colorWhite" />

package com.sample;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.OvershootInterpolator;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

public class DraggableFloatingActionButton extends FloatingActionButton implements View.OnTouchListener {
    CustomClickListener customClickListener;

    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;

    int viewWidth;
    int viewHeight;

    int parentWidth;
    int parentHeight;

    float newX;
    float newY;

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

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

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

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

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

        ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();

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

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

            return false; // not Consumed for ripple effect

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

            viewWidth = view.getWidth();
            viewHeight = view.getHeight();

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

            newX = motionEvent.getRawX() + dX;
            newX = Math.max(layoutParams.leftMargin, newX); // Don't allow the FAB past the left hand side of the parent
            newX = Math.min(parentWidth - viewWidth - layoutParams.rightMargin, newX); // Don't allow the FAB past the right hand side of the parent

            newY = motionEvent.getRawY() + dY;
            newY = Math.max(layoutParams.topMargin, newY); // Don't allow the FAB past the top of the parent
            newY = Math.min(parentHeight - viewHeight - layoutParams.bottomMargin, 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 (newX > ((parentWidth - viewWidth - layoutParams.rightMargin) / 2)) {
                newX = parentWidth - viewWidth - layoutParams.rightMargin;
            } else {
                newX = layoutParams.leftMargin;
            }

            view.animate()
                    .x(newX)
                    .y(newY)
                    .setInterpolator(new OvershootInterpolator())
                    .setDuration(300)
                    .start();

            if (Math.abs(upDX) < CLICK_DRAG_TOLERANCE && Math.abs(upDY) < CLICK_DRAG_TOLERANCE) { // A click
                if (customClickListener != null) {
                    customClickListener.onClick(view);
                }
                return false;// not Consumed for ripple effect
            } else { // A drag
                return false; // not Consumed for ripple effect
            }

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

    }

    public void setCustomClickListener(CustomClickListener customClickListener) {
        this.customClickListener = customClickListener;
    }

    public interface CustomClickListener {
        void onClick(View view);
    }

}

我试过,它可以工作。如何移动包含FAB图标的布局。 - Mahbubur Rahman Khan
可行的解决方案!@ban-geoengineering 的解决方案也有效,但是 Fab 没有自动拖出左/右位置。 - InsaneCat
你能否使该区域可移动(透明背景)并且可以响应触摸事件?现在该区域的移动会阻止其他应用程序接收到触摸事件。 - Zainal Fahrudin

3

所有提出的答案都使用了OnTouch监听器,这种方式近期Android API不推荐使用,因为它与辅助功能实现有关。请注意,startDrag()方法已经过时,开发人员应该改用startDragAndDrop()。

我的实现如下所示,使用OnDragListener():

  1. Define two global float variables dX and dY;
  2. Put the below snippet inside onCreatView() method, where root is root view, taken by the inflater (or any other view, which can receive Drop events);

    final FloatingActionButton fab = root.findViewById(R.id.my_fab);
    
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // Do whatever this button will do on click event
        }
    });
    
    root.setOnDragListener(new View.OnDragListener() {
        @Override
        public boolean onDrag(View v, DragEvent event) {
            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_LOCATION:
                    dX = event.getX();
                    dY = event.getY();
                    break;
                case DragEvent.ACTION_DRAG_ENDED:
                    fab.setX(dX-fab.getWidth()/2);
                    fab.setY(dY-fab.getHeight()/2);
                    break;
            }
            return true;
        }
    });
    
    
    fab.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            View.DragShadowBuilder myShadow = new View.DragShadowBuilder(fab);
            v.startDragAndDrop(null, myShadow, null, View.DRAG_FLAG_GLOBAL);
            return true;
        }
    });
    

很棒的解决方案。毫不费力地工作,无需调试。我唯一需要改变的是,在我的情况下,我不得不将它放在OnCreate中,而不是OnCreateView。 - Akito

0

你可以尝试像下面这样,只需在任何 View 上实现 onTouch

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


}

谢谢Omar。我一直在尝试这种方法,但没有成功。不过我已经有一些代码可以工作了,稍后会发布它。无论如何还是谢谢。 - ban-geoengineering
当我尝试这个时,我只在红色框空间内得到了一个可移动的fab。红色框是想象中的 https://i.stack.imgur.com/a5o9j.png - Subin Babu
@SubinBabu 我刚刚注意到你在两个不同的答案下发布了相同的评论。你能确认它适用于哪个答案吗?如果它适用于两个答案,请查看我在我的答案上刚刚留下的评论。此外,请确保您不要将Omar的Java代码与我的解决方案一起使用,因为这可能会破坏事情。干杯。 - ban-geoengineering

0
Android中函数生成浮动按钮
private static float dX,dY;
    private static float downRawX, downRawY;
    private final static float CLICK_DRAG_TOLERANCE = 10;

 public static void setfab(Activity activity){
            FloatingActionButton fab = new FlyyFloatingButton(activity);
            LinearLayout layout = new LinearLayout(activity);
            LinearLayout.LayoutParams parm = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            fab.setImageResource(R.drawable.ic_rewards);
            fab.setBackgroundTintList(ColorStateList.valueOf(Color.BLUE));
            fab.setFocusable(true);
            fab.setSize(FloatingActionButton.SIZE_AUTO);
            layout.addView(fab);
            View viewParent = (View) fab.getParent();
            activity.addContentView(layout,parm);
            fab.setOnTouchListener(new View.OnTouchListener() {
                @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 view.performClick();
                        }
                        else { // A drag
                            return true; // Consumed
                        }
    
                    }
                    else {
                        return view.onTouchEvent(motionEvent);
                    }
    
                }
            });
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context, "Hello Floating Action Button", Toast.LENGTH_SHORT).show();
                }
            });
        }

0

这是适用于我并且容差为70的监听器。

private class FloatingOnTouchListener implements View.OnTouchListener {
        private float x;
        private float y;
        private float nowX;
        private float nowY;
        private float downX;
        private float downY;
        private final int tolerance = 70;

        @Override
        public boolean onTouch(View view, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                x = (int) event.getRawX();
                y = (int) event.getRawY();
                downX = x;
                downY = y;
            } else
            if (event.getAction() == MotionEvent.ACTION_MOVE) {
                nowX = event.getRawX();
                nowY = event.getRawY();
                float movedX = nowX - x;
                float movedY = nowY - y;
                x = nowX;
                y = nowY;
                iconViewLayoutParams.x = iconViewLayoutParams.x + (int) movedX;
                iconViewLayoutParams.y = iconViewLayoutParams.y + (int) movedY;
                windowManager.updateViewLayout(view, iconViewLayoutParams);
            } else
            if (event.getAction() == MotionEvent.ACTION_UP) {
                float dx = Math.abs(nowX - downX);
                float dy = Math.abs(nowY - downY);
                if (dx < tolerance && dy < tolerance) {
                    Log.d(TAG, "clicou");
                    Log.d(TAG, "dx " + dx);
                    Log.d(TAG, "dy " + dy);
                    windowManager.removeViewImmediate(iconView);
                    windowManager.addView(displayView, layoutParams);
                } else {
                    Log.d(TAG, "dx " + dx);
                    Log.d(TAG, "dy " + dy);
                    return true;
                }
            }
            return true;
        }
    }

0

实际上,你可以使用android.support.design.widget.CoordinatorLayout代替RelativeLayout或其他任何布局,这样就可以移动FAB了。


1
嗨,Rohit,你是不是想把这个作为一条评论添加到现有的答案中,而不是作为一个新的答案?(在这种情况下,前者可能更合适。) - ban-geoengineering

0

在Java代码中可移动的浮动操作按钮

flBtnCallify.setOnTouchListener(new View.OnTouchListener() {
        float dX;
        float dY;
        float startX;
        float startY;
        int lastAction;
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getActionMasked()) {
                case MotionEvent.ACTION_DOWN:
                    dX = v.getX() - event.getRawX();
                    dY = v.getY() - event.getRawY();
                    startX = event.getRawX();
                    startY = event.getRawY();
                    lastAction = MotionEvent.ACTION_DOWN;
                    break;
                case MotionEvent.ACTION_MOVE:
                    v.setY(event.getRawY() + dY);
                    v.setX(event.getRawX() + dX);
                    lastAction = MotionEvent.ACTION_MOVE;
                    break;
                case MotionEvent.ACTION_UP:
                    if (Math.abs(startX - event.getRawX()) < 10 && Math.abs(startY - event.getRawY()) < 10){
                        Toast.makeText(v.getContext(), "Clicked!", Toast.LENGTH_SHORT).show();

                    }
                    break;
                default:
                    return false;
            }
            return false;
        }
    });

-1

这是稍微更新过的版本。它正确地处理了涟漪效果,至少对我来说是有效的。

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){
    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;
            return super.onTouchEvent(motionEvent);

        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();
            setPressed(false);
            return true;

        case MotionEvent.ACTION_UP:
            final float upRawX = motionEvent.getRawX();
            final float upRawY = motionEvent.getRawY();

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

            final boolean isDrag = Math.abs(upDX) >= CLICK_DRAG_TOLERANCE || Math.abs(upDY) >= CLICK_DRAG_TOLERANCE;
            return isDrag || performClick();

        default:
            return super.onTouchEvent(motionEvent);

    }
}

我将你的两个更改添加到我的代码中,但是 MFAB 不再移动。此外,我测试了原始的 com.google.android.material.floatingactionbutton.FloatingActionButton ,它似乎也没有任何涟漪效果。 - ban-geoengineering
我忘了提到我在xml中使用了android:background="?android:attr/selectableItemBackground"。 - Samuel
我的帖子中少了一个问号...请再试一次,使用?android:attr/selectableItemBackground。 - Samuel
谢谢。现在编译通过了,但是无论是使用FAB还是MFAB都没有涟漪效果。 - ban-geoengineering
我真的不知道为什么它对你不起作用。尝试手动在xml中设置涟漪颜色。我使用这段代码并保证它是有效的... - Samuel
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接