Android программно создал кнопку onClick из класса

У меня есть метод переключения onClick в MainActivity.java, а кнопки создаются программно в Navigation.java. Начальное меню nav.mainMenu() вызывается правильно, и кнопка создается, как и ожидалось. Моя проблема в том, что когда я нажимаю кнопку, ничего не происходит.

Я не получаю трассировку стека ошибок в logcat. Я пытался помещать журналы в метод onclick, но это не так далеко. Эмулятор вроде работает, не зависает и не зависает.

Я предполагаю, что когда я отправляю код в меню, активность находится в этом классе? поэтому, когда я пытаюсь использовать onClickListener в MainActivity, он не знает об этом?

Я также не уверен, чего мне ожидать от v.getId() в MainActivity.java R.id.btnGame?

MainActivity.java

public class MainActivity extends Activity implements View.OnClickListener {

  public Navigation nav = new Navigation(this);

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.empty);
    nav.mainMenu();
  }

  @Override
  public void onClick(View v) {
    switch(v.getId()) {
      case R.id.btnGame:
        nav.game();
        break;
    }
  }
}

Навигация.java

public class Navigation {

  Button btnGame;

  Context mContext;
  Navigation(Context mContext) {
    this.mContext = mContext;
  }

  public void mainMenu() {
    LinearLayout ll = new LinearLayout(mContext);
    ll.removeAllViews();
    LinearLayout.LayoutParams llP = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
    ll.setLayoutParams(llP);
    ll.setOrientation(LinearLayout.VERTICAL);
    LinearLayout.LayoutParams btnParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

    btnGame = new Button(mContext.getApplicationContext());
    btnGame.setLayoutParams(btnParams);
    btnGame.setText("Play Game");
    ll.addView(btnGame);

  Activity activity = (Activity) mContext;
    activity.setContentView(ll);
  }

  public void game() {
    Toast.makeText(mContext, "I dont see this", Toast.LENGTH_SHORT).show();
  }
}
  • Я попытался добавить .setOnClickListener() к кнопкам в Navigation.java, но я не могу правильно понять контекст, я не знаю, чего не хватает.

  • Расширение Navigation.java до MainActivity или Activity дает мне цикл ошибок.

Logcat после того, как приложение было встроено в эмулятор:

09-30 17:43:59.655 7038-7038/? I/art: Not late-enabling -Xcheck:jni (already on)
09-30 17:43:59.655 7038-7038/? W/art: Unexpected CPU variant for X86 using defaults: x86
09-30 17:43:59.854 7038-7038/com.fomtirth.barcodebattle W/System: ClassLoader referenced unknown path: /data/app/com.fomtirth.barcodebattle-2/lib/x86
09-30 17:43:59.867 7038-7038/com.fomtirth.barcodebattle I/InstantRun: starting instant run server: is main process
09-30 17:44:00.230 7038-7066/com.fomtirth.barcodebattle I/OpenGLRenderer: Initialized EGL, version 1.4
09-30 17:44:00.230 7038-7066/com.fomtirth.barcodebattle D/OpenGLRenderer: Swap behavior 1
09-30 17:44:00.230 7038-7066/com.fomtirth.barcodebattle W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
09-30 17:44:00.230 7038-7066/com.fomtirth.barcodebattle D/OpenGLRenderer: Swap behavior 0
09-30 17:44:00.234 7038-7066/com.fomtirth.barcodebattle D/EGL_emulation: eglCreateContext: 0x9baa38c0: maj 2 min 0 rcv 2
09-30 17:44:00.241 7038-7066/com.fomtirth.barcodebattle D/EGL_emulation: eglMakeCurrent: 0x9baa38c0: ver 2 0 (tinfo 0x99a887d0)
09-30 17:44:00.293 7038-7066/com.fomtirth.barcodebattle D/EGL_emulation: eglMakeCurrent: 0x9baa38c0: ver 2 0 (tinfo 0x99a887d0)
09-30 17:44:00.400 7038-7066/com.fomtirth.barcodebattle D/EGL_emulation: eglMakeCurrent: 0x9baa38c0: ver 2 0 (tinfo 0x99a887d0)
09-30 17:44:00.460 7038-7066/com.fomtirth.barcodebattle D/EGL_emulation: eglMakeCurrent: 0x9baa38c0: ver 2 0 (tinfo 0x99a887d0)

person TomFirth    schedule 30.09.2017    source источник
comment
Какие ошибки? Вы можете показать их?   -  person OneCricketeer    schedule 30.09.2017
comment
Я не получаю никаких ошибок, logcat пуст после сборки. Я отредактирую выше, чтобы включить вывод сборки.   -  person TomFirth    schedule 30.09.2017
comment
Вы отфильтровали ошибки?   -  person OneCricketeer    schedule 30.09.2017
comment
Нет, это было verbose.   -  person TomFirth    schedule 30.09.2017
comment
Что ж, я совершенно уверен, что Context должен быть нулевым, однако ваша кнопка ничего не делает, потому что вам, похоже, не хватает setOnClickListener   -  person OneCricketeer    schedule 30.09.2017


Ответы (1)


Вы не можете назначить контекст из поля. Вы, вероятно, «не можете назначить право», потому что на самом деле вы получаете исключение нулевого указателя и редактируете неправильное местоположение. При этом getApplicationContext() не нужен.

Кроме того, могу ли я предложить вам вернуть макет содержимого, а не приводить контекст к действию?

public Navigation nav;

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  nav = new Navigation(this);
  setContentView(nav.mainMenu());

} 

@Override
public void onClick(View v) {
  switch(v.getId()) {
    case R.id.btnGame:
      nav.game();
      break;
  }
}

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

Например

Context mContext;
View.OnClickListener mClickListener;

Navigation(Context context) {
    this.mContext = context;
    if (context instanceof View.OnClickListener) {
        this.mClickListener = (View.OnClickListener) context ;
    } 
}

Теперь используйте это

if (mClickListener!=null) {
    button.setOnClickListener(mClickListener);
}

Я также не уверен, чего мне ожидать от v.getId() в MainActivity.java R.id.btnGame?

Идентификатор не соответствует имени переменной. Без явного указания идентификатора кнопки это будет -1

person OneCricketeer    schedule 30.09.2017
comment
Я попытался переместить определение класса в метод onCreate, но я не думал, что это проблема, поскольку первоначальный вызов меню все еще был сделан. Я переставил и не вижу разницы. Я удалил getApplicationContext(). Итак, теперь я оставлю это как btnGame = new Button(mContext);? Я тоже не получаю ответа от этого. - person TomFirth; 30.09.2017
comment
Это блестяще. Я не мог понять, как добавить clickListener к кнопке! - person TomFirth; 30.09.2017
comment
Ваш слушатель может быть реализован везде, где вам это нужно. Вы также можете добавить метод setOnClickListener в свой класс навигации. - person OneCricketeer; 30.09.2017
comment
Регистрируя представление из метода onClick в MainActivity, я получаю -1? Я выйду из прослушивателя и посмотрю, смогу ли я понять, что я сделал неправильно. - person TomFirth; 30.09.2017
comment
v.getId() является отрицательным, потому что вы никогда не устанавливаете идентификатор для кнопки... Есть ли причина, по которой вы не используете XML? Очевидно, у вас уже есть некоторые ресурсы XML, генерирующие значения идентификатора. - person OneCricketeer; 30.09.2017
comment
Если бы я использовал xml, у меня было бы 6 дополнительных макетов. Я надеялся сделать его немного чище с помощью класса для создания этих «страниц». Досадно, что я решил это раньше, но никуда не нажимал источник при форматировании. У меня есть номер ids, созданный в R.values. Единственный, который я установил в XML-файле макета, предназначен для LinearLayout. и наконец.. btnGame.setId(R.id.btnGame); все решил! большое спасибо! - person TomFirth; 30.09.2017