diff --git a/app/build.gradle b/app/build.gradle index c1b2a86..1145724 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,6 +29,9 @@ android { kotlinOptions { jvmTarget = '1.8' } + buildFeatures{ + viewBinding true + } } dependencies { diff --git a/app/src/main/java/otus/gpb/recyclerview/Chat.kt b/app/src/main/java/otus/gpb/recyclerview/Chat.kt new file mode 100644 index 0000000..4b18486 --- /dev/null +++ b/app/src/main/java/otus/gpb/recyclerview/Chat.kt @@ -0,0 +1,110 @@ +package otus.gpb.recyclerview + +class Chat( + val id: Int = 0, + val avatarImage: Int , + val previewImage: Int? , + val nickName: String = "NickName", + val group: String = "", + val message: String = "", + val lastTime: String = "Sun", + val messCount: Int = 0, + val check: Boolean = false, + val isViewed: Boolean = false, + val scam: Boolean = false, + val mute: Boolean = false, + val verified: Boolean = false +) { + companion object { + val pizza = Chat( + id = 1, + avatarImage = R.drawable.pizza_avatar, + previewImage = R.drawable.preview, + nickName = "Pizza", + group = "jija", + message = "Yes, they are necessary", + lastTime = "11:38 AM", + mute = true + ) + val elon = Chat( + id = 2, + avatarImage = R.drawable.ilon_avatar, + previewImage = null, + nickName = "Elon", + message = "I love /r/Reddit!", + lastTime = "12:44 AM", + mute = true + ) + val pasha = Chat( + id = 3, + avatarImage = R.drawable.pasha_avatar, + previewImage = null, + nickName = "Pasha", + message = "How are u?", + lastTime = "Fri", + mute = true, + verified = true + ) + val pasha2 = Chat( + id = 4, + avatarImage = R.drawable.pasha_avatar, + previewImage = null, + nickName = "Pasha2", + message = "what are u doing now", + lastTime = "Thu", + isViewed = true, + mute = true + ) + val telegramSupport = Chat( + id = 5, + avatarImage = R.drawable.tg_avatar, + previewImage = null, + nickName = "Telegram Support", + group = "Support", + message = "Yes it happened.", + lastTime = "Thu", + messCount = 1, + verified = true + ) + val karina = Chat( + id = 6, + avatarImage = R.drawable.karina_avatar, + previewImage = null, + nickName = "Karina", + message = "Okay", + lastTime = "Wed", + check = true + ) + val marilyn = Chat( + id = 7, + avatarImage = R.drawable.marlin_avatar, + previewImage = null, + nickName = "Marilyn", + message = "Will it ever happen", + lastTime = "May 02", + isViewed = true, + scam = true + ) + val chatList = mutableListOf( + pizza, + elon, + pasha, + pasha2, + telegramSupport, + karina, + marilyn + ) + } +} + + + + + + + + + + + + diff --git a/app/src/main/java/otus/gpb/recyclerview/ChatAdapter.kt b/app/src/main/java/otus/gpb/recyclerview/ChatAdapter.kt new file mode 100644 index 0000000..cdf9a88 --- /dev/null +++ b/app/src/main/java/otus/gpb/recyclerview/ChatAdapter.kt @@ -0,0 +1,88 @@ +package otus.gpb.recyclerview + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.Adapter +import otus.gpb.recyclerview.databinding.ItemRecyclerBinding + +class ChatAdapter(private var chatList: MutableList) : Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatViewHolder { + val binding = + ItemRecyclerBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return ChatViewHolder(binding) + } + + override fun getItemCount(): Int { + return chatList.size + } + + override fun onBindViewHolder(holder: ChatViewHolder, position: Int) { + holder.bind(chatList[position]) + } + + fun setChats(newChatList: MutableList) { + chatList = newChatList + notifyDataSetChanged() + } + + fun deleteItem(position: Int) { + chatList.removeAt(position) + notifyItemRemoved(position) + } +} + +class ChatViewHolder(private val binding: ItemRecyclerBinding) : + RecyclerView.ViewHolder(binding.root) { + fun bind(model: Chat) { + binding.imageViewAvatar.setImageResource(model.avatarImage) + model.previewImage?.let { binding.imageViewPreview.setImageResource(it) } + + binding.textViewNickname.text = model.nickName + binding.textViewMessage.text = model.message + binding.textViewMessTime.text = model.lastTime + binding.textViewMessCount.text = model.messCount.toString() + + if (model.group.isEmpty()) + binding.textViewGroup.visibility = View.GONE + else + binding.textViewGroup.text = model.group + + if (model.check) { + binding.imageViewCheck.setImageResource(R.drawable.one_check) + binding.imageViewCheck.visibility = View.VISIBLE + } else if (model.isViewed) { + binding.imageViewCheck.setImageResource(R.drawable.read_check) + binding.imageViewCheck.visibility = View.VISIBLE + } else { + binding.imageViewCheck.visibility = View.GONE + } + + if (model.messCount == 0) { + binding.imageViewMessCountCircle.visibility = View.GONE + binding.textViewMessCount.visibility = View.GONE + } else { + binding.imageViewMessCountCircle.visibility = View.VISIBLE + binding.textViewMessCount.visibility = View.VISIBLE + binding.textViewMessCount.text = model.messCount.toString() + } + + if (model.previewImage == null) { + binding.imageViewPreview.visibility = View.GONE + } else { + binding.imageViewPreview.visibility = View.VISIBLE + binding.imageViewPreview.setImageResource(model.previewImage!!) + } + + if (!model.scam) + binding.imageViewScam.visibility = View.GONE + + if (!model.mute) + binding.imageViewMute.visibility = View.GONE + + if (!model.verified) + binding.imageViewVerified.visibility = View.GONE + } +} \ No newline at end of file diff --git a/app/src/main/java/otus/gpb/recyclerview/CustomItemDecorator.kt b/app/src/main/java/otus/gpb/recyclerview/CustomItemDecorator.kt new file mode 100644 index 0000000..9feba70 --- /dev/null +++ b/app/src/main/java/otus/gpb/recyclerview/CustomItemDecorator.kt @@ -0,0 +1,18 @@ +package otus.gpb.recyclerview + +import android.graphics.Rect +import android.view.View +import androidx.recyclerview.widget.RecyclerView + +class CustomItemDecorator : RecyclerView.ItemDecoration() { + + override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { + outRect.apply { + left = 0 + right = 0 + top = 5 + bottom = 5 + } + } +} + diff --git a/app/src/main/java/otus/gpb/recyclerview/MainActivity.kt b/app/src/main/java/otus/gpb/recyclerview/MainActivity.kt index e2cdca7..055367d 100644 --- a/app/src/main/java/otus/gpb/recyclerview/MainActivity.kt +++ b/app/src/main/java/otus/gpb/recyclerview/MainActivity.kt @@ -1,12 +1,106 @@ package otus.gpb.recyclerview +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.drawable.ColorDrawable import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.widget.Toast +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import otus.gpb.recyclerview.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { + private lateinit var binding: ActivityMainBinding + private lateinit var adapter: ChatAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) + initializeViewBinding() + setupRecyclerView() + setupSwipeToDelete() } -} \ No newline at end of file + + private fun initializeViewBinding() { + binding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.root) + } + + private fun setupRecyclerView() { + adapter = ChatAdapter(chatList = Chat.chatList) + binding.recyclerView.adapter = adapter + binding.recyclerView.layoutManager = LinearLayoutManager(this) + adapter.setChats(Chat.chatList) + binding.recyclerView.addItemDecoration(CustomItemDecorator()) + } + + private fun setupSwipeToDelete() { + val itemTouchHelper = + ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) { + override fun onMove( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + target: RecyclerView.ViewHolder + ): Boolean { + return false + } + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { + adapter.deleteItem(viewHolder.adapterPosition) + } + + override fun onChildDraw( + c: Canvas, + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + dX: Float, + dY: Float, + actionState: Int, + isCurrentlyActive: Boolean + ) { + viewHolder.itemView.apply { + ContextCompat.getDrawable(context, R.drawable.archive)?.apply { + val background = ColorDrawable() + background.color = ContextCompat.getColor(context, R.color.blue) + + val iconMargin = ((bottom - top) - intrinsicHeight) / 2 + val iconTop = top + iconMargin / 2 + val iconBottom = iconTop + intrinsicHeight + val iconRight = right - iconMargin + val iconLeft = iconRight - intrinsicWidth + + setBounds(iconLeft, iconTop, iconRight, iconBottom) + background.setBounds(right + dX.toInt(), top, right, bottom) + + background.draw(c) + draw(c) + } + val textPaint = Paint().apply { + color = Color.WHITE + textSize = 25f + } + val text = "Archive" + val textWidth = textPaint.measureText(text) + val textX = right - textWidth - 30f + val textY = bottom - 20f + c.drawText(text, textX, textY, textPaint) + } + + super.onChildDraw( + c, + recyclerView, + viewHolder, + dX, + dY, + actionState, + isCurrentlyActive + ) + } + }) + + itemTouchHelper.attachToRecyclerView(binding.recyclerView) + } +} diff --git a/app/src/main/res/drawable/archive.xml b/app/src/main/res/drawable/archive.xml new file mode 100644 index 0000000..f92bd38 --- /dev/null +++ b/app/src/main/res/drawable/archive.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border.xml b/app/src/main/res/drawable/border.xml new file mode 100644 index 0000000..69eab20 --- /dev/null +++ b/app/src/main/res/drawable/border.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/circle.xml b/app/src/main/res/drawable/circle.xml new file mode 100644 index 0000000..7a78ede --- /dev/null +++ b/app/src/main/res/drawable/circle.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ilon_avatar.png b/app/src/main/res/drawable/ilon_avatar.png new file mode 100644 index 0000000..af3fd16 Binary files /dev/null and b/app/src/main/res/drawable/ilon_avatar.png differ diff --git a/app/src/main/res/drawable/karina_avatar.png b/app/src/main/res/drawable/karina_avatar.png new file mode 100644 index 0000000..7b5d22e Binary files /dev/null and b/app/src/main/res/drawable/karina_avatar.png differ diff --git a/app/src/main/res/drawable/line.xml b/app/src/main/res/drawable/line.xml new file mode 100644 index 0000000..45cb3f9 --- /dev/null +++ b/app/src/main/res/drawable/line.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/marlin_avatar.png b/app/src/main/res/drawable/marlin_avatar.png new file mode 100644 index 0000000..b6a0dc9 Binary files /dev/null and b/app/src/main/res/drawable/marlin_avatar.png differ diff --git a/app/src/main/res/drawable/one_check.xml b/app/src/main/res/drawable/one_check.xml new file mode 100644 index 0000000..5b04999 --- /dev/null +++ b/app/src/main/res/drawable/one_check.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/pasha_avatar.png b/app/src/main/res/drawable/pasha_avatar.png new file mode 100644 index 0000000..9f29a5b Binary files /dev/null and b/app/src/main/res/drawable/pasha_avatar.png differ diff --git a/app/src/main/res/drawable/pizza_avatar.png b/app/src/main/res/drawable/pizza_avatar.png new file mode 100644 index 0000000..881f416 Binary files /dev/null and b/app/src/main/res/drawable/pizza_avatar.png differ diff --git a/app/src/main/res/drawable/preview.png b/app/src/main/res/drawable/preview.png new file mode 100644 index 0000000..6fd3097 Binary files /dev/null and b/app/src/main/res/drawable/preview.png differ diff --git a/app/src/main/res/drawable/read_check.xml b/app/src/main/res/drawable/read_check.xml new file mode 100644 index 0000000..248c046 --- /dev/null +++ b/app/src/main/res/drawable/read_check.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/sound_off.xml b/app/src/main/res/drawable/sound_off.xml new file mode 100644 index 0000000..bee2fa8 --- /dev/null +++ b/app/src/main/res/drawable/sound_off.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/drawable/tg_avatar.png b/app/src/main/res/drawable/tg_avatar.png new file mode 100644 index 0000000..7f8cf52 Binary files /dev/null and b/app/src/main/res/drawable/tg_avatar.png differ diff --git a/app/src/main/res/drawable/verificated.xml b/app/src/main/res/drawable/verificated.xml new file mode 100644 index 0000000..ef8414a --- /dev/null +++ b/app/src/main/res/drawable/verificated.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/item_recycler.xml b/app/src/main/res/layout/item_recycler.xml new file mode 100644 index 0000000..ae382d3 --- /dev/null +++ b/app/src/main/res/layout/item_recycler.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f8c6127..ef531fe 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -7,4 +7,7 @@ #FF018786 #FF000000 #FFFFFFFF + #95999A + #F44336 + #3D95D4 \ No newline at end of file