带有网格布局的回收器视图/当LayoutManager具有高度和宽度时未显示的项目和getItemCount返回正确的项目数

时间:2018-06-11 11:48:08

标签: android android-layout android-recyclerview gridlayoutmanager

我在协调器布局中有一个Recycler View,GridLayoutManager设置为vertical,并且是自定义适配器。

当布局使用 onLayoutChangeListener 更改时,列数可以自行调整。

Recycler View的Adapter数据是异步加载的,每次更改时,我都会调用recyclelerview.getAdapter() .notifyDataSetChanged()来确保Recycler View显示它。

我在Android Lollipop或更多版本上运行应用程序,build.gradle具有支持库的这种实现:

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

出于某种原因,似乎数据已正确加载,并且根据加载的数据布局高度和宽度是正确的,但网格内的卡片不可见,这里是截图回收者视图的范围必将证明我的观点:

The recycler view has height that changes when the inserted data changes but the items are not visible
回收器视图的高度在插入的数据发生更改但项目不可见时会发生变化

以下是包含Recycler视图的活动的代码:

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

以下是膨胀的ViewHolders的xml文件以及Android Studio中的内容截图:

Item Layout inflated by the Adapter
适配器充气的项目布局

<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>

最后,这是Recycler view 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 个答案:

答案 0 :(得分:-1)

使用window = tkinter.Tk() a = tkinter.simpledialog.askstring("Prompt", "Enter Separator", parent = window) 代替addOnGlobalLayoutListener