Перетащите внутрь контейнера, содержащего EditText - PullRequest
0 голосов
/ 12 октября 2019

У меня возникла эта проблема (проблема) при выдаче события перетаскивания внутри целевого контейнера, содержащего 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>

image

...