Подвижная плавающая кнопка движется за пределы экрана - PullRequest
0 голосов
/ 08 января 2020

В моем проекте я реализовал подвижную плавающую кнопку, но она выходит за пределы экрана, когда выходит за угол. Я хочу, чтобы это соблюдало границы экрана. Пожалуйста, помогите мне с реализацией.

 fab.setOnTouchListener(new View.OnTouchListener() {
        float startX;
        float startRawX;
        float distanceX;
        int lastAction;

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

                case MotionEvent.ACTION_MOVE:
                    view.setX(event.getRawX() + startX);
                    view.setY(event.getRawY() + startX);

                    lastAction = MotionEvent.ACTION_MOVE;
                    break;

                case MotionEvent.ACTION_UP:
                    distanceX = event.getRawX()-startRawX;
                    if (Math.abs(distanceX)< 10){
                    ScanQRcode();                        }
                    break;
                case MotionEvent.ACTION_BUTTON_PRESS:

                default:
                    return false;
            }
            return true;
        }
    });

Ответы [ 2 ]

0 голосов
/ 08 января 2020

Чтобы достичь того, что вы пытаетесь сделать, нужно выполнить несколько шагов:

Прежде всего вам нужно знать высоту и ширину обрабатываемой области, в пределах которой свободно перемещается плавающая кнопка. Для этого вы можете сделать что-то вроде этого:

int screenHeight, screenWidth;

root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                root.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                screenHeight = root.getHeight();
                screenWidth = root.getWidth();
            }
        }); 

Здесь root - это родительское представление, в пределах которого может свободно перемещаться плавающая кнопка. Вы можете поместить этот код в onCreate вашей активности

Далее вам нужно вычислить радиус вашей плавающей кнопки. Это можно сделать примерно так:

int center;

Rect rectf = new Rect();
        fab.getGlobalVisibleRect(rectf);

        int height = rectf.height();
        int width = rectf.width();

        center = width/2;        

Вуаля, теперь у вас есть нужные вам номера. Все, что вам теперь нужно сделать, это установить onTouchListener на кнопку fab и в MotionEvent.ACTION_MOVE проверить, равна ли центральная координата вашей кнопки + ее радиус равным или превышает ширину экрана или отрицательную (при горизонтальном перемещении) или координату центра + это радиус превышает высоту экрана или отрицательный (при вертикальном перемещении). В любом из этих случаев просто переместите фабрику назад влево, вправо, сверху или снизу, в зависимости от обстоятельств. Например: если fab перемещался вверх и достигал 0 x координаты (я рассматриваю весь экран как подвижную область), тогда мы можем установить x-cordinate fab равным ширине вида fab, деленной на 2, чтобы id не не двигайтесь над подвижной областью экрана.

Аналогичные логи c могут быть применены, чтобы удерживать потрясающую кнопку от перемещения влево, вправо или вниз от родителя. Удачи!

0 голосов
/ 08 января 2020

проверьте ниже класс и его XML

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 MovableFloatingActionButton

 <com.example.MovableFloatingActionButton
        android:id="@+id/btnFab"
        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"/>
...