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 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: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.
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.
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 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"
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.
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:
Note: Please Add drawable items before running the Application
Below is the file structure after performing these operations: