Question

I have a custom view MyView inflated from my_view.xml (with a corresponding Java class MyView.java).

I override MyView(Context context, AttributeSet attrs) to connect subviews up to members of the class.

Now one of these subviews is a Button, and I'd like for my view to listen for a click on its button before passing this event on to a delegate. However if I declare

this.myButton.setOnClickListener(this);

in the constructor MyView(Context context, AttributeSet attrs) (where this is an instance of MyView) I get a NullPointerException.

Where is an appropriate place in MyClass.java to call this.myButton.setOnClickListener(this);?

%%

Edit. Some code:

public MyView(Context ctx, AttributeSet attrs)
{
  super(context, attrs);
  this.myButton = (Button) this.findViewById(R.id.my_button);
  this.myButton.setOnClickListener(this); // Raises null pointer;'id' is correct.
}
Was it helpful?

Solution

Instead of trying to do the setOnClickListener(this) call in the constructor, do it after the button has been fully initialized. Try moving setOnClickListener(this) so that it's called (indirectly) from the parent activity's onResume method like this:

public class MainMenuActivity extends Activity {
    @Override
    public void onResume() {
        super.onResume();
        new MyView(this, attrs).onResume();
    }
   ...
}

public class MyView {
    public void onResume() {
        myButton.setOnClickListener(this);
    }
  ...
}

I use Roboguice all the time for this sort of thing, and highly recommend it. My button handler code looks like this:

class ButtonHandler implements OnClickListener {
    @InjectView(R.id.MainMenuButton)
    private Button button;

    public void onResumeEvent( @Observes OnResumeEvent onResume ) {
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        doSomethingUseful();
    }
}

OTHER TIPS

The problem is I've missed off an inflate in the constructor:

LayoutInflater i = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
i.inflate(R.layout.my_view, this);

This is confusing for me as I'd thought the constructor MyView(Context ctx, AttributeSet attrs) would be called in inflating the view, not the other way around.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top