动态生成时 Cardview 显示两次

Cardview shows twice when dynamically generated

我正在尝试创建一个动态生成的卡片列表,因为卡片中有一些东西需要从 FireStore 中提取。我差不多完成了,但卡片出现了两次,实际卡片显示正常,但后面的卡片布局带有预设文本和东西

更新:经过一些建议和帮助,我更改了代码,它仍然没有达到我想要的效果,但我想这是朝着正确方向迈出的一步

这是我用来创建卡片的代码(已更新完整 activity)

public class ScrollingActivity extends AppCompatActivity {

FirebaseFirestore db = FirebaseFirestore.getInstance();
FirebaseAuth fAuth = FirebaseAuth.getInstance();
LinearLayout layout;
String name;

float rating;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_scrolling);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    CollapsingToolbarLayout toolBarLayout = findViewById(R.id.toolbar_layout);
    toolBarLayout.setTitle(getTitle());

    for (int i = 0; i<6; i++){
        addCard(i);
    }

    FloatingActionButton fab = findViewById(R.id.fab);
    fab.setOnClickListener(view -> Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
            .setAction("Action", null).show());

}

private void addCard(int workerNum) {
    layout = findViewById(R.id.thisone);
    View card = getLayoutInflater().inflate(R.layout.sample_card_1, layout, false);

    TextView nameWorker = findViewById(R.id.nameWorker);
    RatingBar RatingBar = findViewById(R.id.ratingBar);
    Button submitButton = findViewById(R.id.submitButton);

    DocumentReference docRef = db.collection("workers").document(String.valueOf(workerNum));
    docRef.get().addOnCompleteListener(task -> {
        if (task.isSuccessful()) {
            DocumentSnapshot document = task.getResult();
            if (document.exists()) {
                Log.d(TAG, "DocumentSnapshot data: " + document.getData());
                name = document.toObject(Classes.Worker.class).getName();
                nameWorker.setText(name);
                rating = document.toObject(Classes.Worker.class).getRating();
                RatingBar.setRating(rating);
            } else {
                Log.d(TAG, "No such document");
            }
        } else {
            Log.d(TAG, "get failed with ", task.getException());
        }
    });

    // perform click event on button
    submitButton.setOnClickListener(v -> {
        DocumentReference changerating = db.collection("workers").document(String.valueOf(workerNum));
        changerating.update("rating", RatingBar.getRating()).addOnSuccessListener(aVoid ->
                Log.d(TAG, "DocumentSnapshot successfully updated!"))
                .addOnFailureListener(e -> Log.w(TAG, "Error updating document", e));
        // get values and then displayed in a toast
        String rating1 = "On a scale of 5 Stars\n New rating = " + RatingBar.getRating();
        Toast.makeText(getApplicationContext(), rating1, Toast.LENGTH_LONG).show();
    });

    layout.addView(card);
}

这是 xml 实际显示卡片的布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 
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="match_parent"
android:fitsSystemWindows="true"
tools:context=".ScrollingActivity">

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/app_bar_height"
    android:fitsSystemWindows="true"
    android:theme="@style/Theme.InternshipThesis.AppBarOverlay">

    <com.google.android.material.appbar.CollapsingToolbarLayout
        android:id="@+id/toolbar_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        app:toolbarId="@+id/toolbar">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/Theme.InternshipThesis.PopupOverlay" />

    </com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".ScrollingActivity"
    tools:showIn="@layout/activity_scrolling">


    <LinearLayout
        android:id="@+id/thisone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="20dp">

        <include layout="@layout/sample_card_1" />
    </LinearLayout>

</androidx.core.widget.NestedScrollView>

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/fab_margin"
    app:layout_anchor="@id/app_bar"
    app:layout_anchorGravity="bottom|end"
    app:srcCompat="@android:drawable/ic_menu_sort_by_size"
    android:contentDescription="@string/main_fab_desc" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

这是卡片的布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/card"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="20dp"
app:cardElevation="2dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp">

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="15dp">

    <com.google.android.material.imageview.ShapeableImageView
        android:id="@+id/imageView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:shapeAppearanceOverlay="@style/roundedImageView"
        android:contentDescription="@string/Desc_Photo_Card1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/sample_worker_1" />

    <TextView
        android:id="@+id/nameWorker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/Text1_Card1"
        android:textSize="20sp"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        android:padding="10dp"/>

    <RatingBar
        android:id="@+id/ratingBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="@+id/imageView"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toBottomOf="@+id/nameWorker" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/submitButton"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:padding="10dp"
        android:text="@string/rating_button"
        android:textColor="#fff"
        android:textSize="20sp"
        android:textStyle="bold"
        app:cornerRadius="20dp"
        app:layout_constraintEnd_toEndOf="@+id/ratingBar"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/ratingBar"
        app:layout_constraintTop_toBottomOf="@+id/ratingBar" />

</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

这是它目前在应用程序中的显示方式

example 1

如果我不在 activity 的 xml 中包含卡片的布局,应用程序会崩溃,因为它找不到卡片中的对象来填充数据,但是如果我包括它显然它会创建一张正确填充的卡,而所有其他卡都只填充了预设数据

您遇到的问题与您的 AddCard 功能有关。您正在膨胀 card_view,但是您不是在新的 card_view(变量 card)内部查看以填充数据的视图,而是在根视图内部查看(如果你只是调用 findViewById,默认情况下它会查看 fragment/activity 的根视图。

补救措施:

  1. 从您的主视图中删除这一行:<include layout="@layout/sample_card_1" />,因为它不是必需的(您的代码应该动态添加卡片)
  2. 修改您的 AddCard 函数,并将这三行更改如下:
    TextView nameWorker = card.findViewById(R.id.nameWorker);
    RatingBar RatingBar = card.findViewById(R.id.ratingBar);
    Button submitButton = card.findViewById(R.id.submitButton);

通过将 findViewById 调用更改为调用您已膨胀的 card 视图,您将不再查看根视图内部(这将解决您引用的那些崩溃),并且相反,将使用您想要的详细信息填写新卡(这将解决您遇到的一张卡被填写而其余为默认值的问题)。