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
example 1
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
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).
Related
I'm doing an application where a list of things has to be displayed, so I created a LinearLayout and programmatically add CardViews to it, there is a function that connects to FireStore database to pull data from it and then the cards get created and added to the LinearLayout.
The data takes a bit to be loaded and that messes with the animation of the cards (The animation given by adding android:animateLayoutChanges="true" to the xml of the LinearLayout).
The final result with animations is clunky and stuttering, is there any way that I could make it smoother? Like maybe making the card wait for the data to be pulled before it gets added to the layout or making a custom animation of some sort that would wait a bit beofre starting.
Here's a video of the current state of the animations:
Example of current behavior of animations
I was asked for code so here it is:
Layout where the cards are added:
<LinearLayout
android:id="#+id/thisone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical">
</LinearLayout>
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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
app:cardCornerRadius="20dp"
app:cardElevation="2dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/linearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="15dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/workerImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:contentDescription="#string/Desc_Photo_Card"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearanceOverlay="#style/roundedImageView"
app:srcCompat="#drawable/worker1" />
<TextView
android:id="#+id/nameWorker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:padding="10dp"
android:text="#string/Text1_Card"
android:textSize="14sp"
app:layout_constraintStart_toEndOf="#+id/workerImage"
app:layout_constraintTop_toTopOf="#+id/workerImage" />
<RatingBar
android:id="#+id/ratingBar"
style="#style/Widget.AppCompat.RatingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="0.4"
android:scaleY="0.4"
app:layout_constraintBottom_toBottomOf="#+id/nameWorker"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/nameWorker"
app:layout_constraintTop_toTopOf="#+id/nameWorker" />
<com.google.android.material.button.MaterialButton
android:id="#+id/submitButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="8dp"
android:padding="10dp"
android:text="#string/rating_button"
android:textColor="#fff"
android:textSize="10sp"
android:textStyle="bold"
app:cornerRadius="20dp"
app:layout_constraintEnd_toEndOf="#+id/nameWorker"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/nameWorker"
app:layout_constraintTop_toBottomOf="#+id/nameWorker"
tools:ignore="SmallSp" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="#string/available_at"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/workerImage" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="Currently not available"
app:layout_constraintBottom_toBottomOf="#+id/textView2"
app:layout_constraintStart_toEndOf="#+id/textView2"
app:layout_constraintTop_toTopOf="#+id/textView2"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Function that fills the card with informations and adds it to the layout:
#SuppressLint("SetTextI18n")
private void addCard(int workerNum) {
View card = getLayoutInflater().inflate(R.layout.card_layout, layout, false);
TextView nameWorker = card.findViewById(R.id.nameWorker);
RatingBar RatingBar = card.findViewById(R.id.ratingBar);
Button submitButton = card.findViewById(R.id.submitButton);
ImageView workerImage = card.findViewById(R.id.workerImage);
TextView first_available_slot = card.findViewById(R.id.textView3);
String workerImgSrc = "worker"+ workerNum; // this is image file name
String PACKAGE_NAME = getApplicationContext().getPackageName();
int imgId = getResources().getIdentifier(PACKAGE_NAME+":drawable/"+workerImgSrc , null, null);
DocumentReference docRef = db.collection("workers").document(String.valueOf(workerNum));
docRef.get().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
// All the informations about the worker are filled out
name = (Objects.requireNonNull(document.toObject(Classes.Worker.class))).getName();
nameWorker.setText(name);
rating = (Objects.requireNonNull(document.toObject(Classes.Worker.class))).getRating();
RatingBar.setRating(rating);
workerImage.setImageBitmap(BitmapFactory.decodeResource(getResources(),imgId));
// Checks if the worker is available and changes the Textview accordingly.
// If there are no available appointments for that worker, the TextView will be
// left unchanged, which means that it till display "Currently not available"
db.collection("workers")
.document(String.valueOf(workerNum))
.collection("schedule")
.whereEqualTo("booked", "false")
.get()
.addOnCompleteListener(task1 -> {
if (task1.isSuccessful()) {
for (QueryDocumentSnapshot document1 : task1.getResult()) {
int day = Integer.parseInt(
Objects.requireNonNull(
document1.getString("day")
)
);
int hour = Integer.parseInt(
Objects.requireNonNull(
document1.getString("hour")
)
);
if(day > currentDay) {
first_available_slot.setText(
"Currently available. Click to see when")
;
}
if(day == currentDay) {
if(hour > currentHour) {
first_available_slot.setText(
"Currently available. Click to see when")
;
}
}
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
);
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
});
// This button allows the user to change the rating of the worker and correctly save the
// changes to the database
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))
;
String rating1 = "On a scale of 5 Stars\n New rating = " + RatingBar.getRating();
Toast.makeText(getApplicationContext(),
rating1, Toast.LENGTH_LONG)
.show()
;
});
card.setOnClickListener(view -> openWorkerActivity(workerNum));
layout.addView(card);
}
My issue is: ui freezes when recycler view adapter start listening
my xml Code is as below
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainAdminPackage.AdminDashboardActivity">
<!--Navigation Drawer Setup-->
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/home_background"
app:headerLayout="#layout/menu_header_design"
app:menu="#menu/main_menu" />
<LinearLayout
android:id="#+id/contentViewLl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/home_background"
android:orientation="vertical">
<!--Navigation Menu and Fab Layout Setup-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="68dp"
android:padding="20dp">
<!--Menu Button-->
<ImageView
android:id="#+id/menuIcon"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="4dp"
android:layout_centerVertical="true"
android:focusable="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:src="#drawable/ic_menu_icon_dark_gray"
app:tint="#color/icon_color"
android:contentDescription="#null"/>
<!--FAB Layout System-->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/addQuestionPollCl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="#+id/menuIcon"
android:minHeight="68dp">
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>
<!--Nested Scroll View-->
<androidx.core.widget.NestedScrollView
android:id="#+id/dashboardNestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<!--Main Container Layout-->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--LAYOUT FOR SEARCH WINDOW AND START DIALOG-->
<RelativeLayout
android:id="#+id/searchAndSloganRl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
</RelativeLayout>
<!--CATEGORIES BUTTON-->
<LinearLayout
android:id="#+id/categoryButtonsLl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:orientation="horizontal"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/searchAndSloganRl"
app:layout_constraintBottom_toBottomOf="parent">
</LinearLayout>
<!--FEATURED COURSE LAYOUT-->
<RelativeLayout
android:id="#+id/featuredCourseRl"
android:visibility="visible"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginBottom="10dp"
android:background="#color/banner_background_light"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/categoryButtonsLl"
app:layout_constraintBottom_toBottomOf="parent">
<!--Banner-->
<!--Recycler View for Featured Courses-->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/featuredCoursesRv"
android:layout_width="match_parent"
android:layout_height="300dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_toEndOf="#id/featuredBackground"
android:background="#color/home_background"
tools:listitem="#layout/row_featured_courses" />
</RelativeLayout>
<!--NEWS FEED-->
<androidx.appcompat.widget.LinearLayoutCompat
android:visibility="visible"
android:id="#+id/newsFeedMiniLlc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:minHeight="100dp"
android:orientation="vertical"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/featuredCourseRl"
app:layout_constraintBottom_toBottomOf="parent">
<!--News Feed Recycler View-->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/newsFeedRv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="horizontal"
android:background="#color/home_background"
tools:listitem="#layout/row_news_feed_dashboard" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!--NOTES CATEGORIES-->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/notesCategoryLlc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="vertical"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/newsFeedMiniLlc"
app:layout_constraintBottom_toBottomOf="parent">
</androidx.appcompat.widget.LinearLayoutCompat>
<!--ASK QUESTION RECYCLER VIEW LAYOUT-->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/askedQuestionMiniLlc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:orientation="vertical"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/notesCategoryLlc"
app:layout_constraintBottom_toBottomOf="parent">
<!--Recycler View for Asked Questions-->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/askQuestionRv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="vertical"
tools:itemCount="10"
android:nestedScrollingEnabled="false"
tools:listitem="#layout/row_asked_question" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
java code for recycler views
//For hiding the FAB when nest scroll is scrolled
dashboardNestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener(){
#Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY){
//For Adapters to Start listening
if(scrollY - oldScrollY != 0) {
if(isVisible(newsFeedMiniLlc)) {
indexOtherPost++;
if(indexOtherPost == 1) {
adapterNewsFeedListFireStoreDashBoard.startListening();
Log.d("NESTED_CHILD", "onScrollChange: indexOtherPost: " + indexOtherPost);
}
}
//Log.d("NESTED_CHILD", "onScrollChange: otherPostMiniLlc: " + isVisible(otherPostMiniLlc));
if(isVisible(askedQuestionMiniLlc)) {
indexAskedQuestion++;
if(indexAskedQuestion == 1) {
adapterAskedQuestionsFireStore.startListening();
Log.d("NESTED_CHILD", "onScrollChange: indexAskedQuestion: " + indexAskedQuestion);
}
}
//Log.d("NESTED_CHILD", "onScrollChange: askedQuestionMiniLlc: " + isVisible(askedQuestionMiniLlc));
}
}
});
//Function for getting Visibility of any View or Layout on the Screen
private static boolean isVisible(final View view) {
if (view == null) {
return false;
}
if (!view.isShown()) {
return false;
}
final Rect actualPosition = new Rect();
view.getGlobalVisibleRect(actualPosition);
int widthPixels = Resources.getSystem().getDisplayMetrics().widthPixels;
int heightPixels = Resources.getSystem().getDisplayMetrics().heightPixels;
final Rect screen = new Rect(0, 0, widthPixels, heightPixels);
return actualPosition.intersect(screen);
}
//For LOADING ASK QUESTIONS
private void loadAskQuestions(){
//for question Recycler view
LinearLayoutManager askQuestionLayoutManager = new LinearLayoutManager(getApplicationContext());
askQuestionLayoutManager.setReverseLayout(false);
askQuestionLayoutManager.setStackFromEnd(false);
askQuestionLayoutManager.setOrientation(RecyclerView.VERTICAL);
askQuestionRv.setLayoutManager(askQuestionLayoutManager);
//get all Question limited to last 10 questions
Query query = FirebaseFirestore.getInstance()
.collection("Asked Questions")
.orderBy("questionId", Query.Direction.DESCENDING)
.limit(10);
FirestoreRecyclerOptions<ModelAskedQuestion> options = new FirestoreRecyclerOptions.Builder<ModelAskedQuestion>()
.setQuery(query, ModelAskedQuestion.class)
.build();
adapterAskedQuestionsFireStore = new AdapterAskedQuestionsFireStore(this, options);
askQuestionRv.setAdapter(adapterAskedQuestionsFireStore);
}
ui freezes when ask question recycler view adapter start listening and ui only freezes for few seconds until all data is loaded in recycler view.
Any one have any solutions ???
More elaboration of the Issue:
1)I have three recycler view under this layout: Two top most Horizontal and last one Vertical in direction.
2)As this is my main dashboard. I have put nested scroll view listener for adapters to start listening when the particular layout containing that recycler view appears on the screen. Top most two adapters and their corresponding recycler views are working perfectly fine.
But when the last recycler view which is vertical in Direction, appears on the screen, It freezes the entire UI, as its adapter starts listening, for few seconds(aprrox. 1-2 seconds).
In this, adapter loads only last 10 items from the server.
I have tried:
1). Fixing the hieght of recyler view.
2). Fixing the height of Layout containing that recycler view.
3). Changed the Main Container Layout From Linear Layout to Constraint Layout.(As It was suggested in one of the comments under that thread(mentioned at the end of this thread)).
4). Tried android:nestedScrollingEnabled="false".
5). Tried app:layout_behavior="#string/appbar_scrolling_view_behavior".
Nothing has worked for this particular problem.
How to get rid of this this freezing of Ui. It should kept scrolling along the items get recycled in recycler view.
It could be same question asked in this thread.
RecyclerView inside NestedScrollview alternative
I am loading some contents from Firebase and also using FirebaseRecyclerAdapter .
This is the Function which shows data from Firebase successfully :
public void showNotifications() {
databaseReference = FirebaseDatabase.getInstance().getReference("Notifications");
databaseReference.keepSynced(true);
options = new FirebaseRecyclerOptions.Builder<NotificationModel>()
.setQuery(FirebaseDatabase.getInstance().getReference("Notifications"), NotificationModel.class)
.build();
notifRecyclerView.setLayoutManager(new LinearLayoutManager(this));
notificationAdaper = new NotificationAdaper(options, NotificationActivity.this);
notifRecyclerView.setAdapter(notificationAdaper);
checkEmpty(); //will show empty image when recyclerView is empty
}
This is my checkEmpty() method :
private void checkEmpty() {
if (notificationAdaper.getItemCount() == 0) {
Log.e("Item count", String.valueOf(notificationAdaper.getItemCount()));
no_notif.setVisibility(View.VISIBLE);
} else {
no_notif.setVisibility(View.GONE);
}
}
Here is the UI code :
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
android:background="#android:color/white"
tools:context="com.devapps.NotificationActivity">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
app:theme="#style/ToolbarTheme">
<TextView
android:id="#+id/toolbarTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:text="Notifications"
android:textColor="#android:color/white"
android:textSize="18sp"
android:textStyle="bold"
android:visibility="visible" />
</androidx.appcompat.widget.Toolbar>
<ImageView
android:id="#+id/no_notif"
android:layout_width="260dp"
android:layout_height="260dp"
android:visibility="gone"
android:layout_centerInParent="true"
android:scaleType="centerCrop"
android:src="#drawable/nonotification" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/notifRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar" />
</RelativeLayout>
The Empty Image Placeholder is always visible even when there is an Item in Firebase Database. How to fix it.
Everytime i am getting E/Item count: 0 even when there is an Item in Firebase Database.
May be you are just altering the visibility of empty view(which you are using to notify user) and not hiding the other views. Like you have recycler view so you need to hide that and view empty message otherwise the message view may be behind the recycler view and hence it is not visible.
Solution
Hide other views on that particular screen
private void checkEmpty() {
if (notificationAdaper.getItemCount() == 0) {
Log.e("Item count", String.valueOf(notificationAdaper.getItemCount()));
no_notif.setVisibility(View.VISIBLE);
notifRecyclerView.setVisibility(View.GONE);
} else {
no_notif.setVisibility(View.GONE);
notifRecyclerView.setVisibility(View.VISIBLE);
}
}
NOTE: notifRecyclerView is the id of recycler view...... I have used it for reference..... if you have declared recycler view with another name in the file , then use that name in lieu of notifRecyclerView
You can use this method to get Recycler View Count
recyclerView.getAdapter().getItemCount();
EDITED
The examples in google searches and the android documentation are basic, and my question is more complex.
What I do not know, is how to put multiple components together and turn it into a single component. CardView + LinearLayout + TextView + ImageView = Custom View.
If I have a basic example, of cardview with at least one button and a space for external content. It would be enough for me to figure out how to do the rest. This within the cardview extension class, because I also do not know how the extension will understand where to create the components
EDITED 2
Example
QUESTION
I was trying to create a method of using Cardview with an expandable button, and I was able to do this in XML. But I wanted to be able to create a library so I could reuse it in other cases.
I'll show you the source code of what I did.
Layout XML
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="vertical">
<LinearLayout
android:id="#+id/cwlltitulobtn"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:orientation="horizontal">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#### TITLE OF BUTTON ####"
android:textSize="18sp"
android:textStyle="bold"/>
<ImageView
android:id="#+id/imgarrowdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:scaleType="fitEnd"
android:visibility="visible"
app:srcCompat="#drawable/ic_keyboard_arrow_down_black_24dp" />
<ImageView
android:id="#+id/imgarrowup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:scaleType="fitEnd"
android:visibility="gone"
app:srcCompat="#drawable/ic_keyboard_arrow_up_black_24dp" />
</LinearLayout>
<LinearLayout
android:id="#+id/cwllconteudo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:orientation="vertical"
android:visibility="gone">
<!-- ########################################
######## CARDVIEW CONTENT HERE #########
########################################-->
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
Java code
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.cwlltitulobtn).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CVOpenCloseBTN();
}
});
}
public void CVOpenCloseBTN(){
ImageView arrowdown = (ImageView) findViewById(R.id.cvimgarrowdown);
ImageView arrowup = (ImageView) findViewById(R.id.cvimgarrowup);
LinearLayout pagecontent = (LinearLayout) findViewById(R.id.cwllconteudo);
if (conteudopage .getVisibility() == View.GONE) {
// it's collapsed - expand it
pagecontent.setVisibility(View.VISIBLE);
arrowdown.setVisibility(View.GONE);
arrowup.setVisibility(View.VISIBLE);
} else {
// it's expanded - collapse it
pagecontent.setVisibility(View.GONE);
arrowdown.setVisibility(View.VISIBLE);
arrowup.setVisibility(View.GONE);
}
}
}
My idea is that I can transform all this part of the xml and java code to be used in this way and faster, than to have to always repeat again:
<br.com.samantabiblioteca.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="5dp"
app:titulo="#### TITLE OF BUTTON ####">
<!-- ########################################
######### CARDVIEW CONTENT HERE ########
########################################-->
</br.com.samantabiblioteca.CardView>
Is it possible to do this?
I am looking for a way to create a Toolbar likes a lot of apps with name and a photo.
I need to allow touch, if user touchs the area near the name or the image it will change activity.
Example:
You just need to put the ImageView and TextView inside your Toolbar, he is just a ViewGroup. For example:
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="#dimen/abc_action_bar_default_height_material">
<LinearLayout
android:id="#+id/linearlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/your_image_description"
android:src="#drawable/your_image"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/your_string" />
</LinearLayout>
</android.support.v7.widget.Toolbar>
After that, you can set the click event on your activity:
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linearlayout);
linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "teste", Toast.LENGTH_LONG).show();
}
});
Run on the emulator to see the result:
Hope this helps.