Android draggable hover button

Recently, the project needs to use drag and drop hover buttons, so a small demo is implemented

Because of the simulator, it looks a bit stuck when dragging. If it runs on the real machine, it is perfect

The difficulties to be overcome in technology are as follows:

1 how to suspend? Use relative layout or frame layout, and put the button on the outermost layer
2 how to drag? Carry out mobile monitoring on the button, and dynamically modify the position of the button display
3 how to limit the drag position? Judgement boundary
4 see code for how to handle click event and scroll event respectively


This class is an abstract class to separate the mobile from the concrete business. This class provides movable properties. The specific implementation should be isolated and handed over to the implementation class for completion
Cannot inherit ViewGroup directly!!!


import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

 * Drag the hover button abstract class. Note that you must inherit the implementation class of ViewGroup instead of directly inheriting ViewGroup
 * By  Jie  2018/8/30
public abstract class AbastractDragFloatActionButton extends RelativeLayout {
    private int parentHeight;//Suspended parent layout height
    private int parentWidth;

    public AbastractDragFloatActionButton(Context context) {
        this(context, null, 0);

    public AbastractDragFloatActionButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);


    public abstract int getLayoutId();

    public abstract void renderView(View view);

    public AbastractDragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        View view= LayoutInflater.from(context).inflate(getLayoutId(), this);
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        View view = getChildAt(0);

    private int lastX;
    private int lastY;

    private boolean isDrag;

    public boolean onTouchEvent(MotionEvent event) {
        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                setPressed(true);//The default is click event
                isDrag=false;//Click event instead of drag by default
                getParent().requestDisallowInterceptTouchEvent(true);//Parent layout does not block listening of child layout
                ViewGroup parent;
                    parent= (ViewGroup) getParent();
            case MotionEvent.ACTION_MOVE:
                isDrag = (parentHeight > 0 && parentWidth > 0);//You can only drag if the parent layout exists
                if(!isDrag) break;

                int dx=rawX-lastX;
                int dy=rawY-lastY;
                //Here, some Huawei mobile phones can't trigger the click event
                int distance= (int) Math.sqrt(dx*dx+dy*dy);
                isDrag = distance>0;//Only displacement greater than 0 indicates dragging
                if(!isDrag) break;

                float x=getX()+dx;
                float y=getY()+dy;
                //Check whether it reaches the top left and bottom right of the edge
            case MotionEvent.ACTION_UP:
                //If it is a drag state, it is not a click press event

        //If it is not a drag, then this event will not be consumed, so as not to affect the handling of the click event
        //Drag events to consume by yourself
        return isDrag || super.onTouchEvent(event);



For specific business classes, you can get the layout of your button s here

public class MyButton extends AbastractDragFloatActionButton {
    public MyButton(Context context) {

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);

    public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

    public int getLayoutId() {
        return R.layout.custom_button;//Get your own floating layout

    public void renderView(View view) {
          //Initialize those layouts

MainActivity use

public class MainActivity extends AppCompatActivity {

    private MyButton button;

    protected void onCreate(Bundle savedInstanceState) {
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"It's live!",Toast.LENGTH_SHORT).show();

    private void initView() {
        button = findViewById(;

Finally, I would like to thank Jane for her inspiration Android draggable suspension button 2 , there is adsorption effect in the article. If it is needed in the project, please refer to the following~

Tags: Android Mobile simulator

Posted on Wed, 01 Jan 2020 08:46:54 -0500 by nemethpeter