I'm trying to create a list of cards that will be generated dynamically because there is some stuff in the card that I need to pull from FireStore. I got it pretty much done but the card shows up sort of twice, the actual card shows up fine but then there is like the card layout in the back with the preset texts and stuff
Update: after some suggestions and help I changed the code, it still doesn't do what I want but I guess its a step in the right direction
here's the code I use to create the card (updated with full 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);
}
Here's the xml of the layout where the cards are actually shown
<?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>
Here's the layout of the card
<?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>
here's how it currently shows in the app
If I dont include the layout of the card in the xml of the activity, the app crashes because it cant find the objects inside the cards to fill in with data, but if I include it apparently it creates one card correctly filled and all the other ones are just filled with the preset data
CodePudding user response:
The issue you're having is based in your AddCard
function. You're inflating the card_view
, but then instead of looking inside the new card_view
(the variable card
) for the views to fill with data, you're looking inside the root view (if you just call findViewById
, it will look inside the root view of the fragment/activity by default).
To remedy this:
- Remove this line from your main view:
<include layout="@layout/sample_card_1" />
, as it's not necessary (your code should dynamically add the cards) - Modify your
AddCard
function, and change these three lines as below:
TextView nameWorker = card.findViewById(R.id.nameWorker);
RatingBar RatingBar = card.findViewById(R.id.ratingBar);
Button submitButton = card.findViewById(R.id.submitButton);
By changing the findViewById
calls to instead call on the card
view you've inflated, you'll stop looking inside the root view (which will solve those crashes you referenced), and instead will fill out the new card with the details you want (which will solve the issue you're having of one card being filled out and the rest being default values).
CodePudding user response:
the thing you missed is you should have added cardview_layout into LinearLayout Vertical, not into CardView
on your activity.xml. so wrap the card_layout.xml with CardView like you did in main.xml(it should be top element instead of ConstraintLayout on your card_layout.xml) and remove below code from main_activity.xml
<androidx.cardview.widget.CardView
android:id="@ id/cardView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
app:cardCornerRadius="20dp"
app:cardElevation="2dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@ id/textView2">
<include
layout="@layout/sample_card_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</androidx.cardview.widget.CardView>
after you remove, add LinearLayout instead with vertical orientation. then add the cardview_layout programmatically into the LinearLayout you have already added.
and use view
instead of directly calling findviewbyıd to prevent crash like below:
TextView nameWorker = view.findViewByID()