はじめに
androidの開発でpopupWindowの中にボタンを設置したときにあった問題の解決方法をまとめます。
-
実現したい機能
- popupされたwindowの中にボタンを設置
-
利用したandoirdのclass
- android.widget.PopupWindow
-
問題点
- popupされたwindowの中のボタンにOnClickListenerがうまく付かない
popupWindowの使い方
- 必要なactivity
- popup対象のwindowのactivity
- popupWindowを表示するactivity
- 必要なclass
- popupWindowを表示するactivityのclass
つまり、classはpopupWindowを表示するactivityのもののみでいいので、popup対象となるwindowのほうは別activityでlayoutなどを構築して、あとclassでpopupWindowsの関連の関数を使ってactivityを呼び出せばいいです。
分かりやすくするために、以下と定義します。
- popupWindowを表示するactivity
- 「my_activity」
- popup対象のwindowのactivity
- 「window_activity」
コアのコードの部分は以下です。(前後の処理のコードは割愛)
import android.widget.PopupWindow
…
(略)
…
Button showWindow = findViewById(R.id.show_button);
showWindow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// popupWindow用のviewを宣言し、window_activityと関連を付け
View popView = SocialFragment_Topic.this.getLayoutInflater().inflate(R.layout.window_activity, null);
// popupWindow関数を利用して初期化するときのlayoutパラメータを設定
PopupWindow ppw = new PopupWindow(popView, LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
…
(略)
…
// windowのpopup、showAtLocationは指定場所でpopupする関数
// パラメータ
// #1 : どのviewでwindowを作成する(popupする)
// #2 : 相対位置(TOP,LEFT,RIGHT,BOTTOM)
// #3 : X方向でのオフセット
// #4 : Y方向でのオフセット
ppw.showAtLocation(findViewById(R.id.window_anchor_linearLayout), Gravity.BOTTOM,0,0);
}
こういう感じでコードを書けば、「my_activity」中の「show」ボタンを押すと、popupWindow自体は実現できるはずです。
popupWindow中のボタン
一般的に下のコードのような感じでボタンのviewを宣言してOnClickListenerの中に詳しい処理を書けば、ボタンを押すと反応するはずです。
button myButton = findViewById(R.id.popupwindow_button);
myButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
popupされたwindowの中には、こういうふうに書いたらOnClickListenerはエラーで落ちます。
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
viewとの関連がつけてない!
ちゃんとこれをしたのに?
button myButton = findViewById(R.id.popupwindow_button);
問題はこの処理は「my_activity」に「window_activity」中のボタンと関連をつけようとするからです。
popupされたwindowの中のものは、表示するほうのactivityのものではないので、
当然、関連を付けようとするとエラーが出ます。
正しい書き方は
import android.widget.PopupWindow
…
(略)
…
Button showWindow = findViewById(R.id.show_button);
showWindow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// popupWindow用のviewを宣言し、window_activityと関連を付け
View popView = SocialFragment_Topic.this.getLayoutInflater().inflate(R.layout.window_activity, null);
// popupWindow関数を利用して初期化するときのlayoutパラメータを設定
PopupWindow ppw = new PopupWindow(popView, LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
…
(略)
…
button myButton = popView.findViewById(R.id.popupwindow_button);
myButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
...(何かの処理)..
}
});
…
(略)
…
// windowのpopup、showAtLocationは指定場所でpopupする関数
ppw.showAtLocation(findViewById(R.id.window_anchor_linearLayout), Gravity.BOTTOM,0,0);
}
…
(略)
誤:
button myButton = findViewById(R.id.popupwindow_button);
正:
button myButton = popView.findViewById(R.id.popupwindow_button);
popViewは
View popView = SocialFragment_Topic.this.getLayoutInflater().inflate(R.layout.window_activity, null);
で宣言したviewです。