【问题标题】:How can i show Material Dialog in a RecyclerView Adapter?如何在 RecyclerView 适配器中显示材质对话框?
【发布时间】:2019-02-15 12:50:52
【问题描述】:

我在显示我在 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();
    }
}

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

【问题讨论】:

  • 您应该使用回调或接口在适配器中的点击侦听器上创建材质对话框或任何对话框
  • 显示您从 Activity 创建适配器对象的代码

标签: android android-recyclerview


【解决方案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();
}

在您的活动中实现接口并在该方法的实现中创建材质对话框。

【讨论】:

  • 感谢您的回答,它很有帮助,而且效果很好
【解决方案2】:

您可以使用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
    }

【讨论】:

    【解决方案3】:

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

    在适配器内部添加点击监听器

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

    我的回调

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

    希望对你有帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      • 2017-12-19
      • 1970-01-01
      • 2022-10-24
      • 2017-06-14
      • 2017-10-07
      • 1970-01-01
      相关资源
      最近更新 更多