简体   繁体   中英

How to allow clicks inside Floating Action Button's circle only?

These are the FAB dimensions following google specs. 在此处输入图片说明

In my application case I need a click listener which is fired by clicking in the FAB's circle only, avoiding clicks inside the square container (56x56).

I was already thinking about get X,Y in each onClick event in my "entire" button and then verify if it's inside my Fab's circle, but i would like to escape from this workaround because it could cause accuracy-click problems with different devices resolutions.

Do you have any idea for an alternative solution?

Thanks in advance.

EDIT:

I've actually implemented this javascript-solution translated in Java
LINK
Do you think i will always get the same accuracy on device screen changes?

I don't think there is a way to actually make a clickable area other than rectangular. You should make your floating button have a width and height set to wrap_content if your circle is an image. Any way you should set it's width and height to match the diameter of the circle. And process the event like this:

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

This will work on any device, as long as your button is tightly wrapped around your drawn circle.

If you don't need the touch event falling deeper, under your floating button when you miss the circle, you can avoid some redundant calculations like this:

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

Keep in mind that for this to work your button should be strictly rectangular. if you want a button to be an ellipse the math should be different.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM