Parte 11 «Crear una aplicación de redes sociales en Android Studio»
- Vamos a comentar en el blog.
- Aquí vamos a escribir un comentario, y luego mostraremos los comentarios y actualizaremos el recuento de comentarios.
- La función de comentarios es la mejor característica en cualquier aplicación de blogs. Ayuda a interactuar con el usuario que ha escrito el blog y mucho más.
Implementación paso a paso
Paso 1: Cree un nuevo archivo de recursos de diseño
Vaya a la aplicación > res > diseño > haga clic con el botón derecho en > Nuevo > Archivo de recursos de diseño y nombre el archivo como comentarios_fila. A continuación se muestra el código para el archivo row_comments.xml .
XML
<?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>
Paso 2: Cree una nueva clase Java y nombre la clase como ModelComment
Trabajando con el archivo ModelComment.java . Creó esta actividad para inicializar la clave para que podamos recuperar el valor de la clave más tarde. ModeloComentario.java
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; }
Paso 3: Cree otra nueva clase Java y nombre la clase como AdapterComment
Trabajar con el archivo AdapterComment.java . AdaptadorComentario.java
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); } } }
Paso 4: trabajar con la actividad PostDetailsActivity
Trabajando con el archivo activity_postdetails.xml .
XML
<?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>
Trabajar con el archivo PostDetailsActivity.java
Publicar comentario usando esto:
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);
Mostrando comentario como este:
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) { } });
PostDetailsActivity.java
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(); } }
Producción:
Para ver todos los archivos dibujables utilizados en este artículo, consulte este enlace: https://drive.google.com/drive/folders/1M_knOH_ugCuwSP5nkYzeD4dRp-Honzbe?usp=sharing
A continuación se muestra la estructura de archivos después de realizar estas operaciones: