Как можно узнать, какое представление щелкнуло в макете OnClickListener?

У меня есть макет, который содержит несколько представлений. Я хочу установить некоторые действия, когда пользователь щелкает в любом месте макета, поэтому я установил OnClickListener для макета, который работает четко. Но как я могу узнать, какое представление было нажато? Я хочу назначить разные действия в зависимости от вида, который был нажат; или, может быть, не было нажато ни одного вида, и это был только сам макет. Таким образом, проблема заключается в том, что если я установлю OnClickListener для одного из представлений, будут активированы как OnCLickListener, связанные с макетом, так и представлением, но мне нужно только действие представления. Заранее спасибо.


person Babak-Na    schedule 06.08.2014    source источник
comment
выложи код метода и xml   -  person Rod_Algonquin    schedule 06.08.2014
comment
Не могли бы вы объяснить немного подробнее? Эти представления всегда одни и те же или вы добавляете их динамически? Знаете ли вы, что вы также можете добавить OnClickListener к каждому представлению?   -  person Sergi Juanola    schedule 06.08.2014
comment
Представления @Korcholis всегда одинаковы. Я знаю о setOclickListener для представлений, но как я могу узнать, какой из них щелкнул? Я отредактировал свой вопрос для вас.   -  person Babak-Na    schedule 06.08.2014
comment
Вы можете сгенерировать тост и проверить его в onClick().   -  person Aman Singh    schedule 06.08.2014
comment
В этом случае используйте то, что предлагают другие. Я нахожу интересным один из @user2959120, так как он также показывает вам, как назначить сам класс в качестве слушателя.   -  person Sergi Juanola    schedule 06.08.2014
comment
Я не мог узнать, как я могу назначить класс OnCLickListener. Если я установлю метод onClick для фрагмента или класса активности, проблема будет решена.   -  person Babak-Na    schedule 06.08.2014
comment
Да да, когда я писал класс, я имел в виду Activity или Fragment.   -  person Sergi Juanola    schedule 06.08.2014


Ответы (7)


Другие ответы довольно абстрактны, а некоторые неверны. Вы не можете переопределить метод onClick для Activity, поскольку у него его нет (если, конечно, вы не реализуете OnClickListener).

Кроме того, если вы установите прослушиватель для макета, аргумент View, полученный методом onClick, всегда будет макетом.


Вы можете либо создать свой собственный макет, который перехватывает клики и проверять, нажали ли вы на представление, либо вы можете установить прослушиватели для всех представлений.

Несколько более чистое решение использует один прослушиватель и проверяет, было ли выбрано представление.

private final String TAG = "MainActivity";
List<View> views = new ArrayList<View>();

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

    RelativeLayout rLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
    TextView tv1 = (TextView) findViewById(R.id.tv1);
    TextView tv2 = (TextView) findViewById(R.id.tv2);
    TextView tv3 = (TextView) findViewById(R.id.tv3);

    views.add(tv1);
    views.add(tv2);
    views.add(tv3);

    View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            boolean isView = false;
            for (View view : views) {
                if (v.equals(view)) {
                    isView = true;
                    break;
                }
            }

            if (isView) {
                Log.e(TAG, "Click on view");
            } else {
                Log.e(TAG, "Click on layout");
            }
        }
    };

    tv1.setOnClickListener(clickListener);
    tv2.setOnClickListener(clickListener);
    tv3.setOnClickListener(clickListener);
    rLayout.setOnClickListener(clickListener);
}

Если вам нужны разные действия для разных представлений, просто создайте прослушиватель для каждого из них.

person Simas    schedule 06.08.2014

Например, Layout имеет два представления View1 и View2. Я предполагаю, что вы их уже надули. Поэтому вам нужно установить OnClickListiner для каждого из них.

Layout.setOnClickListener(this);
View1.setOnClickListener(this);
View2.setOnClickListener(this);

Затем вам нужно переопределить метод:

public void onClick(View v) 
    {
        switch(v.getId())
        {
            case R.id.id_for_layout:
                // do what you want when user click layout
                break;

            case R.id.id_for_first_view:
                // do what you want when user click first view
                break;

            case R.id.id_for_second_view:
                // do what you want when user click second view
                break;
          }
}
person Mladen Rakonjac    schedule 06.08.2014
comment
Где вы переопределили метод onClick? Я полагаю, что он должен быть в классе активности или фрагмента, но он не работает. - person Babak-Na; 06.08.2014
comment
@Babak-Na в том же классе действий или фрагментов. Позаботьтесь об этом вне метода onCreate. - person Mladen Rakonjac; 06.08.2014

Помните, что метод OnClick имеет один параметр, указывающий, какое представление выбрано!

public void onClick(View v) {
      switch(v.getId()) {
        case R.id.btn1:
          // first button
          break;
        case R.id.btn2:
          // second button
          break;
      }
  }
person Kevin Vuilleumier    schedule 06.08.2014

Назначьте идентификатор каждому из ваших представлений с помощью android:id="@+id/v1", затем в

onClick(View v)

проверить вид, как

if(v == findViewById(R.id.v1))
{
 // v1 specific action
}
else if(v == findViewById(R.id.v2))
    {
     // v2 specific action
    }
person Gaurav Gupta    schedule 06.08.2014
comment
вы должны использовать оператор switch для этого.. это может быть проще реализовать - person Pragnesh Ghoda シ; 06.08.2014
comment
@Prag'sシ Вы можете использовать как переключатель, так и лестницу if else. и переключаться лучше, только если у вас много дел. - person Gaurav Gupta; 06.08.2014
comment
да, но вы работаете с несколькими идентификаторами if..elseif..else может быть более сложным для реализации.. - person Pragnesh Ghoda シ; 06.08.2014
comment
@Prag'sシ Как вы можете сказать, что это сложнее? - person Gaurav Gupta; 06.08.2014
comment
просто в простой строке вам нужно каждый раз находить идентификатор с помощью if(v == findViewById(R.id.v1)), а в switch(v.getItemId()) можно выполнять эту работу. - person Pragnesh Ghoda シ; 06.08.2014
comment
@Prag'sシ Здесь, в коммутаторе, вы также должны найти идентификатор в каждом случае, вызвав R.id.desiredView. - person Gaurav Gupta; 06.08.2014

Хорошо, это легко.
Вы должны добавить OnClickListener к каждому представлению (кнопке, textView и т. д.), а также ко всему макету.
В этом случае onClickListeners, которые будут запущены при нажатии, являются onClickListener представления и макет onClickListener.
Так что нет необходимости в целой куче классов.
Одного будет достаточно, если вы попробуете это (выполняйте действия в зависимости от идентификатора и не забывайте о макете ;)):

public void onClick(View v) {
  switch(v.getId()) {
    case R.id.layout:
      layout actions here
      break;
    case R.id.textview:
      textview actions here
      break;

это onClickListener для всех ваших представлений;)

person Hideya    schedule 06.08.2014

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

 getActivity()
      .getWindow()
      .getDecorView()
      .findViewById(android.R.id.content)
      .setOnTouchListener((v, event) -> {

                if (event.getAction() == MotionEvent.ACTION_UP) {
                    Log.v("[onClick]", v.getClass().getCanonicalName());
                }

                return false;
            });
person Kibotu    schedule 19.03.2018

person    schedule
comment
Может быть, я недостаточно хорошо объяснил. Я хочу запустить действие A, если щелкнуло представление, и действие B, если макет щелкнул в свободном пространстве, я имею в виду, что ни одно представление не щелкнуло для действия B. - person Babak-Na; 06.08.2014
comment
ваше решение, кажется, решает проблему, но я не могу найти метод onCLick для действия или класса фрагмента. Как я могу переопределить этот метод для действия или фрагмента? - person Babak-Na; 06.08.2014
comment
@Dilavar это установит onClick только для макета, а не для макета и представлений отдельно. - person Babak-Na; 06.08.2014
comment
затем установите view.onClickListener(это); как btn.setOnclickListner(это) - person Jay Agravat; 06.08.2014