user5894647
user5894647

Reputation: 554

Dragging and dropping dynamically added edit text views

I have relative layout which consists of a button

When I press this button it adds the new custom edittext that I have created to the relative layout

These custom edit text can be dragged and dropped anywhere in the layout. This part of the code works fine.

The problem is :: When I add the first custom edit text and reposition it by dragging it and adding another custom edittext the app works weird not as expected( the two custom edittext overlap each other).

For a better understanding of my problem watch this video

Instead of custom edit text I have tried the same code with textviews and its working fine you can watch this video for the textviews samplehere

Maybe it's due to the setting of on long click listener to my custom edit text in the onclick listener of the button

my main activity

public class MainActivity extends Activity 
{


TextView X, Y;

RelativeLayout dropLayout;
LayoutParams params;
Button addText;

@Override
protected void onCreate(Bundle savedInstanceState)
{

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);


    dropLayout = (RelativeLayout) findViewById(R.id.ondraglayout);  
    dropLayout.setOnDragListener(new MyDragListener());
     addText = (Button) findViewById(R.id.mainButton1);
    addText.setOnClickListener(new MyButtonClickListener());



    X=(TextView) findViewById(R.id.xvalue);
    Y=(TextView) findViewById(R.id.yvalue);


    dropLayout.setOnTouchListener(new OnTouchListener(){

            @Override
            public boolean onTouch(View p1, MotionEvent event)
            {
                switch(event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        int x=(int) event.getX();
                        int y=(int) event.getY();
                        X.setText("x coord is " + x);
                        Y.setText("y coord is " + y);
                        break;

                    case MotionEvent.ACTION_MOVE:
                        x=(int) event.getX();
                        y=(int) event.getY();
                        X.setText("x coord is " + x);
                        Y.setText("y coord is " + y);
                        break;
                }
                return true;
            }


    });
}




   }

my clicklistener

public class MyButtonClickListener implements OnClickListener
 {

@Override
public void onClick(View v)
{
    ViewGroup relativeParent = (ViewGroup) v.getParent();
    CustomEdittext edttxt = new CustomEdittext(v.getContext());
    relativeParent.addView(edttxt);
    edttxt.setOnLongClickListener(new MyLongClickListener());

}

  }

** MyLongClickListner **

public class MyLongClickListner implements OnLongClickListener
 {

@Override
public boolean onLongClick(View v)
{

    ClipData dragdata = ClipData.newPlainText("","");

    View.DragShadowBuilder shdwbldr = new View.DragShadowBuilder(v);

    v.startDrag(dragdata, shdwbldr, v, 0);
    v.setVisibility(View.INVISIBLE);

    return true;
}

   }

my draglistener

public class MyDragListener implements OnDragListener
 {

private LayoutParams params;

@Override
public boolean onDrag(View v, DragEvent event)
{
    View view = (View) event.getLocalState();


    switch(event.getAction())
    {
        case DragEvent.ACTION_DRAG_STARTED:

            params = (RelativeLayout.LayoutParams) view.getLayoutParams();  
            break;

        case DragEvent.ACTION_DRAG_ENTERED:
            int x = (int) event.getX();
            int y = (int) event.getY();

            break;

        case DragEvent.ACTION_DRAG_EXITED :

            break;

        case DragEvent.ACTION_DRAG_LOCATION  :
            x=  (int) event.getX();
            y =  (int) event.getY();
            break;

        case DragEvent.ACTION_DRAG_ENDED   :

            break;

        case DragEvent.ACTION_DROP:

            x = (int) event.getX();
            y = (int) event.getY();
            params.leftMargin = x;
            params.topMargin = y;

            view.setLayoutParams(params);
            view.setVisibility(View.VISIBLE);

            break;
        default: break;
    }
    return true;
}


 }

my custom edit text

public class CustomEdittext extends EditText
 {

Paint paint;

public CustomEdittext(Context context){
    super(context);
    init();


}

public CustomEdittext(Context context, AttributeSet attr){
    super(context, attr);

    init();

}   


public void init(){
    paint = new Paint();

    paint.setAntiAlias(true);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(4);
    paint.setColor(Color.BLUE);




}

@Override
protected void onDraw(Canvas canvas)
{

    super.onDraw(canvas);

    canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
}


  }

my main xml

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#CDC2C0"
android:id="@+id/ondraglayout">



<TextView
    android:layout_height="wrap_content"
    android:text="Large Text"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:layout_width="wrap_content"
    android:layout_alignParentBottom="true"
    android:id="@+id/yvalue"/>

<TextView
    android:layout_height="wrap_content"
    android:text="Large Text"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:layout_width="wrap_content"
    android:layout_above="@id/yvalue"
    android:id="@+id/xvalue"/>

<Button
    android:layout_height="wrap_content"
    android:text="T"
    android:layout_width="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:id="@+id/mainButton1"/>

  </RelativeLayout>

Upvotes: 2

Views: 4054

Answers (1)

vibhor_shri
vibhor_shri

Reputation: 374

Alright, after some research i got this working. Here is the implementation, made a few changes from your initial approach.

Firstly, i've changed you xml to some extent.

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ondraglayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#CDC2C0"
    android:orientation="vertical">


    <RelativeLayout
        android:id="@+id/dropLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/xvalue">

    </RelativeLayout>


    <TextView
        android:id="@+id/yvalue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/xvalue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/yvalue"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <Button
        android:id="@+id/mainButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:text="T" />

</RelativeLayout>

I hope it is fine.

Secondly, as you can see in the xml, another empty layout has been added. The dropLayout is where we will drop the items. In your activity, reference this layout, then set the drag listener on it.

dropLayoutNew.setOnDragListener(dragListener);
dropLayoutNew.setOnTouchListener(otl);

The on touch listener is below, i commented out your implementation:

private View.OnTouchListener otl = new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
        return true; // the listener has consumed the event
    }
};

This is in the same activity, ie the MainActivity. Now, as for the last change i've made. I have created the on drag listener within the MainActivity itself, because i was somehow not able to debug that portion of code,the drag listener from another class(separate issue). So, for the drag listener, paste the below code in your MainActivity.

View.OnDragListener dragListener = new View.OnDragListener() {
    @Override
    public boolean onDrag(View v, DragEvent event) {
        View view = (View) event.getLocalState();
        ViewGroup vg = (ViewGroup) v.getParent();
        RelativeLayout rl = (RelativeLayout)vg.findViewById(R.id.dropLayout);


        switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED:

                params = (RelativeLayout.LayoutParams) view.getLayoutParams();


                break;

            case DragEvent.ACTION_DRAG_ENTERED:
                int x = (int) event.getX();
                int y = (int) event.getY();

                break;

            case DragEvent.ACTION_DRAG_EXITED:

                break;

            case DragEvent.ACTION_DRAG_LOCATION:
                x = (int) event.getX();
                y = (int) event.getY();
                break;

            case DragEvent.ACTION_DRAG_ENDED:

                break;

            case DragEvent.ACTION_DROP:

                int childCountDropped = rl.getChildCount();
                System.out.println("Child Count of Views::::::Dropped" + childCountDropped);

                x = (int) event.getX();
                y = (int) event.getY();
                params.leftMargin = x;
                params.topMargin =  y;

                view.setLayoutParams(params);
                view.setVisibility(View.VISIBLE);

                break;
            default:
                break;
        }
        return true;
    }
};

You can see some code added, but it does not change ur implementation. I wanted to check number of child items in the Relative Layout. I initially thought that it will give me a clear idea about the target layout(where items are being dropped). None the less, this is now working as you wanted. I checked it on a nexus 5 emulator, running 6.0. Do check it for other versions as well.

Conclusion: I am not sure as to why the drag listener was not working when referenced from another class, but none the less, it is working as you wanted now. The onTouchListener, again, you had a different implementation from mine. Maybe we will have to look into some more details on that. The main diff i did was to change the drop layout, you were doing it on the parent, i did it on another child. Rest mostly its the same. I would recommend to try out some other implementation as well, share with us the result.

I hope this code helps, let me know if this does not work.

Upvotes: 3

Related Questions