Setting ontouchlistener on multiple dynamic buttons with flow layout

282 Views Asked by At

I am using flow layout from reference https://github.com/ApmeM/android-flowlayout .Now i am creating multiple dynamic buttons on this layout and setting ontouchlistener on them.The problem is that when i am changing the position of one button by touching, other buttons are also changing there position.I want to change the position of only button that i am touching.Is there any way to do that or other solution.

public class MainActivity extends AppCompatActivity implements    View.OnTouchListener {
          Button floatButton;
        Button _view;
        private int _xDelta;
        private int _yDelta;
        ViewGroup layout;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main2);
            Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
            layout = (ViewGroup) findViewById(R.id.flowLayout);
            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT
                    , ViewGroup.LayoutParams.WRAP_CONTENT);
            layoutParams.leftMargin = 50;
            layoutParams.topMargin = 50;
            layoutParams.bottomMargin = 0;
            layoutParams.rightMargin = 0;
            for (int i = 0; i < 10; i++) {
                _view = new Button(this);
                _view.setText("Button"+(i+1));
                _view.setLayoutParams(layoutParams);
               _view.setOnTouchListener(this);
                layout.addView(_view);
            }
        }
        public boolean onTouch(View view, MotionEvent event) {
            final int X = (int) event.getRawX();
            final int Y = (int) event.getRawY();
            try {
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:

                        FlowLayout.LayoutParams lParams = (FlowLayout.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:
                        FlowLayout.LayoutParams layoutParams = (FlowLayout.LayoutParams) view.getLayoutParams();
                        layoutParams.leftMargin = X - _xDelta;
                        layoutParams.topMargin = Y - _yDelta;
                        layoutParams.rightMargin = 0;
                        layoutParams.bottomMargin = 0;
                        view.setLayoutParams(layoutParams);
                        break;
                }
            }catch (Exception ex){
                Log.d("ON Touch ", ex.toString());
            }
            layout.invalidate();
            return true;
        }
    }
2

There are 2 best solutions below

3
On

More than likely this is happening because you are using a RelativeLayout and the other object positions are somehow defined relative to the button you are moving. If this is the case, then the behavior you describe is expected. But we need to see the XML file to know exactly what is going on.

0
On

you can use 2 layouts and apply OnTouchListener for each in one Activity. Here is my example:- floating_View.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:id="@+id/thisIsAnID"
        android:layout_width="44dp"
        android:layout_height="124dp"
        android:background="#BB000000"
        android:orientation="vertical">
        <ToggleButton
            android:id="@+id/toggl"
            android:layout_width="44dp"
            android:layout_height="40dp"
            android:scaleX="1.4"
            android:scaleY="1.2"
            android:background="@drawable/toggle_selector"
            android:textOff=""
            android:textOn="" />
        <Button
            android:id="@+id/stop"
            android:layout_width="44dp"
            android:layout_height="40dp"
            android:text=""
            android:background="@drawable/ic_baseline_close_24"/>

        <View
            android:id="@+id/view1"
            android:layout_width="44dp"
            android:layout_height="40dp"
            android:text=""
            android:scaleX="0.9"
            android:scaleY="0.9"
            android:background="@drawable/ic_baseline_open_with_24"/>
    </LinearLayout>
</FrameLayout>

pointer_view.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <View
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:background="@drawable/ic_outline_adjust_24"
        android:id="@+id/pointerr"
        android:scaleX="1.1"
        android:scaleY="1.1"
        android:layout_gravity="center_horizontal"/>
</FrameLayout>

And the main File FloatingView.java which is using above two layouts

public class FloatingView extends Service {
    private WindowManager mWindowManager;
    private WindowManager mWindowManager2;
    private View myFloatingView;
    private View myFloatingView2;
    @Override
    public void onCreate() {
        super.onCreate();
        ////getting the widget layout from xml using layout inflater ...dynamic layout use inflater
        myFloatingView= LayoutInflater.from(this).inflate(R.layout.floating_view,null);
        myFloatingView2=LayoutInflater.from(this).inflate(R.layout.pointer_view,null);
        
        final WindowManager.LayoutParams parmss=  new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,//width
                WindowManager.LayoutParams.WRAP_CONTENT,//height
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,//type
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,//flags
                PixelFormat.TRANSLUCENT//format
        );
        final WindowManager.LayoutParams parmss2= new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                PixelFormat.TRANSLUCENT
        );
        //specify the view position
        parmss.gravity= Gravity.CENTER | Gravity.LEFT;
        parmss.x=5;
        parmss.y=50;
        parmss2.gravity=Gravity.CENTER | Gravity.CENTER;
        //getting windows services and adding the floating view to it
        mWindowManager=(WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager2=(WindowManager)getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(myFloatingView,parmss);
        mWindowManager2.addView(myFloatingView2,parmss2);
        myFloatingView.findViewById(R.id.thisIsAnID).setOnTouchListener(new View.OnTouchListener() {
            private int initialX;
            private int initialY;
            private float initialTouchX;
            private float initialTouchY;
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        //remember the initial position.
                        initialX=parmss.x;
                        initialY= parmss.y;
                        //get the touch location
                        initialTouchX=event.getRawX();
                        initialTouchY=event.getRawY();
                        return true;
                    case MotionEvent.ACTION_UP:
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        float Xdiff= Math.round(event.getRawX()-initialTouchX);
                        float Ydiff= Math.round(event.getRawY()-initialTouchY);
                        //Calculate the X and Y coordinates of the view.
                        parmss.x=initialX+(int)Xdiff;
                        parmss.y=initialY+(int)Ydiff;
                        //Update the layout with new X & Y coordinates
                        mWindowManager.updateViewLayout(myFloatingView,parmss);
                        return true;
                }
                return false;
            }
        });
        myFloatingView2.findViewById(R.id.pointerr).setOnTouchListener(new View.OnTouchListener() {
            private int initialX;
            private int initialY;
            private float initialTouchX;
            private float initialTouchY;
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        //remember the initial position.
                        initialX=parmss2.x;
                        initialY= parmss2.y;
                        //get the touch location
                        initialTouchX=event.getRawX();
                        initialTouchY=event.getRawY();
                        return true;
                    case MotionEvent.ACTION_UP:
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        float Xdiff= Math.round(event.getRawX()-initialTouchX);
                        float Ydiff= Math.round(event.getRawY()-initialTouchY);
                        //Calculate the X and Y coordinates of the view.
                        parmss2.x=initialX+(int)Xdiff;
                        parmss2.y=initialY+(int)Ydiff;
                        //Update the layout with new X & Y coordinates
                        mWindowManager2.updateViewLayout(myFloatingView2,parmss2);
                        return true;
                }
                return false;
            }
        });
    }
}