Можно ли передать onTouchEvent нескольким представлениям в Android? - PullRequest
5 голосов
/ 19 ноября 2011

Я прочитал несколько вопросов по этой теме в SO, но на самом деле не нашел на это четкого ответа.

У меня есть структура кадра, на которую я накладываю несколько пользовательских представлений, однако событие onTouch работает толькос видом сверху.(пользовательские представления - это одно и то же представление с одним и тем же событием onTouch, только их несколько)

FrameLayout

  • customView [2] <--- это последнее добавленное представление, которое получает событие </em>
  • customView [1]
  • customView [0]

Iтестирую его на Android 2.2 и задаюсь вопросом, есть ли способ, чтобы другие представленные ниже виды могли узнать, где произошло касание?


EDIT (Добавление некоторого кода)

Я добавляю некоторый код, чтобы, надеюсь, помочь объяснить, где я сталкиваюсь с проблемами.Сначала я просто автоматически вернул onTouchEvent true.Это сделало так, чтобы последнее представление (в моем случае customerView [2] ) было единственным, генерирующим значение.

Однако, как только я добавил метод для установки onTouchEvent чтобы вернуть true или false, теперь единственным представлением, возвращающим сгенерированное значение, является customView [0] .

Надеюсь, это прояснит то, что я спрашиваю.Я довольно новичок в этом, и я ценю, что вы нашли время, чтобы объяснить это (и, конечно, я ценю ваше терпение).

Кроме того, я понимаю, что мой TextView не обновляется со значением для каждого touchEventЯ работаю над исправлением этого.

Моя активность:

public class MyActivity extend Activity {

    CustomView[] customView;
    TextView[] textView;
    int numViews 3;
    //FrameLayout and Params created

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        for(int i = 0; i < numViews; i++) {
            customView[i] = new CustomView(this, i);


            //Allows the onTouch to be handled by all Views - View[0] is the bottom view
            if(i == 0) {
                customView[i].setTouchBool(true);        //set view's onTouch to return true
            } else {
                customView[i].setTouchBool(false);       //set view's onTouch to return false
            }

            //Set TextView to display the number generated by the CustomView
            textView[i].setText(Double.toString(customView[i].getGeneratedNumber()));

            //Add views to main layout
            frame.addView(textView[i]);
            frame.addView(customView[i]);
        }
    }
}

Мой вид:

public class CustomView extends View {

    boolean onTouchHandler = true;
    int xVal = 0, yVal = 0;
    int index;
    double generatedNum = 0;

    public CustomView(Context context) {
        this(context, 0);
        this.index = 0;
    }

    public CustomView(Context context, int index) {
        super(context);
        this.index = index;
    }


    @Override 
    public boolean onTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();

        switch(action) {
            case MotionEvent.ACTION_DOWN: {
                //do logic 
            }

            case MotionEvent.ACTION_MOVE: {
                //do logic
            }

            case MotionEvent.ACTION_UP: {
                xVal = (int) ev.getX();
                yVal = (int) ev.getY();

                generateNumber(xVal, yVal, index);

                break; 
            }
        }
         return onTouchHandler;    
    }  


    private void generateNumber(int x, int y, int index) {
        if(index == 0) {
            generatedNum = (x / 2) * (y / 2) + 64;
        } else {
            generatedNum = (x / 2) * (y / 2) + (index * 128);
        }
    }

    public double getGeneratedNumber() {
        return generatedNum;
    }

    public boolean setTouchBool(boolean b) {
        this.onTouchHandler = b;
    }
}

1 Ответ

15 голосов
/ 19 ноября 2011

Android будет каскадно просматривать представления, вызывая onTouchEvent для каждого из них, пока не получит true от одного из них.Если вы хотите, чтобы событие касания обрабатывалось всеми из них, возвращайте false, пока оно не достигнет последнего.

РЕДАКТИРОВАТЬ:

ОК.Если я правильно понимаю, у вас есть один вид сверху, содержащий несколько дочерних видов на один уровень глубиной.Мой первоначальный ответ предполагал, что у вас есть три пользовательских представления, которые располагаются друг над другом в иерархии ViewGroup (View3 является дочерним элементом View2. View2 является дочерним элементом View1. View1 является дочерним элементом ParentView).Вы хотите, чтобы событие касания пользователя в родительском представлении было отправлено всем его дочерним элементам.

В таком случае, AFAIK, в Android-интерфейсе нет представления, позволяющего это сделать.Итак, вам нужно создать собственное представление, которое это делает.

ОК, я не проверял это, поэтому, пожалуйста, скажите мне, работает ли он, и если вы пытаетесь.Создайте пользовательский класс, который расширяет любой объект frame, затем переопределите метод onTouch следующим образом.

@Override 
public boolean onTouchEvent(MotionEvent ev) {
   for(int i = 0; i < this.getChildCount(); i++){
      this.getChildAt(i).dispatchTouchEvent(ev);
   } 
   return true;
} 

Теперь сохраните ту же логику, что и ваши пользовательские представления, за исключением того, что все они должны возвращать false поскольку ваше родительское представление не получит событие onTouch, если оно не будет сделано, как указано в моем предыдущем ответе

note: с этой реализацией, дочернее представление, к которому фактически прикасается пользователь, сработает дваждыпотому что по логике сработает событие дочернего касания -> вернет false -> событие сработает родительского касания -> снова сработает событие дочернего касания

...