问题
I'm trying to create a form in which the user can move inputs around. I have an editText and want it to be able to move it to a new location in my relativeLayout. I am able to pick it up and move it around, but once I let go, it disappears completely. I've tried pretty much everything. I think the onDrag method may not ever be called because my logs never show up. Also, after a let go of my editText, I get this error message in logcat: Reporting drop result: false
Another issue I've been having is that when you tap the editText, it think I'm trying to drag it meaning I can't actually change the text inside it.
Any help is appreciated! Thanks!
Here is my relative layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
xmlns:app = "http://schemas.android.com/apk/res-auto"
xmlns:tools = "http://schemas.android.com/tools"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:paddingBottom = "@dimen/activity_vertical_margin"
android:paddingLeft = "@dimen/activity_horizontal_margin"
android:paddingRight = "@dimen/activity_horizontal_margin"
android:paddingTop = "@dimen/activity_vertical_margin"
app:layout_behavior = "@string/appbar_scrolling_view_behavior"
tools:context = "com.supercilex.myapp.NewForm"
tools:showIn = "@layout/activity_new_form"
android:id="@+id/relativeLayout">
<EditText
android:id = "@+id/editText"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_alignParentStart = "true"
android:layout_alignParentTop = "true"
android:ems = "10"
android:hint = "Enter some text"
android:inputType = "textPersonName" />
</RelativeLayout>
Here is my class:
import android.content.ClipData;
import android.content.ClipDescription;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
import common.FileManagement;
public class NewForm extends AppCompatActivity
{
private static EditText editText;
private android.widget.RelativeLayout.LayoutParams layoutParams;
String msg;
@Override
protected void onCreate ( Bundle savedInstanceState )
{
super.onCreate ( savedInstanceState );
setContentView ( R.layout.activity_new_form );
Toolbar toolbar = ( Toolbar ) findViewById ( R.id.toolbar );
setSupportActionBar ( toolbar );
editText = ( EditText ) findViewById ( R.id.editText );
FileManagement fileManagement = new FileManagement ();
editText.setText ( fileManagement.read ( "textViewData", getApplicationContext () ) );
FloatingActionButton fab = ( FloatingActionButton ) findViewById ( R.id.fab );
fab.setOnClickListener ( new View.OnClickListener ()
{
@Override
public void onClick ( View view )
{
FileManagement fileManagement = new FileManagement ();
String tmpEditText = editText.getText ().toString ();
MainActivity.textView.setText ( tmpEditText );
fileManagement.save ( "textViewData", tmpEditText, getApplicationContext () );
finish ();
}
} );
editText.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());
String[] mimeTypes = { ClipDescription.MIMETYPE_TEXT_PLAIN};
ClipData dragData = new ClipData(v.getTag().toString(),mimeTypes, item);
View.DragShadowBuilder myShadow = new View.DragShadowBuilder(editText);
v.startDrag(dragData,myShadow,null,0);
return true;
}
});
editText.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
switch(event.getAction())
{
case DragEvent.ACTION_DRAG_STARTED:
layoutParams = (RelativeLayout.LayoutParams)v.getLayoutParams();
Log.d(msg, "Action is DragEvent.ACTION_DRAG_STARTED");
return true;
case DragEvent.ACTION_DRAG_ENTERED:
Log.d(msg, "Action is DragEvent.ACTION_DRAG_ENTERED");
int x_cord = (int) event.getX();
int y_cord = (int) event.getY();
return true;
case DragEvent.ACTION_DRAG_EXITED :
Log.d(msg, "Action is DragEvent.ACTION_DRAG_EXITED");
x_cord = (int) event.getX();
y_cord = (int) event.getY();
layoutParams.leftMargin = x_cord;
layoutParams.topMargin = y_cord;
v.setLayoutParams(layoutParams);
return true;
case DragEvent.ACTION_DRAG_LOCATION :
Log.d(msg, "Action is DragEvent.ACTION_DRAG_LOCATION");
x_cord = (int) event.getX();
y_cord = (int) event.getY();
return true;
case DragEvent.ACTION_DRAG_ENDED :
Log.d ( msg, "Action is DragEvent.ACTION_DRAG_ENDED" );
return true;
case DragEvent.ACTION_DROP:
Log.d( msg, "ACTION_DROP event");
return true;
default:
break;
}
return true;
}
});
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(editText);
editText.startDrag(data, shadowBuilder, editText, 0);
editText.setVisibility(View.INVISIBLE);
return true;
}
else
{
return false;
}
}
});
}
}
I've also tried my onDrag method with break;
instead of return true;
And I've tried it this way:
public boolean onDrag(View v, DragEvent event) {
switch(event.getAction())
{
case DragEvent.ACTION_DRAG_STARTED:
break;
case DragEvent.ACTION_DRAG_ENTERED:
break;
case DragEvent.ACTION_DRAG_EXITED :
break;
case DragEvent.ACTION_DRAG_LOCATION :
break;
case DragEvent.ACTION_DRAG_ENDED :
break;
case DragEvent.ACTION_DROP:
View view = (View) event.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
owner.removeView(view);
FrameLayout container = (FrameLayout) v;
container.addView(view);
view.setVisibility(View.VISIBLE);
Log.d( msg, "ACTION_DROP event");
break;
default:
break;
}
return true;
}
Edit: Here is my updated code:
Above onCreate()
private EditText editText;
private RelativeLayout.LayoutParams layoutParams;
The rest:
findViewById(R.id.yourlayoutname).setOnDragListener( new View.OnDragListener()
{
@Override
public boolean onDrag ( View v, DragEvent event )
{
if ( event.getAction() == DragEvent.ACTION_DROP )
{
int xCord = ( int ) event.getX();
int yCord = ( int ) event.getY();
int height = editText.getHeight();
int width = editText.getWidth();
layoutParams.leftMargin = xCord - width;
layoutParams.topMargin = yCord - height;
editText.setLayoutParams( layoutParams );
}
return true;
}
});
editText.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
String[] mimeTypes = { ClipDescription.MIMETYPE_TEXT_PLAIN};
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(editText);
v.startDrag( data, shadowBuilder, mimeTypes, 0);
return true;
}
} );
editText.setOnDragListener( new View.OnDragListener()
{
@Override
public boolean onDrag ( View v, DragEvent event )
{
if ( event.getAction() == DragEvent.ACTION_DRAG_STARTED )
{
layoutParams = ( RelativeLayout.LayoutParams ) v.getLayoutParams();
}
return true;
}
} );
回答1:
I get this error message in logcat: Reporting drop result: false
It's not error message. It's mean that the Action drop not returned true
as result by the View
DragListener
.
Your EditText
disappear because you set it invisiblity to View.INVISIBLE
inside your onTouchListener
and never changed it back.
try this: First choose if you want to Drag by Touch or by Long Click. You don't need both. Let's say you decided to do it by touch:
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(editText);
editText.startDrag(data, shadowBuilder, editText, 0);
editText.setVisibility(View.INVISIBLE);
return true;
}
else
{
return false;
}
}
});
Remove all the reduntant code from the code Listener, no need it to the Drag as the system handle the drag for you. If you want the coordinations of the Drop to be the new location of the EditText
than you need to assign DragListener
to the EditText
container RelativeLayout
and retrieve them in `ACTION_DROP. If not:
editText.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
if (event.getAction == DragEvent.ACTION_DRAG_STARTED){
layoutParams = (RelativeLayout.LayoutParams)v.getLayoutParams();
} else if (event.getAction() == DragEvent.ACTION_DRAG_ENDED)
v.setVisibility(View.VISIBLE)
return true;
}
});
For getting the drop location you need something like that:
findViewById(R.id.relativeLayout).setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
if (event.getAction() == DragEvent.ACTION_DRAG_DROP){
int x_cord = (int) event.getX();
int y_cord = (int) event.getY();
layoutParams.leftMargin = x_cord;
layoutParams.topMargin = y_cord;
editText.setLayoutParams(layoutParams);
}
return true;
}
});
来源:https://stackoverflow.com/questions/33664512/android-after-drop-edittext-that-was-being-dragged-disapears