如何在RecyclerView适配器中显示“材料”对话框?

时间:2019-02-15 12:50:52

标签: android android-recyclerview

我在显示我在RecyclerView适配器中创建的MaterialDialog时遇到问题。我想在回收者视图所在的活动中显示该对话框,并且我已经通过了活动上下文,但是它总是给我这个例外:

com.afollestad.materialdialogs.MaterialDialog$DialogException: Bad window token, you cannot show a dialog before an Activity is created or after it's hidden.

这是我的RecyclerView适配器:

public class AssetsAdapter extends RecyclerView.Adapter<AssetsAdapter.ItemHolder>{
    private static final String TAG = "AssetsAdapter";

    private ArrayList<Asset> listData;
    private Context activityContext;

    private MaterialDialog dialog;

    public AssetsAdapter(ArrayList<Asset> listData, Context activityContext, UserService userService) {
        this.listData = listData;
        this.activityContext = activityContext;
    }

    public AssetsAdapter(Context activityContext) {
        this.activityContext = activityContext;
    }

    @NonNull
    @Override
    public ItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.layout_item_assets, parent, false);
        return new ItemHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ItemHolder holder, final int position) {

        holder.tv_name.setText(listData.get(position).getName());
        holder.tv_manufacturer.setText(listData.get(position).getAsset_id());
        holder.tv_quantity.setText(listData.get(position).getPurchase_cost());


        holder.btn_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showCreateDialog(position);
            }
        });

        holder.btn_edit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(activityContext, "Edit", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        if(listData.isEmpty()) return 0;
        else return listData.size();
    }

    public class ItemHolder extends RecyclerView.ViewHolder{
        private ImageView iv_asset;

        private TextView tv_name;
        private TextView tv_manufacturer;
        private TextView tv_quantity;
        private TextView tv_status;

        private ImageButton btn_edit;
        private ImageButton btn_delete;

        public ItemHolder(View itemView) {
            super(itemView);

            iv_asset = itemView.findViewById(R.id.iv_asset);

            tv_name = itemView.findViewById(R.id.tv_name);
            tv_manufacturer = itemView.findViewById(R.id.tv_manufacturer);
            tv_quantity = itemView.findViewById(R.id.tv_quantity);
            tv_status = itemView.findViewById(R.id.tv_status);

            btn_edit = itemView.findViewById(R.id.btn_edit);
            btn_delete = itemView.findViewById(R.id.btn_delete);
        }
    }

    private void showCreateDialog(final int id){
        Log.i(TAG, "showCreateDialog: called");

        MaterialDialog.Builder builder = new MaterialDialog.Builder(activityContext)
                .content("Are you sure you want to delete this data?")
                .contentGravity(GravityEnum.CENTER)
                .autoDismiss(true)
                .positiveText("Yes")
                .negativeText("No")
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        //deleteAsset(id);
                    }
                })
                .onNegative(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        // do nothing
                    }
                })
                .canceledOnTouchOutside(true);

        dialog = builder.build();
        dialog.show();
    }
}

我认为我正确地传递了上下文,因为我没有表现出敬酒的问题。所以我不确定我做错了什么。任何答案将不胜感激,谢谢。

3 个答案:

答案 0 :(得分:1)

在适配器中使用这样的界面

public class AssetsAdapter extends RecyclerView.Adapter<AssetsAdapter.ItemHolder>{
    private static final String TAG = "AssetsAdapter";
private OnButtonClickListener listener;
...........
..........
.........
public AssetsAdapter(ArrayList<Asset> listData, Context activityContext, UserService userService,OnButtonClickListener  listener) {
        this.listData = listData;
        this.activityContext = activityContext;
        this.listener = listener;
    }
.......
......
...
..

 @Override
    public void onBindViewHolder(@NonNull ItemHolder holder, final int position) {

        holder.tv_name.setText(listData.get(position).getName());
        holder.tv_manufacturer.setText(listData.get(position).getAsset_id());
        holder.tv_quantity.setText(listData.get(position).getPurchase_cost());


        holder.btn_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.showCreateDialog();
            }
        });

        holder.btn_edit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(activityContext, "Edit", Toast.LENGTH_SHORT).show();
            }
        });
    }

创建类似的界面

public interface OnButtonClickListener {
    void showCreateDialog();
}

在您的活动中实现界面,并在该方法的实现中创建材料对话框。

答案 1 :(得分:1)

您可以使用EventBus

在您的 gradle文件

dependencies {
      implementation 'org.greenrobot:eventbus:3.1.1'
}

onBindViewHolder

        holder.btn_delete.setTag(holder);
        holder.btn_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ItemHolder myItemHolder = (ItemHolder) v.getTag();
                EventBus.getDefault().post(listData.get(myItemHolder.getAdapterPosition()));
            }
        });

活动

    @Override
    protected void onStart () {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop () {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void deleteAssetEvent (Asset asset){
        //Call your dialog here
    }

答案 2 :(得分:1)

因为您正在使用适配器内的对话框视图。不要在适配器内进行诸如clickListeners之类的操作。使用界面执行点击操作。

内部适配器中添加点击侦听器

  var mItemClickListener: MyCallback? = null
  fun setOnClickListener(click: MyCallback) {
    mItemClickListener = click
  }

MyCallback

public interface MyCallback {
    void onListClick(int position, Object _list);
}

点击适配器内的操作

holder.btn_delete.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
             mItemClickListener.onListClick(getAdapterPosition(), yourItemModel)
        }
    });

活动/片段

MyAdapter myAdapter = new MyAdapter()
recyclerView.setAdapter(myAdapter)

myAdapter.setOnClickListener(new MyCallback(){

    @Override
    public void onListClick(Int position, Item yourItem) {
        //here you can show dialog
        showDialog()
    }
})

希望对您有帮助:)