テキストをリストするためにRecyclerView
を使用していますが、ここで、ユーザーがテキストをクリックしたときにカスタムアラートダイアログボックスがポップアップ表示されるようにしたいと思います。
これまでこれを試しましたが、NullPointerExceptionが発生しました。ここで何が悪いのでしょうか?
public class CBAdapter extends RecyclerView.Adapter<CBAdapter.ViewHolder> {
List<AdapterData> mItems;
public CBAdapter() {
super();
mItems = new ArrayList<>();
AdapterData data = new AdapterData();
data.setTextOne("Many Bows");
mItems.add(data);
data = new AdapterData();
data.setTextOne("Pardon");
mItems.add(data);
data = new AdapterData();
data.setTextOne("Fall To Knees & Beg");
mItems.add(data);
data = new AdapterData();
data.setTextOne("Backflips");
mItems.add(data);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.test3, viewGroup, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
AdapterData data = mItems.get(i);
viewHolder.textOne.setText(data.getTextOne());
}
@Override
public int getItemCount() {
return mItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
public TextView textOne;
private Context context;
public ViewHolder(View itemView) {
super(itemView);
textOne = (TextView)itemView.findViewById(R.id.textView1);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.custom_dialog);
dialog.setTitle("Title");
TextView text = (TextView) dialog.findViewById(R.id.text);
text.setText("hello world");
ImageView image = (ImageView) dialog.findViewById(R.id.image);
image.setImageResource(R.drawable.ic_launcher);
Button dialogButton = (Button) dialog.findViewById(R.id.dialogButtonOK);
dialogButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
});
}
}
}
コンテキストの初期化を忘れた
context = itemView.getContext();
これはクエリに対する答えではありませんが、このシナリオを処理するためのより良い方法です。
コールバックメソッドを使用します。
アクティビティ内:
これは、Adapter
にあるインターフェースを実装します。この例では、ユーザーがRecyclerView
のアイテムをクリックしたときに呼び出されます。
public class MyActivity extends Activity implements AdapterCallback {
private MyAdapter mMyAdapter;
@Override
public void onMethodCallback() {
// Show your alert
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mMyAdapter = new MyAdapter(this);
}
}
アダプタ内:
アクティビティでは、Adapter
を開始し、これを引数としてコンストラクターに渡しました。これにより、コールバックメソッドのインターフェイスが開始されます。ユーザークリックにコールバックメソッドを使用していることがわかります。
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private AdapterCallback mAdapterCallback;
public MyAdapter(Context context) {
try {
this.mAdapterCallback = ((AdapterCallback) context);
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement AdapterCallback.");
}
}
@Override
public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, final int i) {
// simple example, call interface here
// not complete
viewHolder.itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
mAdapterCallback.onMethodCallback();
} catch (ClassCastException exception) {
// do something
}
}
});
}
public static interface AdapterCallback {
void onMethodCallback();
}
}
final Dialog dialog = new Dialog(your_activity_context);
質問には直接関係ありませんが、お願いします:アダプター内でonClickListener-sを設定しないでください!
これはどのように行われるべきかです:
private class ItemDataHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener{
private final String TAG = ItemDataHolder.class.getSimpleName();
/**
* Define view's elements
*/
/**
* Define object instance
*/
private Item mData;
// Constructor
public MessageDataHolder(View itemView) {
super(itemView);
/**
* Init elements
*/
itemView.setOnLongClickListener(this);
}
/**
* Method to handle long click on the item
* @param v View to handle click on
* @return
*/
@Override
public boolean onLongClick(View v) {
Log.v(TAG, "Long click fired!");
return false;
}
/**
* Function to update view's elements
* @param message Good data to be updated to
*/
public void bindData(Item message) {
mData = message;
/**
* Set values of views here
**/
}
}
私の答えが誰かがより良いコードを書くのに役立つことを願っています:)
nullであるcontext
を使用しているので、context
をViewHolder
コンストラクターとCBAdapterコンストラクターに渡します。未満:
public class CBAdapter extends RecyclerView.Adapter<CBAdapter.ViewHolder> {
List<AdapterData> mItems;
Context context;
public CBAdapter(Context context) {
super();
this.context = context;
.....
}
およびViewHolderクラス
class ViewHolder extends RecyclerView.ViewHolder{
public TextView textOne;
private Context mcontext;
public ViewHolder(View itemView, Context mcontext) {
super(itemView);
this.mcontext = mcontext;
....
}