web-dev-qa-db-fra.com

Dialogue d'alerte personnalisé avec RecyclerView

J'utilise RecyclerView pour répertorier du texte et je souhaite maintenant que, lorsque l'utilisateur clique dessus, une boîte de dialogue d'alerte personnalisée s'ouvre.

J'ai déjà essayé cela, mais j'obtiens une exception NullPointerException; qu'est-ce qui ne va pas ici?

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


    }
}
}
9
Jacques Krause

Nevermind j'ai oublié l'initialisation de mon contexte

context = itemView.getContext ();

5
Jacques Krause

Ce n'est pas la réponse à votre question, mais le meilleur moyen de gérer ce scénario.

Utilisez des méthodes de rappel.

Dans votre activité:

Cela implémentera l'interface que nous avons dans notre Adapter. Dans cet exemple, il sera appelé lorsque l'utilisateur cliquera sur un élément de la variable 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);
    }
}

Dans votre adaptateur:

Dans l'activité, nous avons lancé notre Adapter et l'avons transmis sous forme d'argument au constructeur. Cela initiera notre interface pour notre méthode de rappel. Vous pouvez constater que nous utilisons notre méthode de rappel pour les clics de l'utilisateur.

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

Courtesy:Appelez la méthode d'activité depuis l'adaptateur

3
Anoop M
final Dialog dialog = new Dialog(your_activity_context);
2
Nikunj

Pas directement lié à la question, bien que je vous en prie: NE définissez PAS l'adaptateur interne onClickListener-s! 

Voici comment cela devrait être fait:

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
        **/
    }
}

J'espère que mes réponses aideront quelqu'un à écrire un meilleur code :)

0
egorikem

Vous utilisez context qui est null donc transmettez le constructeur context dans le constructeur ViewHolder et dans le constructeur CBAdapter également comme ci-dessous:

public class CBAdapter extends RecyclerView.Adapter<CBAdapter.ViewHolder> {

List<AdapterData> mItems;
Context context;

public CBAdapter(Context context) {
    super();
    this.context = context;
    .....
  }

Et dans la classe ViewHolder

class ViewHolder extends RecyclerView.ViewHolder{

    public TextView textOne;
    private Context mcontext;


    public ViewHolder(View itemView, Context mcontext) {
        super(itemView);
        this.mcontext = mcontext;
        ....
   }
0
Pankaj