Как разрешить клики только внутри круга плавающей кнопки действия?

Это потрясающие размеры, соответствующие спецификациям Google. введите здесь описание изображения

В моем случае приложения мне нужен прослушиватель кликов, который срабатывает, щелкая только по кругу FAB, избегая щелчков внутри квадратного контейнера (56x56).

Я уже думал о том, чтобы получить X, Y в каждом событии onClick в моей «всей» кнопке, а затем проверить, находится ли он внутри круга моего Fab, но я хотел бы избежать этого обходного пути, потому что это может вызвать проблемы с точностью клика с различными разрешениями устройств. .

У вас есть идеи для альтернативного решения?

Заранее спасибо.

РЕДАКТИРОВАТЬ:

Я фактически реализовал это решение javascript, переведенное на Java
ССЫЛКА
Как вы думаете, я всегда буду получать одинаковую точность при изменении экрана устройства?


person Nicolò    schedule 28.10.2016    source источник
comment
Вы могли бы просто использовать две кнопки, поместив одну на вершине фабрики...   -  person Dportology    schedule 28.10.2016
comment
У меня такая же проблема с кнопкой с нестандартной овальной формой. В любом случае onClick запускается в поле... Так что, я полагаю, дело не только в плавающих кнопках действий, но и в макетах в целом. Похоже, они должны быть только в квадрате..   -  person Nicolò    schedule 28.10.2016


Ответы (1)


Я не думаю, что есть способ создать интерактивную область, отличную от прямоугольной. Вы должны сделать свою плавающую кнопку шириной и высотой, установленной на wrap_content, если ваш круг является изображением. В любом случае вы должны установить его ширину и высоту, чтобы они соответствовали диаметру круга. И обработайте событие следующим образом:

    view.setOnTouchListener(new View.OnTouchListener() {
                                @Override
                                public boolean onTouch(View v, MotionEvent event) {
                                    ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
                                    float radius = layoutParams.width / 2f;
                                    float x = event.getX() - radius;
                                    float y = event.getY() - radius;
                                    if (isInCircle(radius, x, y)) {
                                        if (event.getAction() == MotionEvent.ACTION_DOWN) {
                                            // perform your action
                                        }
                                        return true;
                                    } else {
                                        return false;
                                    }
                                }

                                private boolean isInCircle(float radius, float x, float y) {
                                    if (Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) < radius) {
                                        //touch was performed inside the circle;
                                        return true;
                                    } else {
                                        //touched ouside the circle
                                        return false;
                                    }
                                }
                            }
    );

Это будет работать на любом устройстве, если ваша кнопка плотно обернута вокруг нарисованного круга.

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

    view.setOnTouchListener(new View.OnTouchListener() {
                                @Override
                                public boolean onTouch(View v, MotionEvent event) {
                                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                                        ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
                                        float radius = layoutParams.width / 2f;
                                        float x = event.getX() - radius;
                                        float y = event.getY() - radius;
                                        if (isInCircle(radius, x, y)) {
                                            // perform your action
                                        }
                                    }
                                    return true;
                                }

                                private boolean isInCircle(float radius, float x, float y) {
                                    if (Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) < radius) {
                                        //touch was performed inside the circle;
                                        return true;
                                    } else {
                                        //touched ouside the circle
                                        return false;
                                    }
                                }
                            }
    );

Имейте в виду, что для этого ваша кнопка должна быть строго прямоугольной. если вы хотите, чтобы кнопка была эллипсом, математика должна быть другой.

person Timur Gorchag    schedule 28.10.2016