У меня возникла эта проблема (проблема) при выдаче события перетаскивания внутри целевого контейнера, содержащего editText . Чтобы воспроизвести эту проблему, я создал следующий пример:
1) Создал линейный макет (ll_container) в качестве целевого контейнера
2) Внутри макета выше, я создал четыре editTexts:
- EditText, который является фокусируемым
- EditText, который не фокусируется
- EditText с набором
DragListener
(рассматривается как еще одна цель перетаскивания) - Пользовательский editText с
onDragEvent()
, установленным так, чтобы всегда возвращать false
3) В качестве элемента перетаскивания я создал плавающую кнопку действия.
4) Событие перетаскивания начинается последолго нажимая на вышеупомянутый потрясающий. Событие перетаскивания передает данные в виде текста (в данном случае сообщения «Утечка данных!») .
public static void startDrag(View view) {
ClipData clipData = ClipData.newPlainText("", "Data Leaked!");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
view);
view.startDrag(clipData, shadowBuilder, view, 0);
}
5) В процессе события перетаскивания и при наведении курсора на вышеуказанные значения editTexts наблюдается (соответственно) :
Целевой контейнер (ll_container) теряет контроль над событием отбрасывания. EditText фокусируется, и если я удаляю цель (fab), данные, передаваемые в событии перетаскивания, устанавливаются в editText (, который не является целью перетаскивания ). Это не ожидается .
То же, что и в первом случае, но editText не фокусируется. Этого не ожидается .
EditText будет рассматриваться как еще одна цель отбрасывания. Удаление цели (fab) не приведет к утечке переданных данных. Ожидаемое поведение .
EditText не сфокусирован. Целевой контейнер (ll_container) по-прежнему контролирует событие сброса, и если цель отброшена (fab), утечки данных не произойдет. Ожидаемое поведение .
Вопросы :
- Это нормальное (стандартное) поведение editText впроцесс события перетаскивания?
- Если это поведение по умолчанию, могу ли я остановить это поведение (как в случае 4), не создавая пользовательский editText (переопределяя
onDragEvent()
)?
Пример
MainActivity.class:
public class MainActivity extends AppCompatActivity {
private final String TAG = MainActivity.class.getSimpleName();
private LinearLayout ll_container;
private EditText edt;
private EditText edt1;
private EditText edt2;
private EditText edt3;
private FloatingActionButton fab_item;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll_container = (LinearLayout) findViewById(R.id.ll_container);
ll_container.setOnDragListener(getOnDragListener());
edt = (EditText) findViewById(R.id.edt);
edt1 = (EditText) findViewById(R.id.edt1);
edt2 = (EditText) findViewById(R.id.edt2);
edt2.setOnDragListener(getOnDragListener());
edt3 = (EditText) findViewById(R.id.edt3);
fab_item = (FloatingActionButton) findViewById(R.id.fab_item);
fab_item.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
edt.setText("");
edt1.setText("");
edt2.setText("");
edt3.setText("");
edt.clearFocus();
edt1.clearFocus();
edt2.clearFocus();
edt3.clearFocus();
startDrag(fab_item);
return true;
}
});
}
public static void startDrag(View view) {
ClipData clipData = ClipData.newPlainText("", "Data Leaked!");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
view);
view.startDrag(clipData, shadowBuilder, view, 0);
}
public View.OnDragListener getOnDragListener() {
View.OnDragListener onDragListener = new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
Drawable enterShape = getResources()
.getDrawable(R.drawable.enter_shape);
Drawable normalShape = getResources()
.getDrawable(R.drawable.normal_shape);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
case DragEvent.ACTION_DRAG_ENTERED:
v.setBackground(enterShape);
break;
case DragEvent.ACTION_DRAG_EXITED:
case DragEvent.ACTION_DRAG_ENDED:
v.setBackground(normalShape);
break;
case DragEvent.ACTION_DROP:
Toast.makeText(getApplicationContext(), "Drop Successful!", Toast.LENGTH_LONG).show();
break;
default:
break;
}
return true;
}
};
return onDragListener;
}
}
CustomEditText.class :
public class CustomEditText extends AppCompatEditText {
public CustomEditText(Context context) {
super(context);
}
public CustomEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onDragEvent(DragEvent event) {
return false;
}
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/ll"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_gravity="center"
android:weightSum="100"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="300dp"
android:layout_height="300dp"
android:orientation="vertical"
android:layout_centerInParent="true"
android:background="@drawable/normal_shape"
android:id="@+id/ll_container">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:padding="10dp"
android:layout_gravity="center"
android:gravity="center"
android:textColorHint="@color/colorAccent"
android:hint="Focusable"
android:id="@+id/edt">
</EditText>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:padding="10dp"
android:layout_gravity="center"
android:gravity="center"
android:focusable="false"
android:textColorHint="@color/colorAccent"
android:hint="Not Focusable"
android:id="@+id/edt1">
</EditText>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:padding="10dp"
android:layout_gravity="center"
android:gravity="center"
android:background="@drawable/normal_shape"
android:textColorHint="@color/colorAccent"
android:hint="Drag Listener"
android:id="@+id/edt2">
</EditText>
<com.example.rabee.myapplication.CustomEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:padding="10dp"
android:layout_gravity="center"
android:gravity="center"
android:textColorHint="@color/colorAccent"
android:hint="Custom onDragEvent"
android:id="@+id/edt3">
</com.example.rabee.myapplication.CustomEditText>
</LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fab_item"
app:fabCustomSize="100dp"
android:src="@android:drawable/ic_menu_close_clear_cancel"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="30dp">
</com.google.android.material.floatingactionbutton.FloatingActionButton>
</RelativeLayout>
enter_shape.xml :
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="@android:color/transparent"/>
<stroke
android:width="15dp"
android:color="@color/colorPrimary" />
<corners
android:bottomLeftRadius="7dp"
android:bottomRightRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
</shape>
normal_shape.xml :
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="@android:color/transparent"/>
<stroke
android:width="2dp"
android:color="@color/colorAccent" />
<corners
android:bottomLeftRadius="7dp"
android:bottomRightRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
</shape>