2

I have an onClick switch method in MainActivity.java and the buttons are programmatically created in Navigation.java. The initial menu nav.mainMenu() gets called correctly and the button is created as expected. My issue is that when I click the button, nothing happens.

I get no error stack trace in the logcat. I have tried putting logs in the onclick method, but it doesn't get that far. The emulator appears to work and does not freeze or crash.

I assume that when I send the code to the menu, the activity is in that class? so when I try to use the onClickListener in MainActivity, it isn't aware of it?

I'm also not sure what I should be expecting from v.getId() in 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;
    }
  }
}

Navigation.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();
  }
}
  • I have tried adding .setOnClickListener() to the buttons in Navigation.java but I can't get the context right, I don't know if that's what is missing.

  • Extending Navigation.java to MainActivity or Activity gives me a loop of errors.

Logcat after the app has been built onto the emulator:

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)
TomFirth
  • 2,334
  • 4
  • 20
  • 31

1 Answers1

2

You cannot assign a Context from a field. You probably "can't assign a right", because you're actually getting a nullpointerexception and editing the wrong location. That being said, getApplicationContext() isn't needed.

Also, might I suggest that you return the content layout rather than casting the context to an Activity?

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;
  }
}

At first glance, I see that you never set a click listener on the button, so you should probably do that.

For example

Context mContext;
View.OnClickListener mClickListener;

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

Now use this

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

I'm also not sure what I should be expecting from v.getId() in MainActivity.java R.id.btnGame?

The ID doesn't match the variable name. Without explicitly giving the button an ID, it'll be -1

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • I had tried moving the class definition into the onCreate method but I didn't think that was the issue as the initial menu call was still made. I've moved it and see no difference. I have removed `getApplicationContext()`. So now I leave it as `btnGame = new Button(mContext);`? I get no response from this either. – TomFirth Sep 30 '17 at 16:57
  • That's brilliant. I couldn't work out how to add a `clickListener` to the button! – TomFirth Sep 30 '17 at 17:06
  • 1
    Your listener can be implemented wherever you need it. You can also add a setOnClickListener method to your Navigation class – OneCricketeer Sep 30 '17 at 17:08
  • Logging the view from the `onClick` method in MainActivity I get `-1` ? I'll log out the listener and see if I can work out what i've done wrong. – TomFirth Sep 30 '17 at 17:13
  • 1
    `v.getId()` is negative one because you never set the ID onto the button... Any reason you aren't using XML? You apparently already have some XML resources generating id values – OneCricketeer Sep 30 '17 at 17:16
  • If I use xml, I would have 6 additional layouts. I was hoping to make it a little cleaner with a class to build those 'pages'. Annoyingly, I had solved this before but didn't push the source anywhere when I formatted. I have a number of `ids` created in in `R.values`. The only one I have set in a layout xml file is for the `LinearLayout`. and finally.. `btnGame.setId(R.id.btnGame);` has solved everything! thank you very much! – TomFirth Sep 30 '17 at 17:25