I have created a Recycler view in my fragment_add_friends.xml like below
<android.support.v7.widget.RecyclerView
android:id="#+id/all_user_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
and I created all_user_display_layout.xml file for display each user like below
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/all_user_image">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/all_user_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="full name"/>
<TextView
android:id="#+id/all_user_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="user status"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
In my AddFriendsFragment.java I got the recycler view like below in my on create view method
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_add_friends, container, false);
all_user_list = (RecyclerView) v.findViewById(R.id.all_user_list);
all_user_list.setHasFixedSize(true);
all_user_list.setLayoutManager(new LinearLayoutManager(getActivity()));
return v;
}
and I have created a helper class that have Strings name, status,
image and there getters setters and constructor and empty construcor because I have to retrieve those data and xml file those things in is all_user_display_layout.xml
and I got the database reference like below
databaseReference = FirebaseDatabase.getInstance().getReference().child("users");
and I create the onViewCreated method like below
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
after that what are the things that I have to do to get data from
fireabse to recycler view
please help me im new to these stuff
Assuming that users node is a direct child of your Firebase database root, to get the name, image and status, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = rootRef.child("users");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List <String> list = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String name = ds.child("name").getValue(String.class);
String image = ds.child("image").getValue(String.class);
String status = ds.child("status").getValue(String.class);
list.add(name + " / " + image + " / " + status);
Log.d("TAG", name + " / " + image + " / " + status);
}
Log.d("TAG", list);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
usersRef.addListenerForSingleValueEvent(eventListener);
Your output will be:
Hemal / https... / Busy
Jake Stewart / https... / Busy
Remove these lines from onCreateView
all_user_list = (RecyclerView) v.findViewById(R.id.all_user_list);
all_user_list.setHasFixedSize(true);
all_user_list.setLayoutManager(new LinearLayoutManager(getActivity()));
Add the following code in onViewCreated
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
FirebaseRecyclerViewAdapter<<Your-Helper-Class>, ViewHolder> adapter;
ref = new Firebase("https://<yourapp>.firebaseio.com");
RecyclerView recycler = (RecyclerView) findViewById(R.id.all_user_list);
recycler.setHasFixedSize(true);
recycler.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new FirebaseRecyclerViewAdapter<<Your-Helper-Class>, ViewHolder>(<Your-Helper-Class>.class, android.R.layout.all_user_display_layout.xml, ViewHolder.class, mRef) {
public void populateViewHolder(ViewHolder viewHolder, <Your-Helper-Class> helper) {
Picasso.with(context).load(helper.getImage()).into(viewHolder.image);
viewHolder.name.setText(helper.getName());
viewHolder.status.setText(helper.getStatus());
}
};
recycler.setAdapter(mAdapter);
}
private static class ViewHolder extends RecyclerView.ViewHolder {
CircleImageView image;
TextView name;
TextView status;
public ChatMessageViewHolder(View itemView) {
super(itemView);
image = (TextView)itemView.findViewById(android.R.id.all_user_image);
name = (TextView)itemView.findViewById(android.R.id.all_user_name);
status = (TextView) itemView.findViewById(android.R.id.all_user_status);
}
}
Also use Picasso for loading image in imageview. Add these lines in your build.gradle.
compile 'com.squareup.picasso:picasso:2.5.2'
Related
I am trying to create a tablayout with 3 fragments. One of them is AllPostFragment. Initially the fragment is set to show - "No new food posts!". After onCreateView, i wish to fetch the posts from the database and update them inside the listview. Here is the code for AllPostFragment.
public class AllPostFragment extends ListFragment{
String Username;
ArrayList<String> posts = new ArrayList<>();
public AllPostFragment(String Username)
{
this.Username=Username;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_all_post_fragment, container, false);
return rootView;
}
#Override
public void onResume() {
super.onResume();
FirebaseDatabase firebaseDatabase=FirebaseDatabase.getInstance();
DatabaseReference postref=firebaseDatabase.getReference("posts");
postref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot snap : snapshot.getChildren()){
String s="Type: "+snap.child("type").getValue()+"\n"+"Name: "+snap.child("name").getValue()+"\n"+"Phone: "+snap.child("phoneNo").getValue()+"\n"+"City: "+snap.child("city").getValue()+"\n"+"PostedBy: "+snap.child("Username").getValue();
posts.add(s);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
ArrayAdapter<String> adapter=new ArrayAdapter<(getListView().getContext(),android.R.layout.simple_list_item_1,posts);
setListAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
I am updating the posts onResume but i want to update them before the first view is loaded. But when I try to set the arrayadapter in the onCreateView method, it says view not created.The code for the xml file is als attached below.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".AllPostFragment"
xmlns:android="http://schemas.android.com/apk/res/android">
<ListView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#AEC5EB"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:id="#android:id/list"/>
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="#android:id/empty"
android:text="No new food posts!"/>
</RelativeLayout>
I come to ask you for guidance with this, I have a recycler view, and what I want is that while the recyclerview is filled from the cloud firebase, a circular progressBar appears, and as soon as it loads, it disappears and the Recyclerview is loaded. I have already tried seeing various orientations around here but I cannot find it, with my code the progressbar is placed in a GONE way immediately, I imagine that you have to implement a ** CALLBACK ** or something like that, but no idea, I would appreciate that They will guide me a little with that of the CALLBACK, to see how I could implement it.
Borrow a photo and video from other users so they understand what I want to do
Demo Imagen ---> https://i.stack.imgur.com/JbLSi.png
Here is a video with what I want ---> Video
And here is the code that I am using
-------------------- Layout ------------------
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MasvotingFragment">
<ProgressBar
android:id="#+id/progress_bar"
style="?android:progressBarStyle"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="60dp"
android:visibility="gone"
android:layout_marginTop="5dp"
android:id="#+id/recyclerview_id">
</androidx.recyclerview.widget.RecyclerView>
</FrameLayout>
--------------------- Java ---------------------------
public class MasvotingFragment extends Fragment {
public MasvotingFragment() {
// Required empty public constructor
}
private FirebaseFirestore mDatabase;
private RecyclerView recyclerView ;
private Parcelable listState;
private RecyclerViewMasvotados mAdapter;
private ProgressBar mProgressBar;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_masvoting, container, false);
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
mDatabase = FirebaseFirestore.getInstance();
recyclerView = view.findViewById(R.id.recyclerview_id);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mProgressBar = view.findViewById(R.id.progress_bar);
basedatocall();
if(listState!=null){
listState = Objects.requireNonNull(savedInstanceState).getParcelable("ListState");
}
}
private void basedatocall() {
Query query = mDatabase.collection("Post")
.orderBy("totales", Query.Direction.DESCENDING);
FirestoreRecyclerOptions<masvotados> options = new FirestoreRecyclerOptions.Builder<masvotados>()
.setQuery(query, masvotados.class).build();
mAdapter = new RecyclerViewMasvotados(options);
mAdapter.notifyDataSetChanged();
recyclerView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
mAdapter.startListening();
recyclerView.setAdapter(mAdapter);
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onStart() {
super.onStart();
Objects.requireNonNull(recyclerView.getLayoutManager()).onRestoreInstanceState(listState);
mAdapter.startListening();
}
#Override
public void onStop() {
super.onStop();
if (mAdapter !=null){
mAdapter.stopListening();
}
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("ListState", Objects.requireNonNull(recyclerView.getLayoutManager()).onSaveInstanceState());
}
}
In advance Thank you all for your help, a hug
I have a SwipeRefreshLayout on my RecyclerView, I want the items to refresh as the user scrolls down instead of just pulling down from the top every time. I need something like Instagram or facebook that the posts load as the user is scrolling down. So that the user doesn't have to keep coming up again and again to refresh and load more posts
Here is my XML code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/bar">
</com.google.android.material.appbar.AppBarLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/bar">
<androidx.core.widget.NestedScrollView
android:id="#+id/scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/bar">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/bar"
android:id="#+id/recycler_view_posts"/>
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</RelativeLayout>
Here is my fragment code:
public class HomeFragment extends Fragment {
//POSTS
private RecyclerView recyclerViewPosts;
private PostAdapter postAdapter;
private List<Post> postLists;
private List<String> followingList;
private Context mContext;
private static final int TOTAL_NUMBER_OF_ITEMS_TO_LOAD = 5;
private SwipeRefreshLayout swipeRefreshLayout;
private int currentPage = 1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
//POSTS
recyclerViewPosts = view.findViewById(R.id.recycler_view_posts);
recyclerViewPosts.setHasFixedSize(true);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerViewPosts.setLayoutManager(linearLayoutManager);
postLists = new ArrayList<>();
postAdapter = new PostAdapter(getContext(), postLists);
recyclerViewPosts.setAdapter(postAdapter);
swipeRefreshLayout = view.findViewById(R.id.swiperefresh);
checkFollowing();
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener(){
#Override
public void onRefresh() {
currentPage++;
postLists.clear();
readPosts();
}
});
return view;
}
private void readPosts() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
Query postQuery = reference.limitToLast(currentPage * TOTAL_NUMBER_OF_ITEMS_TO_LOAD);
postQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
postLists.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
postLists.add(post);
}
postAdapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
I would recommend you to use the Paging Library from Android. It is design for it and you have a nice tutorial for it here. It might be a bit of work but it is worth it.
I am new to programming in androidstudio/java so I'm looking for some assistance. I'm currently trying to make an app that is similar to facebook messenger by using firebase and android studio. I'm at the stage where I am trying to create the layout for the ChatActivity (see code below). However, I'm having some issues with showing new messages at the bottom of the screen.
I have tried using ".setStackFromEnd(true);" but setting it either true or false, the text still appears at the top! (see images)
Code:
ChatActivity is as follows:
public class ChatActivity extends AppCompatActivity {
//Firebase variables
private FirebaseAuth mAuth;
private DatabaseReference mDatabaseUser, mDatabaseChat;
private FirebaseStorage mStorage;
private StorageReference mStorageReference;
//Recyclerview variables
private RecyclerView recyclerView;
private RecyclerViewChatAdapter mChatAdapter;
//Variables for users
private String userId,friendId,namefriend,chatId;
private CircleImageView mImageFriend;
private ArrayList<ChatObject> resultsChat = new ArrayList<>();
private Button mSendButton;
private EditText mSendText;
private TextView mNameFriend;
//Linear layout manager
private LinearLayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
//prevent opening keyboard automatically
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
//Set firebase variables
mAuth = FirebaseAuth.getInstance();
userId = mAuth.getCurrentUser().getUid();
friendId = getIntent().getExtras().getString("friendId");
namefriend = getIntent().getExtras().getString("friendName");
mDatabaseUser = FirebaseDatabase.getInstance().getReference().child("Friends").child(userId).child("Friendlist").child(friendId).child("chatId");
mDatabaseChat = FirebaseDatabase.getInstance().getReference();
mStorage = FirebaseStorage.getInstance();
mStorageReference = mStorage.getReference();
//Get findviewbyId's
recyclerView = (RecyclerView) findViewById(R.id.ChatActivity_recyclerview);
mSendButton = (Button) findViewById(R.id.ChatActivity_Send);
mSendText = (EditText) findViewById(R.id.ChatActivity_SendText);
mNameFriend = (TextView) findViewById(R.id.ChatActivity_Name);
mImageFriend = (CircleImageView) findViewById(R.id.ChatActivity_ImageFriend);
//Filling in recyclerview and adapter
FillInRecyclerView();
//Set name
mNameFriend.setText(" "+namefriend);
//set picture
StorageReference profileRef = mStorageReference.child("profilepictures/"+friendId);
GlideApp.with(this)
.load(profileRef)
.into(mImageFriend);
//Setting database for messages
getChatId();
//Send message
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendMessage();
}
});
}
private void sendMessage() {
String sendMessageText = mSendText.getText().toString();
if(!sendMessageText.isEmpty()){
DatabaseReference newMessageDb = mDatabaseChat.push();
Map newMessage = new HashMap();
newMessage.put("createdByUser", userId);
newMessage.put("text", sendMessageText);
newMessageDb.setValue(newMessage);
}
mSendText.setText(null);
}
private void getChatId(){
mDatabaseUser.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
chatId = dataSnapshot.getValue().toString();
mDatabaseChat = mDatabaseChat.child("Message").child(chatId);
getChatMessages();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void getChatMessages() {
mDatabaseChat.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if(dataSnapshot.exists()){
String message = null;
String createdByUser = null;
if (dataSnapshot.child("text").getValue()!=null){
message = dataSnapshot.child("text").getValue().toString();
}
if (dataSnapshot.child("createdByUser").getValue()!=null){
createdByUser = dataSnapshot.child("createdByUser").getValue().toString();
}
if(message!=null && createdByUser!=null){
Boolean currentUserBoolean = false;
if(createdByUser.equals(userId)){
currentUserBoolean=true;
}
ChatObject newMessage = new ChatObject(message, currentUserBoolean, createdByUser);
resultsChat.add(0,newMessage);
mChatAdapter.notifyDataSetChanged();
mLayoutManager.scrollToPositionWithOffset(0,0);
}
}
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public void FillInRecyclerView(){
mLayoutManager = new LinearLayoutManager(this);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(true);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
mLayoutManager.scrollToPositionWithOffset(0,0);
mChatAdapter = new RecyclerViewChatAdapter(ChatActivity.this, resultsChat);
recyclerView.setAdapter(mChatAdapter);
recyclerView.setLayoutManager(mLayoutManager);
}
ActivityChat 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="match_parent"
tools:context=".ChatActivity">
<LinearLayout
android:id="#+id/ChatActivity_LinearLayoutHeader"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#drawable/background_chatheader"
android:paddingStart="7dp"
android:paddingLeft="7dp"
android:windowSoftInputMode="adjustResize"
android:layout_marginBottom="3dp">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="45dp"
android:layout_height="45dp"
android:id="#+id/ChatActivity_ImageFriend"
android:src="#mipmap/ic_launcher"
android:layout_gravity="center"
/>
<TextView
android:id="#+id/ChatActivity_Name"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Test"
android:gravity="center_vertical|start"
android:textSize="25sp"
android:textColor="#color/white"
android:fontFamily="sans-serif"
/>
</LinearLayout>
<android.support.v4.widget.NestedScrollView
android:layout_below="#+id/ChatActivity_LinearLayoutHeader"
android:layout_above="#id/ChatActivity_LinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:scrollbarStyle="outsideOverlay"
>
<android.support.v7.widget.RecyclerView
app:stackFromEnd="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/ChatActivity_LinearLayout"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
android:id="#+id/ChatActivity_recyclerview"
>
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.NestedScrollView>
<LinearLayout
android:id="#+id/ChatActivity_LinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<EditText
android:layout_weight="0.7"
android:id="#+id/ChatActivity_SendText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Type your message..."
/>
<Button
android:layout_weight="0.3"
android:id="#+id/ChatActivity_Send"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="send"/>
</LinearLayout>
</RelativeLayout>
Itemlayout xml file for the recyclerview:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/Recyclerview_Parent_Container"
>
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/Recyclerview_ChatImage"
android:layout_width="42dp"
android:layout_height="42dp"
android:src="#mipmap/ic_launcher"
android:visibility="invisible"
/>
<LinearLayout
android:layout_marginStart="9dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6sp"
android:id="#+id/Recyclerview_Container"
android:orientation="horizontal"
android:background="#drawable/border_chat_bubbles"
android:layout_marginLeft="7dp"
android:layout_marginEnd="7dp">
<TextView
android:id="#+id/Recyclerview_Message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Text"
android:textSize="18sp"
/>
</LinearLayout>
</LinearLayout>
RecyclerView adapter code:
public class RecyclerViewChatAdapter extends RecyclerView.Adapter<RecyclerViewChatAdapter.ViewHolder> {
private List<ChatObject> chatList;
private Context context;
//Firebase
private FirebaseAuth mAuth;
private String CurrentUserId;
private FirebaseStorage mStorage;
private StorageReference mStorageReference;
public RecyclerViewChatAdapter(Context context, List<ChatObject> chatList) {
this.chatList = chatList;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerview_chatlist_layout, viewGroup, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
//Firebase variables
mStorage = FirebaseStorage.getInstance();
mStorageReference = mStorage.getReference();
mAuth = FirebaseAuth.getInstance();
CurrentUserId = mAuth.getCurrentUser().getUid();
//Setting profile picture into recyclerview
StorageReference profileRef = mStorageReference.child("profilepictures/" + chatList.get(position).getUserid());
GlideApp.with(context)
.load(profileRef)
.into(holder.mProfilepicture);
//Setting message layout for user and friend
holder.mMessage.setText(chatList.get(position).getMessage());
if (chatList.get(position).getCurrentUser()) {
holder.mParentContainer.setGravity(Gravity.END);
holder.mMessage.setTextColor(Color.parseColor("#404040"));
holder.mContainer.setBackgroundResource(R.drawable.border_chat_bubbles);
holder.mProfilepicture.setVisibility(View.INVISIBLE);
} else {
holder.mParentContainer.setGravity(Gravity.START);
holder.mMessage.setTextColor(Color.parseColor("#FFFFFF"));
holder.mContainer.setBackgroundResource(R.drawable.border_chat_bubbles_friend);
holder.mProfilepicture.setVisibility(View.VISIBLE);
//Set picture of friend when multiple messages
int i = 1;
if(position+i<chatList.size()) {
while (!chatList.get(position + i).getCurrentUser()) {
if ((chatList.get(position + i).getCurrentUser()) == chatList.get(position).getCurrentUser()) {
holder.mProfilepicture.setVisibility(View.INVISIBLE);
i++;
} else {
break;
}
if (position + i == chatList.size()) {
break;
}
}
}
}
}
#Override
public int getItemCount() {
return this.chatList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView mMessage;
LinearLayout mContainer, mParentContainer;
CircleImageView mProfilepicture;
public ViewHolder(View itemView) {
super(itemView);
mParentContainer = itemView.findViewById(R.id.Recyclerview_Parent_Container);
mMessage = itemView.findViewById(R.id.Recyclerview_Message);
mContainer = itemView.findViewById(R.id.Recyclerview_Container);
mProfilepicture = itemView.findViewById(R.id.Recyclerview_ChatImage);
}
}
What it looks like on the emulator:
Screenshot of emulator of what it looks like
What I want it to look like:
Emulator of what I want
Now if I set SetStackFromEnd to true or false, I keep getting the same result as in the above picture. However, SetReverseLayout does work! What also does not work is the scrollToPositionWithOffset(0,0); or any other variation, I think the issue must be linked to each other
What have I tried to do already and did not work:
changing the position at what time "FillInRecyclerView()" method is being called, however this did not change anything.
Various combinations of SetReverseLayout/SetStackFromEnd to true
Setting stackfromend to true in the XML code
Changing the RelativeLayout to a LinearLayout in 'ChatActivity.xml'
Setting the relative layout height to match parent
Any help is welcome!
Thank you
You need to use both setStackFromEnd and setReverseLayout. Set both value true and you will get your expected output.
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(mContext);
recyclerView.setLayoutManager(mLinearLayoutManager);
mLinearLayoutManager.setStackFromEnd(true);
mLinearLayoutManager.setReverseLayout(true);
I have created a recyclerView in one of the fragments of my activity. And I am binding it to a dataset. I have set both the LinearLayoutManager and RecyclerView Adapter. My dataset is also getting created correctly and so is my Viewholder. There are no compilation warnings, no exceptions in my Logcat. I have checked the XML layouts for both fragment and the individual item and both are having all items set to Visible.
Yet my recyclerView is not showing in the fragment.
What are the common oversights resulting in recyclerView not being visible. Appreciate any guidance I can get on the matter.
Relevant Method initialising my recylerView is below:
private void loadMyPlacardView(View view){
List<Post> postList = new ArrayList<>();
RecyclerView placardsRecyclerView = view.findViewById(R.id.fp_placards_recyclerView);
LinearLayoutManager postsLayoutManager = new LinearLayoutManager(view.getContext());
placardsRecyclerView.setHasFixedSize(true);
placardsRecyclerView.setLayoutManager(postsLayoutManager);
DataSnapshot dataSnapshot = FirebaseStorageUtils.postDataSnapshot;
for (DataSnapshot singleSnapShot: dataSnapshot.getChildren()) {
Post thisPost = singleSnapShot.getValue(Post.class);
postList.add(thisPost);
}
PlacardsRecyclerViewAdapter placardsRecyclerViewAdapter = new PlacardsRecyclerViewAdapter(postList);
placardsRecyclerView.setAdapter(placardsRecyclerViewAdapter);
}
Code for the RecyclerviewAdapter is here
public class PlacardsRecyclerViewAdapter
extends RecyclerView.Adapter<PlacardHolder> {
private static final String TAG = "PlacardsViewAdapter";
private List<Post> listofPosts;
public PlacardsRecyclerViewAdapter(List <Post> list) {
listofPosts = list;
}
#Override
public PlacardHolder onCreateViewHolder(ViewGroup parent, int viewType){
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.placard_item, parent, false);
return new PlacardHolder(view);
}
#Override
public void onBindViewHolder(PlacardHolder placard, int position) {
Post currentPost = listofPosts.get(position);
String username = currentPost.getUserName();
placard.userName.setText(username);
}
#Override
public int getItemCount() {
return listofPosts.size();
}
}
Code for Recyclerviewholder as class PlacardHolder.java is below
public class PlacardHolder extends RecyclerView.ViewHolder {
private static final String TAG = "PlacardsHolder";
public TextView userName;
public PlacardHolder(View view){
super(view);
this.userName = view.findViewById(R.id.pi_profile_name);
}
}
XML for the Placard Item is placard_item.xml below
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="#+id/pi_profile_name"
android:text="#string/default_username"
android:textAlignment="center"
android:textSize="25sp"
android:textStyle="bold"
android:layout_weight="7"/></android.support.constraint.ConstraintLayout>
and code for fragment_placard.xml is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="testing recyclerview"/>
<android.support.v7.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fp_placards_recyclerView"
android:scrollbars="vertical"
android:visibility="visible"
android:layout_margin="10dp">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
The textview from the fragment_placard.xml is loading fine but not the recyclerview.
Okay! It is about Firebase. You are not notifying your adapter after adding data to dataset. Do
if(placardsRecyclerViewAdapter != null)
placardsRecyclerViewAdapter.notifyDataSetChanged();
after adding data to postList.
Updated
Full structure:
private ValueEventListener postListener = null;
private void loadMyPlacardView(View view) {
List<Post> postList = new ArrayList<>();
RecyclerView placardsRecyclerView = view.findViewById(R.id.fp_placards_recyclerView);
LinearLayoutManager postsLayoutManager = new LinearLayoutManager(view.getContext());
placardsRecyclerView.setHasFixedSize(true);
placardsRecyclerView.setLayoutManager(postsLayoutManager);
PlacardsRecyclerViewAdapter placardsRecyclerViewAdapter = new PlacardsRecyclerViewAdapter(postList);
placardsRecyclerView.setAdapter(placardsRecyclerViewAdapter);
//Fetching data from Firebase
postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChildren()) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Post thisPost = ds.getValue(Post.class);
postList.add(thisPost);
}
if(placardsRecyclerViewAdapter != null)
placardsRecyclerViewAdapter.notifyDataSetChanged(); //Now postList has data so notify adapter.
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.e("DB error", "loadPost:onCancelled", databaseError.toException());
}
};
databaseReference.addListenerForSingleValueEvent(valueEventListener);
}
I found the answer to my question. there were 2 bugs. First problem was in the placard_item.xml where I had declared the Constraintview as follows:
android:layout_height ="match parent"
because of this the layout was taking up the entire space in the screen. The second bug was that I had defined the TextView as below
android:layout_width = "0dp"
This was causing the TextView to disappear inside the recyclerview at run-time, although it was showing perfectly well in the "Design" view of my xml in AndroidStudio IDE. I am posting answer here in case someone else faces same issues. "ConstraintView" in general is proving hard to handle while working with Recyclerview. So going back to the simpler LinearLayout.