Recycler View с Grid Layout / Элементы не отображаются, в то время как LayoutManager имеет Height и Width и getItemCount возвращает правильное количество элементов

У меня есть Recycler View внутри Layout Coordinator Layout с GridLayoutManager, установленным в вертикальное положение, и пользовательским адаптером.

Количество столбцов может изменяться самостоятельно при изменении макета с помощью onLayoutChangeListener.

Данные адаптера представления Recycler загружаются асинхронно, и каждый раз, когда они меняются, я вызываю recyclerview.getAdapter ().notifyDataSetChanged (), чтобы убедиться, что представление Recycler отображает их.

Я запускаю приложение на Android Lollipop или более, и build.gradle имеет такую ​​реализацию библиотеки поддержки:

implementation 'com.android.support:recyclerview-v7:27.0.2'

По какой-то причине кажется, что данные загружены правильно, и что высота и ширина макета являются правильными в соответствии с загруженными данными, но карты внутри сетки не видны, вот скриншот границ представления рециркулятора, чтобы доказать мою точку зрения:

Высота окна рециркуляции изменяется при изменении вставленных данных, но элементы не отображаются
Высота окна рециркуляции изменяется при изменении вставленных данных, но элементы не отображаются

Вот код для действия, содержащего представление переработчика:

public class SessionChildrenActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    public static ArrayList<SessionChild> ChildrenList;

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

        ChildrenList = new ArrayList<>();

        recyclerView = findViewById(R.id.children_gridview);
        recyclerView.setAdapter(new ChildrenAdapter());

        final Context c = this;

        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        GridLayoutManager layoutManager = new GridLayoutManager(c,(int)(displayMetrics.widthPixels / (getResources().getDimension(R.dimen.cell_width))),GridLayoutManager.VERTICAL,true);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
                recyclerView.setLayoutManager(new GridLayoutManager(c,(int)(displayMetrics.widthPixels / (getResources().getDimension(R.dimen.cell_width))),GridLayoutManager.VERTICAL,true));
            }
        });
        //Start of a query (Google Firestore) that gets the children associated with the session, just showing you the part that adds the retrieved child to the list given to the adapter
        ...
        if(ChildrenList.indexOf(child) == -1){
            ChildrenList.add(child);
            Collections.sort(ChildrenList,new Comparator<SessionChild>() {
                @Override
                public int compare(SessionChild sc1, SessionChild sc2)
                {
                    return sc1.getChild().getNickname().compareTo(sc2.getChild().getNickname());
                }
            });
            recyclerView.getAdapter().notifyDataSetChanged();
        }
        ...
    }
}

Вот код для пользовательского адаптера:

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


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

    public ChildrenAdapter() {
        super();
    }

    @Override
    public void onBindViewHolder(ViewHolder mViewHolder, int position) {
        mViewHolder.firstname.setText(SessionChildrenActivity.ChildrenList.get(position).getChild().getNickname());
        Calendar birthdate = Calendar.getInstance();
        if(SessionChildrenActivity.ChildrenList.get(position).getChild().getPersonalInfo().getBirthdate() != null){
            birthdate.setTime(SessionChildrenActivity.ChildrenList.get(position).getChild().getPersonalInfo().getBirthdate());
            mViewHolder.age.setText(getAge(birthdate));
        }
        else
            mViewHolder.age.setText("?");
        if(SessionChildrenActivity.ChildrenList.get(position).getChild().getPhotoURL() != null && !SessionChildrenActivity.ChildrenList.get(position).getChild().getPhotoURL().equals("") && mViewHolder.image.getDrawingCache() == null) {
            new DownloadImageTask(mViewHolder.image).execute(SessionChildrenActivity.ChildrenList.get(position).getChild().getPhotoURL());
        }
    }

    @Override
    public int getItemCount() {
        return SessionChildrenActivity.ChildrenList.size();
    }

    @Override
    public long getItemId(int position) {
        return (long) position;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        private TextView firstname;
        private ImageView image;
        private TextView age;
        private ConstraintLayout card;

        public ViewHolder(View v) {
            super(v);
            firstname = v.findViewById(R.id.firstname);
            age = v.findViewById(R.id.age);
            image = v.findViewById(R.id.thumb_img);
            card = v.findViewById(R.id.cardview);
            card.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(v.getContext(),child_details.class);
                    SessionChild sessionChild = SessionChildrenActivity.ChildrenList.get(((ViewGroup)v.getParent()).indexOfChild(v));
                    intent.putExtra("session_child",sessionChild);
                    v.getContext().startActivity(intent);
                }
            });
        }
    }

    private String getAge(Calendar dob){
        Calendar today = Calendar.getInstance();

        int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR);

        if (today.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR)){
            age--;
        }
        return String.valueOf(age);
    }

    private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
        ImageView bmImage;

        public DownloadImageTask(ImageView bmImage) {
            this.bmImage = bmImage;
        }

        protected Bitmap doInBackground(String... urls) {
            String urldisplay = urls[0];
            Bitmap mIcon11 = null;
            try {
                InputStream in = new java.net.URL(urldisplay).openStream();
                mIcon11 = BitmapFactory.decodeStream(in);
            } catch (Exception e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return mIcon11;
        }

        protected void onPostExecute(Bitmap result) {
            bmImage.setImageBitmap(result);
        }
    }

    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }
}

Вот xml-файл раздутых ViewHolders и скриншот того, как он выглядит в Android Studio:

Расположение элементов надувается адаптером
Расположение элементов надувается адаптером

<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/cardview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/card"
    android:foreground="?attr/selectableItemBackground">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:elevation="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/age"
            style="@android:style/TextAppearance.Material.Medium"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:paddingEnd="8dp"
            android:paddingStart="4dp"
            android:text="@string/whatever"
            android:textColor="@android:color/white"
            app:layout_constraintBottom_toBottomOf="@+id/thumb_img"
            app:layout_constraintEnd_toEndOf="parent" />

        <TextView
            android:id="@+id/firstname"
            style="@android:style/TextAppearance.Material.Medium"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:paddingEnd="4dp"
            android:paddingStart="8dp"
            android:text="@string/note"
            android:textColor="@android:color/white"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="@+id/thumb_img"
            app:layout_constraintEnd_toStartOf="@+id/age"
            app:layout_constraintStart_toStartOf="parent" />

        <com.makeramen.roundedimageview.RoundedImageView
            android:id="@+id/thumb_img"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:contentDescription="@string/whatever"
            android:scaleType="centerCrop"
            app:layout_constraintDimensionRatio="H,1:1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:riv_corner_radius="8dp"
            app:riv_oval="false" />

        <ImageView
            android:id="@+id/delete_confirm"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginEnd="2dp"
            android:layout_marginTop="2dp"
            android:contentDescription="@string/whatever"
            android:visibility="invisible"
            app:layout_constraintBottom_toBottomOf="@+id/guideline10"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/fui_done_check_mark" />

        <ImageView
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:contentDescription="@string/whatever"
            android:src="@drawable/card_bottom"
            app:layout_constraintBottom_toBottomOf="@+id/thumb_img"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/firstname">

        </ImageView>

        <android.support.constraint.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.8" />

        <android.support.constraint.Guideline
            android:id="@+id/guideline10"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.2" />

    </android.support.constraint.ConstraintLayout>

</android.support.constraint.ConstraintLayout>

И, наконец, вот код для представления переработчика XML:

<RelativeLayout 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:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/children_gridview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:nestedScrollingEnabled="false">

    </android.support.v7.widget.RecyclerView>

</RelativeLayout>

Я не видел ни одной проблемы, сообщающей об этой ошибке нигде, так что, если у вас есть представление о том, откуда она может появиться, это было бы очень признательно. Извините за длинный пост, я попытался удалить как можно больше ненужного кода. Надеюсь, кто-нибудь сможет мне помочь!

1 ответ

Я думаю, что проблема заключается в последнем макете. Удалить nestedScrollingEnabled и установить все heights в match_parent (вместо wrap_content).

Вы отлаживали то, что установлено в качестве диапазона? Вы пытались упростить макет элемента (уродливый линейный макет со всем содержимым или пошаговое удаление элементов вида элемента)?

Кстати: весь код немного нечист. Вы можете использовать привязку данных, Picasso/ Glide для загрузки изображения, локальную переменную в адаптере для содержимого layoutManager.setSpanCount() вместо создания новой каждый раз, и вы можете использовать Listener вместо взаимодействия с другими компонентами из адаптер.

Использование addOnGlobalLayoutListener вместо addOnLayoutChangeListener,

Другие вопросы по тегам