动态生成时 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 的根视图。
补救措施:
- 从您的主视图中删除这一行:
<include layout="@layout/sample_card_1" />
,因为它不是必需的(您的代码应该动态添加卡片)
- 修改您的
AddCard
函数,并将这三行更改如下:
TextView nameWorker = card.findViewById(R.id.nameWorker);
RatingBar RatingBar = card.findViewById(R.id.ratingBar);
Button submitButton = card.findViewById(R.id.submitButton);
通过将 findViewById
调用更改为调用您已膨胀的 card
视图,您将不再查看根视图内部(这将解决您引用的那些崩溃),并且相反,将使用您想要的详细信息填写新卡(这将解决您遇到的一张卡被填写而其余为默认值的问题)。
我正在尝试创建一个动态生成的卡片列表,因为卡片中有一些东西需要从 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 的根视图。
补救措施:
- 从您的主视图中删除这一行:
<include layout="@layout/sample_card_1" />
,因为它不是必需的(您的代码应该动态添加卡片) - 修改您的
AddCard
函数,并将这三行更改如下:
TextView nameWorker = card.findViewById(R.id.nameWorker);
RatingBar RatingBar = card.findViewById(R.id.ratingBar);
Button submitButton = card.findViewById(R.id.submitButton);
通过将 findViewById
调用更改为调用您已膨胀的 card
视图,您将不再查看根视图内部(这将解决您引用的那些崩溃),并且相反,将使用您想要的详细信息填写新卡(这将解决您遇到的一张卡被填写而其余为默认值的问题)。