Grid View
인스타 검색 탭에서 보면 contents들이 grid view를 이용하여 표시된다.
이를 표현하기 위해서 안드로이드에서 제공하는 grid view를 이용하여 contents를 띄워보자.
<?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="match_parent"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/gridFragment_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
fragment_grid를 위와 같이 변경하자.
LinearLayout에 RecyclerView를 넣어 새로 등록되는 contents들도 띄울 수 있다.
package com.example.firstapp.navigation
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.example.firstapp.R
import com.example.firstapp.navigation.model.ContentDTO
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.FirebaseFirestoreException
import com.google.firebase.firestore.QuerySnapshot
class GridFragment: Fragment(){
var firestore: FirebaseFirestore? = null
var fragmentView: View? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
fragmentView = LayoutInflater.from(activity).inflate(R.layout.fragment_grid,container,false)
firestore = FirebaseFirestore.getInstance()
var gridFragmentRecyclerView = fragmentView?.findViewById<RecyclerView>(R.id.gridFragment_recyclerView)
gridFragmentRecyclerView?.adapter = UserFragmentRecyclerViewAdapter()
gridFragmentRecyclerView?.layoutManager = GridLayoutManager(activity, 3)
return fragmentView
}
inner class UserFragmentRecyclerViewAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>(){
var contentDTOs: ArrayList<ContentDTO> = arrayListOf()
init{
firestore?.collection("images")?.addSnapshotListener{
value: QuerySnapshot?, error: FirebaseFirestoreException? ->
if(value == null){
return@addSnapshotListener
}
//get data
for(snapshot in value.documents){
contentDTOs.add(snapshot.toObject(ContentDTO::class.java)!!)
}
notifyDataSetChanged()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
var width = resources.displayMetrics.widthPixels / 3
var imageview = ImageView(parent.context)
imageview.layoutParams = LinearLayoutCompat.LayoutParams(width,width)
return CustomViewHolder(imageview)
}
inner class CustomViewHolder(var imageview: ImageView) : RecyclerView.ViewHolder(imageview)
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
var imageview = (holder as CustomViewHolder).imageview
Glide.with(holder.itemView.context).load(contentDTOs[position].imageUrl).apply(RequestOptions().centerCrop()).into(imageview)
}
override fun getItemCount(): Int {
return contentDTOs.size
}
}
}
inner class를 하나 정의하는데 이는 전에 생성했던 피드에 띄우는 것과 동일하다.
이미지들을 하나씩 가져와 RecyclerView에 렌더하는 것이다.
댓글 기능
게시물에 댓글을 작성하는 기능과 그를 표시하는 기능을 구현해보자.
<?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=".navigation.CommentActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="35dp">
<ImageView
android:src="@drawable/logo_title"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.appcompat.widget.Toolbar>
<LinearLayout
android:id="@+id/toolbar_division"
android:layout_width="match_parent"
android:layout_height="1dp"
android:orientation="horizontal"
android:layout_below="@id/my_toolbar"
android:background="@color/colorDivision"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/comment_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="30dp"
android:layout_below="@+id/toolbar_division"/>
<Button
android:id="@+id/comment_btn_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_alignParentRight="true"
android:layout_below="@+id/comment_recyclerview"
android:text="@string/send"/>
<EditText
android:id="@+id/comment_edit_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_below="@+id/comment_recyclerview"
android:layout_toLeftOf="@+id/comment_btn_send"
/>
</RelativeLayout>
툴바와 recyclerview와 edit text, button을 배치한다.
package com.example.firstapp.navigation
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.example.firstapp.R
import com.example.firstapp.navigation.model.ContentDTO
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.FirebaseFirestoreException
import com.google.firebase.firestore.QuerySnapshot
class CommentActivity : AppCompatActivity() {
var contentUid: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_comment)
contentUid = intent.getStringExtra("contentUid")
var commentBtnSend = findViewById<Button>(R.id.comment_btn_send)
var commentEditMessage = findViewById<EditText>(R.id.comment_edit_message)
var commentRecyclerView = findViewById<RecyclerView>(R.id.comment_recyclerview)
commentRecyclerView.adapter = CommentRecyclerviewAdapter()
commentRecyclerView.layoutManager = LinearLayoutManager(this)
commentBtnSend.setOnClickListener {
var comment = ContentDTO.Comment()
comment.userId = FirebaseAuth.getInstance().currentUser?.email
comment.uid = FirebaseAuth.getInstance().currentUser?.uid
comment.comment = commentEditMessage.text.toString()
comment.timestamp = System.currentTimeMillis()
FirebaseFirestore.getInstance().collection("images").document(contentUid!!).collection("comments").document().set(comment)
commentEditMessage.setText("")
}
}
inner class CommentRecyclerviewAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>(){
var comments: ArrayList<ContentDTO.Comment> = arrayListOf()
init{
FirebaseFirestore.getInstance()
.collection("images")
.document(contentUid!!)
.collection("comments")
.orderBy("timestamp")
.addSnapshotListener{ value: QuerySnapshot?, error: FirebaseFirestoreException? ->
comments.clear()
if(value == null ){
return@addSnapshotListener
}
for(snapshot in value.documents!!){
comments.add(snapshot.toObject(ContentDTO.Comment::class.java)!!)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
var view = LayoutInflater.from(parent.context).inflate(R.layout.item_comment, parent, false)
return CustomViewHolder(view)
}
private inner class CustomViewHolder(view: View): RecyclerView.ViewHolder(view)
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
var view = holder.itemView
var commentViewItemComment = view.findViewById<TextView>(R.id.commentViewItem_textView_comment)
var commentViewProfile = view.findViewById<TextView>(R.id.commentViewItem_textView_profile)
var commentViewImageProfile = view.findViewById<ImageView>(R.id.commentViewItem_imageView_profile)
commentViewItemComment.text = comments[position].comment
commentViewProfile.text = comments[position].userId
FirebaseFirestore.getInstance()
.collection("profileImages")
.document(comments[position].uid!!)
.get()
.addOnCompleteListener { task ->
if(task.isSuccessful){
var url = task.result!!["image"]
Glide.with(holder.itemView.context).load(url).apply(RequestOptions().circleCrop()).into(commentViewImageProfile)
}
}
}
override fun getItemCount(): Int {
return comments.size
}
}
}
edit text에서 text를 읽어와 firebase에 전달하는 것이다.
게시물에 comment필드가 생기며 저장된다.
그리고 등록된 댓글을 보여지게 하기 위해 CommentRecyclerViewAdapter를 만들어 적용하면 된다.
어댑터에서는 댓글을 작성한 유저의 프로필 사진과 댓글 내용을 읽어와 item에 적용한다.
그리고 시간순서로 정렬한다.
다음은 댓글 item이다.
<?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="50dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/commentViewItem_imageView_profile"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_margin="7.5dp"
/>
<TextView
android:id="@+id/commentViewItem_textView_profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="UserID"
android:textStyle="bold"
android:layout_margin="7.5dp"/>
<TextView
android:id="@+id/commentViewItem_textView_comment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="message"
android:layout_margin="7.5dp"/>
</LinearLayout>