onTouchListener () не отвечает, если представление анимировано за пределами прямого родительского представления - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть ImageView, который является потомком LinearLayout.Если я анимирую ImageView где-нибудь внутри LinearLayout, onTouchListener() реагирует после анимации, но перестает отвечать, если анимация перемещает представление за пределы прямого LinearLayout родителя.

Другими словами, будет ли запущен ImageView onTouchListener() или нет, полностью зависит от того, находятся ли смещения x и y моей анимации в пределах родительского элемента LinearLayout.

ObjectAnimator translateX =
        ObjectAnimator.ofFloat(view, "translationX",
                offSet_X);

ObjectAnimator translateY =
        ObjectAnimator.ofFloat(view, "translationY",
                offSet_Y);

translateX.setDuration(translationDurationMill);
translateX.start();
translateY.setDuration(translationDurationMill);
translateY.start();

Ожидается ли такое поведение или это может быть ошибка в моем коде?

edit

Так, например, я сократил проблему до простого приложения и убедился, что поведение - это не ошибка, а способ работы Android.но я не уверен, как обойти это поведение.

Итак, вот простой макет для основного действия

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:clipChildren="false"
    android:clipToPadding="false"
    >

    <LinearLayout
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="@color/colorPrimary"
        android:text="Hello World!"
        android:gravity="center"
        >

        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/colorAccent"
            android:text="hello world" />

    </LinearLayout>
</LinearLayout>

Вот код основного действия

public class MainActivity extends AppCompatActivity
        implements View.OnTouchListener{

    int mTranslationDurationMill = 500;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv = findViewById(R.id.tv);
        tv.setOnTouchListener(this);

        animateTextView(tv,10,10);
    }

    private void animateTextView(View view, int offSet_X,int offSet_Y)
    {
        ObjectAnimator translateX =
                ObjectAnimator.ofFloat(view, "translationX",
                        offSet_X);

        ObjectAnimator translateY =
                ObjectAnimator.ofFloat(view, "translationY",
                        offSet_Y);

        translateX.setDuration(mTranslationDurationMill);
        translateX.start();
        translateY.setDuration(mTranslationDurationMill);
        translateY.start();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("TAG","onTouch()");
        return false;
    }
}

Выше у меня есть animateTextView(tv,10,10); для анимации текстового представления, и после анимации я могу подтвердить, что журнал показывает событие касания, и вот картинка

enter image description here

но Если сделать animateTextView(tv,400,400);, то представление выходит за пределы прямого родителя LinearLayout, и событие касания не регистрируется.Вот картинка.

enter image description here

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Я мог бы найти работу вокруг.Похоже, что событие касания не будет распространено на анимированное представление, если касание даже происходит на анимированном представлении, но за пределами непосредственного родителя анимированного представления, поэтому я перезаписываю обработчик события отправки активности и пропускаюсобытие движения непосредственно к анимированному виду.

public class MainActivity extends AppCompatActivity
        implements View.OnTouchListener {

    int mTranslationDurationMill = 500;
    TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findViewById(R.id.tv);
        tv.setOnTouchListener(this);

        animateTextView(tv, 400, 400);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("TAG", "onTouch()");
        Log.d("TAG", "event.getAction() "+event.getAction());
        return false;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent me) {

        Log.d("TAG", "dispatchTouchEvent");

        // Send the motion event directly to the view.

        this.onTouch(tv, me);

        // Don't propagate the motion event to the children.
        return true;
    }

    private void animateTextView(View view, int offSet_X, int offSet_Y) {
        ObjectAnimator translateX =
                ObjectAnimator.ofFloat(view, "translationX",
                        offSet_X);

        ObjectAnimator translateY =
                ObjectAnimator.ofFloat(view, "translationY",
                        offSet_Y);

        translateX.setDuration(mTranslationDurationMill);
        translateX.start();
        translateY.setDuration(mTranslationDurationMill);
        translateY.start();
    }
}

Итак, вот журналы, когда я прикасаюсь к анимированному представлению, когда оно выходит за пределы родительского вида:

D/TAG: dispatchTouchEvent
D/TAG: onTouch()
D/TAG: event.getAction() 0
D/TAG: dispatchTouchEvent
D/TAG: onTouch()
D/TAG: event.getAction() 2
D/TAG: dispatchTouchEvent
D/TAG: onTouch()
D/TAG: event.getAction() 2
D/TAG: dispatchTouchEvent
D/TAG: onTouch()
D/TAG: event.getAction() 2
D/TAG: dispatchTouchEvent
D/TAG: onTouch()
D/TAG: event.getAction() 1 
0 голосов
/ 03 декабря 2018

это работает для меня.вот весь код

в макете, у меня есть ImageView и TextView (изменение текста с не нажатого на нажатый после срабатывания события касания)

<FrameLayout
    android:id="@+id/child_view_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/child_view"
        android:layout_width="match_parent"
        android:layout_height="300px"
        app:srcCompat="@color/colorAccent"
        tools:layout_editor_absoluteX="216dp"
        tools:layout_editor_absoluteY="143dp" />

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:text="not clicked"
        android:textSize="30sp"
        tools:layout_editor_absoluteX="119dp"
        tools:layout_editor_absoluteY="230dp" />
</FrameLayout>

в коде:childView - это TextView textView - это TextView, который слушатель будет прослушивать для события касания, и в случае обнаружения он изменит текст textView на «нажатие»

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    textView = findViewById(R.id.textview);

    childView = findViewById(R.id.child_view);
    childView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            textView.setText("clicked");
            return false;
        }
    });

}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    if(hasFocus){
        View containerView = findViewById(R.id.child_view_container);
        childView.setTranslationX(containerView.getWidth());
        childView.animate()
                .translationXBy(-containerView.getWidth())
                .setDuration(10000)
                .setInterpolator(new AccelerateDecelerateInterpolator())
                .start();
    }
}

Надеюсь, это полезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...