简体   繁体   English

使用RecyclerView的自定义警报对话框

[英]Custom Alert Dialog With RecyclerView

I'm using RecyclerView to list some text and now I want to make it so that when the user clicks on text a custom Alert Dialog box pops up. 我正在使用RecyclerView列出一些文本,现在我想这样做,以便当用户点击文本时弹出一个自定义警报对话框。

I have tried this so far but get a NullPointerException; 到目前为止我已尝试过这个但是得到一个NullPointerException; what could be wrong here? 这可能有什么问题?

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


    }
}
}

Nevermind I forgot the initialization my context 没关系我忘了初始化我的上下文

context = itemView.getContext(); context = itemView.getContext();

This is not the answer for your query but the better way to handle this scenario. 这不是您的查询的答案,而是处理此方案的更好方法。

Use callback methods. 使用回调方法。

In your Activity: 在您的活动中:

This will implement the interface that we have in our Adapter . 这将实现我们在Adapter中的Adapter In this example, it will be called when the user clicks on an item in the RecyclerView . 在此示例中,将在用户单击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);
    }
}

In your Adapter: 在您的适配器中:

In the Activity, we initiated our Adapter and passed this as an argument to the constructor. 在Activity中,我们启动了我们的Adapter并将其作为参数传递给构造函数。 This will initiate our interface for our callback method. 这将启动我们的回调方法接口。 You can see that we use our callback method for user clicks. 您可以看到我们使用回调方法进行用户点击。

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 : Call Activity method from adapter 礼貌: 从适配器调用Activity方法

final Dialog dialog = new Dialog(your_activity_context);

You are using context which is null so pass the context in ViewHolder constructor and in CBAdapter constructor also like as below: 您正在使用context ,因此通过contextViewHolder构造和CBAdapter构造也很喜欢,如下:

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

List<AdapterData> mItems;
Context context;

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

And in ViewHolder class 并在ViewHolder类中

class ViewHolder extends RecyclerView.ViewHolder{

    public TextView textOne;
    private Context mcontext;


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

Not directly related to the question, although I beg you: DO NOT set onClickListener-s inside adapter! 与问题没有直接关系,虽然我求求你:不要在适配器内设置onClickListener-s!

This is how it should be done: 这是应该如何做到的:

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

Hope my answers helps someone to write a better code :) 希望我的答案能帮助别人写出更好的代码:)

Write this code: 写这段代码:

 final Dialog dialog = new Dialog(CBAdapter.this);

instead of 代替

final Dialog dialog = new Dialog(context);

(or) (要么)

context = CBAdapter.this; // Initialize context

Hope this helps. 希望这可以帮助。

Happy Coding :) 快乐编码:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM