android - 具有网格布局的回收器视图/项目未显示,而 LayoutManager 具有高度和宽度,并且 getItemCount 返回正确的项目数
问题描述
我在协调器布局中有一个回收器视图,其中一个 GridLayoutManager 设置为垂直和一个自定义适配器。
当布局使用onLayoutChangeListener更改时,列数可以自行调整。
Recycler View 的 Adapter 数据是异步加载的,每次更改时,我都会调用 recyclerview.getAdapter() .notifyDataSetChanged()以确保 Recycler View 显示它。
我在 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);
}
}
这是膨胀的 ViewHolders 的 xml 文件和它在 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>
我在任何地方都没有看到任何报告此错误的问题,所以如果您知道它可能来自哪里,那将非常感激。抱歉,这篇文章很长,我试图尽可能多地删除不必要的代码。希望有人能帮助我!
解决方案
使用addOnGlobalLayoutListener
而不是addOnLayoutChangeListener
.
推荐阅读
- selenium - 不导航分页3并获得陈旧的元素异常
- python - 在python中将二维矩阵转换为Dataframe
- java - 为什么将第二个元素添加到双链表时会发生堆栈溢出?
- spring - 为什么我可以使用构造函数注入而不使用@autowired
- r - 运行 devtools::release() 以准备在 R 中发布包时 git 检查错误
- python - Python数据框:如何返回列中出现的次数?
- nginx - 在nginx上部署gatsby刷新时重定向地址错误并带出端口号?
- amazon-web-services - AWS ENI(弹性网络接口)和NAT网关在路由表配置中的区别
- git - git 分支上的 Dependabot
- java - (Java) 为什么超类可以有子类类型的变量?