This is the Part 11 of “Build a Social Media App on Android Studio” tutorial, and we are going to cover the following functionalities in this article:
- We are going to comment on the blog.
- Here we are going to write a comment, and then we will be showing the comments and will be updating the comment count.
- The comment feature is the best feature in any blogging app. It helps in interacting with the user who has written the blog and much more.
Step By Step Implementation
Step 1: Create a new layout resource file
Go to the app > res > layout > Right-click > New > Layout Resource File and name the file as row_comments. Below is the code for the row_comments.xml file.
XML
<? xml version = "1.0" encoding = "utf-8" ?> < androidx.cardview.widget.CardView android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_margin = "1dp" android:orientation = "vertical" app:cardBackgroundColor = "@color/colorWhite" app:contentPadding = "2dp" > < RelativeLayout android:layout_width = "match_parent" android:layout_height = "wrap_content" > < de.hdodenhof.circleimageview.CircleImageView android:id = "@+id/loadcomment" android:layout_width = "40dp" android:layout_height = "40dp" android:layout_marginEnd = "5dp" android:layout_marginRight = "5dp" android:src = "@drawable/profile_image" /> < TextView android:id = "@+id/commentname" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_toRightOf = "@id/loadcomment" android:text = "Anni" android:textColor = "@color/colorBlack" android:textSize = "16sp" android:textStyle = "bold" /> < TextView android:id = "@+id/commenttext" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_below = "@id/commentname" android:layout_toEndOf = "@id/loadcomment" android:layout_toRightOf = "@id/loadcomment" android:text = "Actual Comment" android:textColor = "@color/colorBlack" /> < TextView android:id = "@+id/commenttime" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_below = "@id/commenttext" android:layout_toEndOf = "@id/loadcomment" android:layout_toRightOf = "@id/loadcomment" android:text = "12/06/19" /> </ RelativeLayout > </ androidx.cardview.widget.CardView > |
Step 2: Create a new java class and name the class as ModelComment
Working with the ModelComment.java file. Created this activity to initialize the key so that we can retrieve the value of the key later. Below is the code for the ModelComment.java file.
Java
package com.example.socialmediaapp; public class ModelComment { String cId; String comment; String ptime; String udp; public String getcId() { return cId; } public void setcId(String cId) { this .cId = cId; } public String getComment() { return comment; } public void setComment(String comment) { this .comment = comment; } public String getPtime() { return ptime; } public void setPtime(String ptime) { this .ptime = ptime; } public String getUdp() { return udp; } public void setUdp(String udp) { this .udp = udp; } public String getUemail() { return uemail; } public void setUemail(String uemail) { this .uemail = uemail; } public String getUid() { return uid; } public void setUid(String uid) { this .uid = uid; } public String getUname() { return uname; } public void setUname(String uname) { this .uname = uname; } String uemail; public ModelComment() { } String uid; public ModelComment(String cId, String comment, String ptime, String udp, String uemail, String uid, String uname) { this .cId = cId; this .comment = comment; this .ptime = ptime; this .udp = udp; this .uemail = uemail; this .uid = uid; this .uname = uname; } String uname; } |
Step 3: Create another new java class and name the class as AdapterComment
Working with the AdapterComment.java file. Below is the code for the AdapterComment.java file.
Java
package com.example.socialmediaapp; import android.content.Context; import android.text.format.DateFormat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import java.util.Calendar; import java.util.List; import java.util.Locale; public class AdapterComment extends RecyclerView.Adapter<com.example.socialmediaapp.AdapterComment.MyHolder> { Context context; List<ModelComment> list; public AdapterComment(Context context, List<ModelComment> list, String myuid, String postid) { this .context = context; this .list = list; this .myuid = myuid; this .postid = postid; } String myuid; String postid; @NonNull @Override public MyHolder onCreateViewHolder( @NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.row_comments, parent, false ); return new MyHolder(view); } @Override public void onBindViewHolder( @NonNull MyHolder holder, int position) { final String uid = list.get(position).getUid(); String name = list.get(position).getUname(); String email = list.get(position).getUemail(); String image = list.get(position).getUdp(); final String cid = list.get(position).getcId(); String comment = list.get(position).getComment(); String timestamp = list.get(position).getPtime(); Calendar calendar = Calendar.getInstance(Locale.ENGLISH); calendar.setTimeInMillis(Long.parseLong(timestamp)); String timedate = DateFormat.format( "dd/MM/yyyy hh:mm aa" , calendar).toString(); holder.name.setText(name); holder.time.setText(timedate); holder.comment.setText(comment); try { Glide.with(context).load(image).into(holder.imagea); } catch (Exception e) { } } @Override public int getItemCount() { return list.size(); } class MyHolder extends RecyclerView.ViewHolder { ImageView imagea; TextView name, comment, time; public MyHolder( @NonNull View itemView) { super (itemView); imagea = itemView.findViewById(R.id.loadcomment); name = itemView.findViewById(R.id.commentname); comment = itemView.findViewById(R.id.commenttext); time = itemView.findViewById(R.id.commenttime); } } } |
Step 4: Working with the PostDetailsActivity Activity
Working with the activity_postdetails.xml file.
XML
<? xml version = "1.0" encoding = "utf-8" ?> < RelativeLayout android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".PostDetailsActivity" > < androidx.core.widget.NestedScrollView android:layout_width = "match_parent" android:layout_height = "match_parent" android:layout_above = "@id/commentsa" > < LinearLayout android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:orientation = "vertical" > < androidx.cardview.widget.CardView android:layout_width = "match_parent" android:layout_height = "wrap_content" android:orientation = "vertical" app:cardBackgroundColor = "@color/colorWhite" app:cardCornerRadius = "3dp" app:cardElevation = "3dp" app:cardUseCompatPadding = "true" app:contentPadding = "5dp" > < LinearLayout android:layout_width = "match_parent" android:layout_height = "wrap_content" android:orientation = "vertical" > < LinearLayout android:id = "@+id/profilelayoutco" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:gravity = "center_vertical" android:orientation = "horizontal" > < de.hdodenhof.circleimageview.CircleImageView android:id = "@+id/pictureco" android:layout_width = "50dp" android:layout_height = "50dp" android:scaleType = "centerCrop" android:src = "@drawable/profile_image" /> < LinearLayout android:layout_width = "0dp" android:layout_height = "wrap_content" android:layout_weight = "1" android:orientation = "vertical" > < TextView android:id = "@+id/unameco" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "Name" android:textColor = "@color/colorBlack" android:textSize = "20sp" /> < TextView android:id = "@+id/utimeco" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "33 min" /> </ LinearLayout > < ImageButton android:id = "@+id/morebtn" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:background = "@null" android:src = "@drawable/ic_more" /> </ LinearLayout > < TextView android:id = "@+id/ptitleco" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:text = "Title" android:textSize = "16sp" android:textStyle = "bold" /> < TextView android:id = "@+id/descriptco" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:text = "Description" android:textColor = "@color/colorBlack" /> < ImageView android:id = "@+id/pimagetvco" android:layout_width = "match_parent" android:layout_height = "200dp" android:background = "@color/colorWhite" /> < LinearLayout android:layout_width = "match_parent" android:layout_height = "wrap_content" android:orientation = "horizontal" > < TextView android:id = "@+id/plikebco" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_weight = "1" android:text = "1.2K Likes" android:textColor = "@color/colorPrimary" /> < TextView android:id = "@+id/pcommenttv" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_weight = "1" android:text = "1.2K Comment" android:textAlignment = "textEnd" android:textColor = "@color/colorPrimary" /> </ LinearLayout > < View android:layout_width = "match_parent" android:layout_height = "1dp" android:background = "#F5F0F0" /> < LinearLayout android:layout_width = "match_parent" android:layout_height = "wrap_content" android:gravity = "center" android:orientation = "horizontal" > < Button android:id = "@+id/like" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_weight = "1" android:autoLink = "all" android:background = "@color/colorWhite" android:drawableStart = "@drawable/ic_like" android:drawableLeft = "@drawable/ic_like" android:padding = "5dp" android:text = "Like" /> < Button android:id = "@+id/share" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_weight = "1" android:background = "@color/colorWhite" android:drawableStart = "@drawable/ic_share" android:drawableLeft = "@drawable/ic_share" android:padding = "5dp" android:text = "SHARE" /> </ LinearLayout > </ LinearLayout > </ androidx.cardview.widget.CardView > < TextView android:layout_width = "match_parent" android:layout_height = "wrap_content" android:drawableStart = "@drawable/ic_commenting" android:drawableLeft = "@drawable/ic_commenting" android:drawablePadding = "5dp" android:padding = "2dp" android:text = "Comments" android:textColor = "@color/colorBlack" /> < androidx.recyclerview.widget.RecyclerView android:id = "@+id/recyclecomment" android:layout_width = "match_parent" android:layout_height = "wrap_content" /> </ LinearLayout > </ androidx.core.widget.NestedScrollView > < RelativeLayout android:id = "@+id/commentsa" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_alignParentBottom = "true" > < de.hdodenhof.circleimageview.CircleImageView android:id = "@+id/commentimge" android:layout_width = "50dp" android:layout_height = "50dp" android:src = "@drawable/profile_image" /> < EditText android:id = "@+id/typecommet" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_toStartOf = "@id/sendcomment" android:layout_toEndOf = "@id/commentimge" android:layout_weight = "1" android:background = "@color/colorWhite" android:hint = "Enter Comment..." android:inputType = "textCapSentences|textMultiLine" android:padding = "15dp" /> < ImageButton android:id = "@+id/sendcomment" android:layout_width = "40dp" android:layout_height = "40dp" android:layout_alignParentRight = "true" android:background = "@color/colorWhite" android:src = "@drawable/send_message" /> </ RelativeLayout > </ RelativeLayout > |
Working with the PostDetailsActivity.java file
Post Comment Using this:
DatabaseReference datarf= FirebaseDatabase.getInstance().getReference("Posts").child(postId).child("Comments"); HashMap<String ,Object> hashMap=new HashMap<>(); hashMap.put("cId",timestamp); hashMap.put("comment",commentss); hashMap.put("ptime",timestamp); hashMap.put("uid",myuid); hashMap.put("uemail",myemail); hashMap.put("udp",mydp); hashMap.put("uname",myname); datarf.child(timestamp).setValue(hashMap);
Showing Comment like this:
DatabaseReference reference= FirebaseDatabase.getInstance().getReference("Posts").child(postId).child("Comments"); reference.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { commentList.clear(); for (DataSnapshot dataSnapshot1:dataSnapshot.getChildren()){ } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } });
Below is the code for the PostDetailsActivity.java file.
Java
package com.example.socialmediaapp; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.text.format.DateFormat; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.Query; import com.google.firebase.database.ValueEventListener; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Locale; public class PostDetailsActivity extends AppCompatActivity { String hisuid, ptime, myuid, myname, myemail, mydp, uimage, postId, plike, hisdp, hisname; ImageView picture, image; TextView name, time, title, description, like, tcomment; ImageButton more; Button likebtn, share; LinearLayout profile; EditText comment; ImageButton sendb; RecyclerView recyclerView; List<ModelComment> commentList; AdapterComment adapterComment; ImageView imagep; boolean mlike = false ; ActionBar actionBar; ProgressDialog progressDialog; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_post_details); actionBar = getSupportActionBar(); actionBar.setTitle( "Post Details" ); actionBar.setDisplayHomeAsUpEnabled( true ); actionBar.setDisplayShowHomeEnabled( true ); postId = getIntent().getStringExtra( "pid" ); recyclerView = findViewById(R.id.recyclecomment); picture = findViewById(R.id.pictureco); image = findViewById(R.id.pimagetvco); name = findViewById(R.id.unameco); time = findViewById(R.id.utimeco); more = findViewById(R.id.morebtn); title = findViewById(R.id.ptitleco); myemail = FirebaseAuth.getInstance().getCurrentUser().getEmail(); myuid = FirebaseAuth.getInstance().getCurrentUser().getUid(); description = findViewById(R.id.descriptco); tcomment = findViewById(R.id.pcommenttv); like = findViewById(R.id.plikebco); likebtn = findViewById(R.id.like); comment = findViewById(R.id.typecommet); sendb = findViewById(R.id.sendcomment); imagep = findViewById(R.id.commentimge); share = findViewById(R.id.share); profile = findViewById(R.id.profilelayout); progressDialog = new ProgressDialog( this ); loadPostInfo(); loadUserInfo(); setLikes(); actionBar.setSubtitle( "SignedInAs:" + myemail); loadComments(); sendb.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { postComment(); } }); likebtn.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { likepost(); } }); like.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(PostDetailsActivity. this , PostLikedByActivity. class ); intent.putExtra( "pid" , postId); startActivity(intent); } }); } private void loadComments() { LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext()); recyclerView.setLayoutManager(layoutManager); commentList = new ArrayList<>(); DatabaseReference reference = FirebaseDatabase.getInstance().getReference( "Posts" ).child(postId).child( "Comments" ); reference.addValueEventListener( new ValueEventListener() { @Override public void onDataChange( @NonNull DataSnapshot dataSnapshot) { commentList.clear(); for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) { ModelComment modelComment = dataSnapshot1.getValue(ModelComment. class ); commentList.add(modelComment); adapterComment = new AdapterComment(getApplicationContext(), commentList, myuid, postId); recyclerView.setAdapter(adapterComment); } } @Override public void onCancelled( @NonNull DatabaseError databaseError) { } }); } private void setLikes() { final DatabaseReference liekeref = FirebaseDatabase.getInstance().getReference().child( "Likes" ); liekeref.addValueEventListener( new ValueEventListener() { @Override public void onDataChange( @NonNull DataSnapshot dataSnapshot) { if (dataSnapshot.child(postId).hasChild(myuid)) { likebtn.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_liked, 0 , 0 , 0 ); likebtn.setText( "Liked" ); } else { likebtn.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_like, 0 , 0 , 0 ); likebtn.setText( "Like" ); } } @Override public void onCancelled( @NonNull DatabaseError databaseError) { } }); } private void likepost() { mlike = true ; final DatabaseReference liekeref = FirebaseDatabase.getInstance().getReference().child( "Likes" ); final DatabaseReference postref = FirebaseDatabase.getInstance().getReference().child( "Posts" ); liekeref.addValueEventListener( new ValueEventListener() { @Override public void onDataChange( @NonNull DataSnapshot dataSnapshot) { if (mlike) { if (dataSnapshot.child(postId).hasChild(myuid)) { postref.child(postId).child( "plike" ).setValue( "" + (Integer.parseInt(plike) - 1 )); liekeref.child(postId).child(myuid).removeValue(); mlike = false ; } else { postref.child(postId).child( "plike" ).setValue( "" + (Integer.parseInt(plike) + 1 )); liekeref.child(postId).child(myuid).setValue( "Liked" ); mlike = false ; } } } @Override public void onCancelled( @NonNull DatabaseError databaseError) { } }); } private void postComment() { progressDialog.setMessage( "Adding Comment" ); final String commentss = comment.getText().toString().trim(); if (TextUtils.isEmpty(commentss)) { Toast.makeText(PostDetailsActivity. this , "Empty comment" , Toast.LENGTH_LONG).show(); return ; } progressDialog.show(); String timestamp = String.valueOf(System.currentTimeMillis()); DatabaseReference datarf = FirebaseDatabase.getInstance().getReference( "Posts" ).child(postId).child( "Comments" ); HashMap<String, Object> hashMap = new HashMap<>(); hashMap.put( "cId" , timestamp); hashMap.put( "comment" , commentss); hashMap.put( "ptime" , timestamp); hashMap.put( "uid" , myuid); hashMap.put( "uemail" , myemail); hashMap.put( "udp" , mydp); hashMap.put( "uname" , myname); datarf.child(timestamp).setValue(hashMap).addOnSuccessListener( new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { progressDialog.dismiss(); Toast.makeText(PostDetailsActivity. this , "Added" , Toast.LENGTH_LONG).show(); comment.setText( "" ); updatecommetcount(); } }).addOnFailureListener( new OnFailureListener() { @Override public void onFailure( @NonNull Exception e) { progressDialog.dismiss(); Toast.makeText(PostDetailsActivity. this , "Failed" , Toast.LENGTH_LONG).show(); } }); } boolean count = false ; private void updatecommetcount() { count = true ; final DatabaseReference reference = FirebaseDatabase.getInstance().getReference( "Posts" ).child(postId); reference.addListenerForSingleValueEvent( new ValueEventListener() { @Override public void onDataChange( @NonNull DataSnapshot dataSnapshot) { if (count) { String comments = "" + dataSnapshot.child( "pcomments" ).getValue(); int newcomment = Integer.parseInt(comments) + 1 ; reference.child( "pcomments" ).setValue( "" + newcomment); count = false ; } } @Override public void onCancelled( @NonNull DatabaseError databaseError) { } }); } private void loadUserInfo() { Query myref = FirebaseDatabase.getInstance().getReference( "Users" ); myref.orderByChild( "uid" ).equalTo(myuid).addListenerForSingleValueEvent( new ValueEventListener() { @Override public void onDataChange( @NonNull DataSnapshot dataSnapshot) { for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) { myname = dataSnapshot1.child( "name" ).getValue().toString(); mydp = dataSnapshot1.child( "image" ).getValue().toString(); try { Glide.with(PostDetailsActivity. this ).load(mydp).into(imagep); } catch (Exception e) { } } } @Override public void onCancelled( @NonNull DatabaseError databaseError) { } }); } private void loadPostInfo() { DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference( "Posts" ); Query query = databaseReference.orderByChild( "ptime" ).equalTo(postId); query.addValueEventListener( new ValueEventListener() { @Override public void onDataChange( @NonNull DataSnapshot dataSnapshot) { for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) { String ptitle = dataSnapshot1.child( "title" ).getValue().toString(); String descriptions = dataSnapshot1.child( "description" ).getValue().toString(); uimage = dataSnapshot1.child( "uimage" ).getValue().toString(); hisdp = dataSnapshot1.child( "udp" ).getValue().toString(); // hisuid = dataSnapshot1.child("uid").getValue().toString(); String uemail = dataSnapshot1.child( "uemail" ).getValue().toString(); hisname = dataSnapshot1.child( "uname" ).getValue().toString(); ptime = dataSnapshot1.child( "ptime" ).getValue().toString(); plike = dataSnapshot1.child( "plike" ).getValue().toString(); String commentcount = dataSnapshot1.child( "pcomments" ).getValue().toString(); Calendar calendar = Calendar.getInstance(Locale.ENGLISH); calendar.setTimeInMillis(Long.parseLong(ptime)); String timedate = DateFormat.format( "dd/MM/yyyy hh:mm aa" , calendar).toString(); name.setText(hisname); title.setText(ptitle); description.setText(descriptions); like.setText(plike + " Likes" ); time.setText(timedate); tcomment.setText(commentcount + " Comments" ); if (uimage.equals( "noImage" )) { image.setVisibility(View.GONE); } else { image.setVisibility(View.VISIBLE); try { Glide.with(PostDetailsActivity. this ).load(uimage).into(image); } catch (Exception e) { } } try { Glide.with(PostDetailsActivity. this ).load(hisdp).into(picture); } catch (Exception e) { } } } @Override public void onCancelled( @NonNull DatabaseError databaseError) { } }); } @Override public boolean onSupportNavigateUp() { onBackPressed(); return super .onSupportNavigateUp(); } } |
Output:
For all the drawable file used in this article please refer to this link: https://drive.google.com/drive/folders/1M_knOH_ugCuwSP5nkYzeD4dRp-Honzbe?usp=sharing
Below is the file structure after performing these operations: