Android и делает " это " слушателем для одной из своих кнопок
У меня есть пользовательский вид MyView
, раздутый из my_view.xml
(с соответствующим классом Java MyView.java
).
Я переопределяю MyView(Context context, AttributeSet attrs)
для подключения вложенных представлений к членам класса.
Теперь один из этих подвидов является Button
, и я хотел бы, чтобы мой вид прослушал щелчок по его кнопке, прежде чем передавать это событие делегату. Однако если я объявлю
this.myButton.setOnClickListener(this);
В конструкторе MyView(Context context, AttributeSet attrs)
(где this
- экземпляр MyView
) я получаю NullPointerException
.
Где находится подходящее место в MyClass.java
для вызова this.myButton.setOnClickListener(this);
?
%%
Правка. Код:
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.
}
2 ответа:
Вместо того, чтобы пытаться выполнить вызов
setOnClickListener(this)
в конструкторе, сделайте это после полной инициализации кнопки. Попробуйте переместитьsetOnClickListener(this)
так, чтобы он вызывался (косвенно) из метода родительского действияonResume
следующим образом: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); } ... }
Я использую Roboguice все время для такого рода вещей, и очень рекомендую его. Мой код обработчика кнопок выглядит следующим образом:
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(); } }
Проблема в том, что я пропустил накачку в конструкторе:
LayoutInflater i = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); i.inflate(R.layout.my_view, this);
Это сбивает меня с толку, поскольку я думал, что конструктор
MyView(Context ctx, AttributeSet attrs)
будет вызван для раздувания представления, а не наоборот.