带有 RecyclerView 的自定义 AlertDialog - 列表始终为空

Posted

技术标签:

【中文标题】带有 RecyclerView 的自定义 AlertDialog - 列表始终为空【英文标题】:Custom AlertDialog with RecyclerView - list is always empty 【发布时间】:2018-12-31 19:33:33 【问题描述】:

首先,我使用 RecyclerView 创建了活动,它工作正常。我的原始代码:

activity_agreements.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                             xmlns:app="http://schemas.android.com/apk/res-auto"
                                             xmlns:tools="http://schemas.android.com/tools"
                                             android:id="@+id/linearLayout"
                                             android:layout_
                                             android:layout_>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/list"
        android:layout_
        android:layout_
        android:layout_marginBottom="8dp"
        android:paddingTop="8dp"
        android:scrollbars="vertical"
        app:layout_constraintBottom_toTopOf="@+id/editText"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/editText"
        android:layout_
        android:layout_
        android:layout_marginLeft="8dp"
        android:ems="10"
        android:gravity="left"
        android:inputType="none|text|textPersonName"
        android:text="* required fields"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/btnGetSelected"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

    <Button
        android:id="@+id/btnGetSelected"
        android:layout_
        android:layout_
        android:layout_marginBottom="4dp"
        android:text="I agree"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>


</android.support.constraint.ConstraintLayout>

传递给 ActivityAgreements 和适配器设置的协议列表:

@Override
    protected void onCreate(Bundle savedInstanceState)
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_agreements);

        btnGetSelected = findViewById(R.id.btnGetSelected);
        list = findViewById(R.id.list);
        list.setLayoutManager(new LinearLayoutManager(this));
        list.setHasFixedSize(true);


        agreements = getIntent().getParcelableArrayListExtra("agreements");



        AgreementsAdapter adapter = new AgreementsAdapter(this.agreements);
        list.setAdapter(adapter);

我的适配器代码:

public class AgreementsAdapter extends RecyclerView.Adapter<AgreementsAdapter.ViewHolder>


    ArrayList<Agreement> agreements;

    public AgreementsAdapter(List<Agreement> agreements)
    
        this.agreements = new ArrayList<>(agreements);
    

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.agreement_list_item, parent, false);
        return new ViewHolder(v);
    

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position)
    
        holder.bindData(agreements.get(position));
        holder.checkbox.setOnCheckedChangeListener(null);
        holder.checkbox.setChecked(agreements.get(position).getAccepted());
        //holder.checkbox.setFloorUnCheckedColor(agreements.get(position).getRequired()? Color.rgb(255,0,0):Color.rgb(0,255,0) );
        holder.checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> agreements.get(holder.getAdapterPosition()).setAccepted(isChecked));
    

    @Override
    public int getItemCount()
    
        return agreements.size();
    

    public static class ViewHolder extends RecyclerView.ViewHolder
    
        private TextView textAgreementName;
        private AppCompatCheckBox checkbox;

        public ViewHolder(View v)
        
            super(v);
            //textAgreementName = v.findViewById(R.id.text_agreement_name);
            checkbox = v.findViewById(R.id.checkbox_agreement_accepted);
        

        public void bindData(Agreement agreement)
        
            //checkbox.setFloorUnCheckedColor(agreement.getRequired()? Color.rgb(255,0,0):Color.rgb(0,0,255) );
            /*if(agreement.getRequired())
            
                textAgreementName.setTypeface(null, Typeface.BOLD);
                textAgreementName.setText(agreement.getName() + " *");
            
            else
                textAgreementName.setText(agreement.getName());*/


            if(agreement.getRequired())
            
                checkbox.setText(agreement.getName() + " *");
                checkbox.setTypeface(null, Typeface.BOLD);
            
            else
            
                checkbox.setText(agreement.getName());
            




        
    

一切都很好,带有列表的活动显示自己没有任何问题。现在,我想使用 AlertDialog,而不是活动来显示协议列表。我正在尝试以这种方式创建 AlertDialog(在主要活动中):

AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this);
            LayoutInflater inflater = getLayoutInflater();
            View convertView = inflater.inflate(R.layout.activity_agreements, null);
            alertDialog.setView(convertView);


            RecyclerView list = convertView.findViewById(R.id.list);
            list.setLayoutManager(new LinearLayoutManager(this));
            list.setHasFixedSize(true);

            AgreementsAdapter adapter = new AgreementsAdapter(agreements);
            list.setAdapter(adapter);



           alertDialog.show();

agreements 变量包含协议列表(与之前传递给 AgrrementsActivity 的相同)。但它不起作用 - 对话框以自定义布局显示,但列表始终为空。

谁能指出我错过了什么?

固定大小的新代码和其他建议:

AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this);
            LayoutInflater inflater = getLayoutInflater();
            View convertView = inflater.inflate(R.layout.activity_agreements, null);



            RecyclerView list = convertView.findViewById(R.id.list);
            list.setLayoutManager(new LinearLayoutManager(this));
            list.setHasFixedSize(true);

            AgreementsAdapter adapter = new AgreementsAdapter(agreements);
            list.setAdapter(adapter);
            alertDialog.setView(convertView);

            AlertDialog dialog = alertDialog.create();
            dialog.getWindow().setLayout(600, 400);



           dialog.show();
           adapter.notifyDataSetChanged();

【问题讨论】:

你想在 Dialog 中显示 recyclerview 吗? 是的,这就是我想要的。自定义布局如上图,从活动移到对话框 试试 alertDialog.setView(convertView);下面 list.setAdapter(adapter); 列表仍为空 你能检查一下 android:layout_ android:layout_ 的回收站视图吗 【参考方案1】:

您的 RecyclerView 可能正在显示列表,但它的高度为 0,因此看起来是空的。

对话框大小有点棘手,检查this answer 并尝试给它一个固定高度(可能是屏幕高度的百分比)。

【讨论】:

AlertDialog 没有方法getWindow 你应该使用compat库(developer.android.com/reference/android/support/v7/app/…),它有getWindow方法。 好吧,好吧,我设法设置了大小,但它没有效果,大小相同,仍然没有显示列表 - 问题已更新 你的答案是对的。列表在那里,但与 Activity 内部不同,现在它的大小为 0。你知道如何正确渲染它吗?你上面的解决方案(设置对话框大小)没有效果 好的,终于成功了。我设置了android:layout_width="0dp" android:layout_height="wrap_content",现在好像没问题了【参考方案2】:

我知道现在回答这个问题已经很晚了,但我也遇到了同样的问题。所以对于仍然面临这个问题的人可以使用以下技术。

如果您使用 Recycler View 和约束布局 并在警报对话框中设置了 layout_height="0",那么您将无法看到 recycler View 列表。要解决此问题,请设置此

app:layout_constraintHeight_default="wrap"

回收站视图

【讨论】:

【参考方案3】:

下班后寻找使用 RecyclerView 和 AlertDialog 和 ConstraintLayout 的最佳方式,解决方案:

<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_
android:layout_>

<TextView
    android:id="@+id/abc"
    android:layout_
    android:layout_
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />


<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recycler"
    android:layout_
    android:layout_
    app:layout_constraintHeight_default="wrap"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/abc" />

<ProgressBar
    android:id="@+id/progressBarFavorito"
    style="?android:attr/progressBarStyle"
    android:layout_
    android:layout_
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/abc" />

【讨论】:

【参考方案4】:

对于在alertdialogue中使用recyclerview,你应该有点棘手。因为你使用匹配父级,所以recyclerview的宽度为0,因为recyclerviews维度是在创建alertdialogue之前设置的。所以你这样做:

1) 使用 runnable 并设置您的适配器(或我们使用 recyclerview 进行的其他活动)延迟 1 秒

或者, 2)当您初始化recyclerview时,只需以编程方式设置它的layoutparams。这解决了我的问题。(不要盲目使用此代码,我只是从我的代码中复制它,它可能不适合您的代码。而只是了解这个问题。)

member_list.setLayoutParams(new ConstraintLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

【讨论】:

以上是关于带有 RecyclerView 的自定义 AlertDialog - 列表始终为空的主要内容,如果未能解决你的问题,请参考以下文章

支持下拉刷新和上划加载更多的自定义RecyclerView(仿XListView效果)

可扩展的自定义 CardView 不显示来自 Firebase 的 RecyclerView 的所有内容

Kotlin android中的RecyclerView itemClickListener

带有水平溢出的Android垂直recyclerview

具有自定义数据源偏移量的 Android 分页库 RecyclerView 中的项目

带有 UIImageView 的自定义 UITableViewCell 不显示图像