-
Notifications
You must be signed in to change notification settings - Fork 63
Homework_10 implementation(RecyclerView) #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package otus.gpb.recyclerview | ||
|
|
||
| import android.util.Log | ||
| import android.view.LayoutInflater | ||
| import android.view.ViewGroup | ||
| import androidx.recyclerview.widget.RecyclerView | ||
| import com.bumptech.glide.Glide | ||
|
|
||
| class ChatTlgAdapter( ):RecyclerView.Adapter<ChatTlgViewHolder>(){ | ||
|
|
||
| private var ChatItemList = mutableListOf<ChatTlgItem>() | ||
| fun setList(list: List<ChatTlgItem>) { | ||
| ChatItemList = list.toList() as MutableList<ChatTlgItem> | ||
| notifyDataSetChanged() | ||
| } | ||
|
|
||
| override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatTlgViewHolder { | ||
|
|
||
| val view = LayoutInflater.from(parent.context) | ||
| val binding = view.inflate( R.layout.item_tlg_chat, parent, false ) | ||
| return ChatTlgViewHolder( binding ) | ||
| } | ||
|
|
||
| override fun getItemCount(): Int { | ||
| return ChatItemList.size | ||
| } | ||
|
|
||
| override fun onBindViewHolder( chatViewHolder: ChatTlgViewHolder, position: Int) { | ||
| chatViewHolder.bind( ChatItemList[position] ) | ||
| } | ||
| fun onItemSwipe( position:Int, direction:Int ){ | ||
| ChatItemList.removeAt(position) | ||
| notifyItemRemoved(position) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| package otus.gpb.recyclerview | ||
|
|
||
| import com.github.javafaker.Faker | ||
|
|
||
| data class ChatTlgItem( | ||
| // TODO There should be a real structure with Tg chat elements | ||
| val chatName: String, // Chat name | ||
| val messageAuthor: String, // Message author | ||
| val messageTitle: String, // Message fragment | ||
| val messageTime: String, // Message recv time | ||
| val messageCnt: Int, // Message count | ||
| val photo: String // Avatar | ||
| ) | ||
|
|
||
| class ChatTlgService( private val isNewList: Boolean ){ | ||
|
|
||
| private var itemsCnt:Int = 6 | ||
| private var chatList = mutableListOf<ChatTlgItem>() | ||
|
|
||
| init { | ||
| if( isNewList ) itemsCnt = 20 | ||
| val faker = Faker.instance() | ||
|
|
||
| chatList = (0..itemsCnt).map { | ||
| ChatTlgItem( | ||
| chatName = faker.name().fullName(), | ||
| messageAuthor = faker.name().fullName(), | ||
| messageTitle = faker.book().title(), | ||
| messageTime = faker.numerify("##:## AM"),//"11:25 AM", | ||
| messageCnt = faker.number().numberBetween(1,100), | ||
| photo = IMAGES[it % IMAGES.size], | ||
| ) | ||
| }.toMutableList() | ||
| } | ||
|
|
||
| fun getTlgChat() : List<ChatTlgItem>{ | ||
| return chatList | ||
| } | ||
|
|
||
| companion object { | ||
| private val IMAGES = mutableListOf( | ||
| "avatar_1", | ||
| "avatar_2", | ||
| "avatar_3", | ||
| "avatar_4", | ||
| "avatar_5", | ||
| "avatar_6" | ||
| ) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package otus.gpb.recyclerview | ||
|
|
||
| import androidx.recyclerview.widget.ItemTouchHelper | ||
| import androidx.recyclerview.widget.RecyclerView | ||
|
|
||
| class TlgItemTouchHelper( val adapter: ChatTlgAdapter ) : ItemTouchHelper.Callback() { | ||
|
|
||
| override fun getMovementFlags( | ||
| recyclerView: RecyclerView, | ||
| viewHolder: RecyclerView.ViewHolder | ||
| ): Int { | ||
| val swipeFlags = ItemTouchHelper.START | ||
| return makeMovementFlags(0 , swipeFlags) | ||
| } | ||
|
|
||
| override fun isItemViewSwipeEnabled(): Boolean { | ||
| return true | ||
| } | ||
|
|
||
| override fun onMove( | ||
| recyclerView: RecyclerView, | ||
| viewHolder: RecyclerView.ViewHolder, | ||
| target: RecyclerView.ViewHolder | ||
| ): Boolean { | ||
| return false | ||
| } | ||
|
|
||
| override fun onSwiped( | ||
| viewHolder: RecyclerView.ViewHolder, | ||
| direction: Int | ||
| ) { | ||
| val itemPosition:Int = viewHolder.adapterPosition | ||
| adapter.onItemSwipe( itemPosition, direction ) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Если добавить проверку позиции перед использованием, будет безопаснее при быстрых свайпах |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package otus.gpb.recyclerview | ||
|
|
||
| import android.view.View | ||
| import android.widget.ImageView | ||
| import android.widget.TextView | ||
| import androidx.recyclerview.widget.RecyclerView | ||
| import com.bumptech.glide.Glide | ||
| import com.bumptech.glide.load.engine.DiskCacheStrategy | ||
| import org.apache.commons.lang3.ClassUtils.getPackageName | ||
|
|
||
| class ChatTlgViewHolder( private val view : View ) : RecyclerView.ViewHolder( view ){ | ||
|
|
||
| private val image: ImageView by lazy { view.findViewById(R.id.imageView) } | ||
| private val chatName: TextView by lazy { view.findViewById(R.id.chatNameTextView) } | ||
| private val messAuthor: TextView by lazy { view.findViewById(R.id.authorTextView) } | ||
| private val messageText: TextView by lazy { view.findViewById(R.id.messageTextView) } | ||
| private val messageTime: TextView by lazy { view.findViewById(R.id.timeTextView) } | ||
| private val messageCnt: TextView by lazy { view.findViewById(R.id.cntMessTextView) } | ||
|
|
||
|
|
||
| fun bind( chatTlgItem: ChatTlgItem ) { | ||
|
|
||
| chatName.text = chatTlgItem.chatName | ||
| messAuthor.text = chatTlgItem.messageAuthor | ||
| messageText.text = chatTlgItem.messageTitle | ||
| messageTime.text = chatTlgItem.messageTime | ||
| messageCnt.text = chatTlgItem.messageCnt.toString() | ||
|
|
||
| image.setImageResource(R.drawable.ic_person) | ||
|
|
||
| val resourceName = chatTlgItem.photo | ||
| val res = view.context.getResources() | ||
| val packageName = view.context.packageName | ||
| val resourceId = res.getIdentifier(resourceName, "drawable", packageName ) | ||
| if (resourceId != 0) { | ||
|
|
||
| image.setImageResource(resourceId) | ||
| /* | ||
| Glide.with(view.context) | ||
| .load(resourceId) | ||
| .skipMemoryCache(false) | ||
| .diskCacheStrategy(DiskCacheStrategy.ALL ) | ||
| .circleCrop() | ||
| .into(image) | ||
| */ | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,49 @@ | ||
| package otus.gpb.recyclerview | ||
|
|
||
| import androidx.appcompat.app.AppCompatActivity | ||
| import android.os.Bundle | ||
|
|
||
| class MainActivity : AppCompatActivity() { | ||
|
|
||
| override fun onCreate(savedInstanceState: Bundle?) { | ||
| super.onCreate(savedInstanceState) | ||
| setContentView(R.layout.activity_main) | ||
| } | ||
| package otus.gpb.recyclerview | ||
|
|
||
| import androidx.appcompat.app.AppCompatActivity | ||
| import android.os.Bundle | ||
| import androidx.recyclerview.widget.DividerItemDecoration | ||
| import androidx.recyclerview.widget.ItemTouchHelper | ||
| import androidx.recyclerview.widget.LinearLayoutManager | ||
| import androidx.recyclerview.widget.RecyclerView | ||
|
|
||
| class MainActivity : AppCompatActivity() { | ||
|
|
||
| private var ChatTlgList:List<ChatTlgItem> = mutableListOf() | ||
| private lateinit var chatTlgAdapter:ChatTlgAdapter | ||
| private lateinit var dividerItemDecoration : DividerItemDecoration | ||
|
|
||
| override fun onCreate(savedInstanceState: Bundle?) { | ||
| super.onCreate(savedInstanceState) | ||
| setContentView(R.layout.activity_main) | ||
|
|
||
| ChatTlgList = ChatTlgService( true ).getTlgChat() | ||
| chatTlgAdapter = ChatTlgAdapter( ) | ||
|
|
||
| val manager = LinearLayoutManager(this) // LayoutManager | ||
| val rv = findViewById<RecyclerView>(R.id.recyclerView) | ||
| rv.adapter = chatTlgAdapter | ||
| rv.layoutManager = manager | ||
| dividerItemDecoration = DividerItemDecoration( | ||
| rv.context, | ||
| (rv.layoutManager as LinearLayoutManager).orientation | ||
| ) | ||
| rv.addItemDecoration(dividerItemDecoration) | ||
|
|
||
| chatTlgAdapter.setList( ChatTlgList ) | ||
|
|
||
| var callback = TlgItemTouchHelper( chatTlgAdapter ) | ||
| var itemTouchHelper = ItemTouchHelper( callback ) | ||
| itemTouchHelper.attachToRecyclerView( rv ) | ||
| rv.addOnScrollListener(object : RecyclerView.OnScrollListener() { | ||
| override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { | ||
| super.onScrolled(recyclerView, dx, dy) | ||
| if (!recyclerView.canScrollVertically(1)) { | ||
| var chatAddList = ChatTlgService( false ) | ||
| ChatTlgList = ChatTlgList + chatAddList.getTlgChat() | ||
| chatTlgAdapter.setList( ChatTlgList ) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. При достижении конца списка onScrolled может вызываться несколько раз подряд. Флаг isLoading для защиты от повторных вызовов будет хорошо смотреться |
||
| } | ||
| } | ||
| }) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| android:width="50dp" | ||
| android:height="50dp" | ||
| android:tint="@color/grey" | ||
| android:viewportWidth="24" | ||
| android:viewportHeight="24"> | ||
| <path | ||
| android:fillColor="@android:color/white" | ||
| android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,6c1.93,0 3.5,1.57 3.5,3.5S13.93,13 12,13s-3.5,-1.57 -3.5,-3.5S10.07,6 12,6zM12,20c-2.03,0 -4.43,-0.82 -6.14,-2.88C7.55,15.8 9.68,15 12,15s4.45,0.8 6.14,2.12C16.43,19.18 14.03,20 12,20z" /> | ||
| </vector> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||
| android:shape="oval"> | ||
| <solid android:color="#0085FD" /> | ||
| <padding | ||
| android:left="10dp" | ||
| android:top="5dp" | ||
| android:right="10dp" | ||
| android:bottom="5dp" /> | ||
| </shape> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,38 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| xmlns:tools="http://schemas.android.com/tools" | ||
| android:layout_width="match_parent" | ||
| android:layout_height="match_parent" | ||
| tools:context=".MainActivity"> | ||
|
|
||
| <androidx.recyclerview.widget.RecyclerView | ||
| android:id="@+id/recyclerView" | ||
| android:layout_width="match_parent" | ||
| android:layout_height="match_parent" /> | ||
|
|
||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity"> | ||
|
|
||
| <androidx.appcompat.widget.Toolbar | ||
| android:id="@+id/toolbar3" | ||
| android:layout_width="match_parent" | ||
| android:layout_height="wrap_content" | ||
| android:background="?attr/colorPrimary" | ||
| android:minHeight="?attr/actionBarSize" | ||
| android:theme="?attr/actionBarTheme" | ||
| app:layout_constraintEnd_toEndOf="parent" | ||
| app:layout_constraintStart_toStartOf="parent" | ||
| app:layout_constraintTop_toTopOf="parent" | ||
| app:logo="@drawable/menu" | ||
| app:title="Telegram" | ||
| app:titleMargin="4dp" | ||
| app:titleMarginEnd="20dp" | ||
| app:titleMarginStart="50dp" | ||
| app:titleTextAppearance="@style/TextAppearance.AppCompat.Body1" | ||
| app:titleTextColor="#F6FFFFFF" /> | ||
|
|
||
| <androidx.recyclerview.widget.RecyclerView | ||
| android:id="@+id/recyclerView" | ||
| android:layout_width="match_parent" | ||
| android:layout_height="match_parent" | ||
| android:layout_marginTop="55dp" | ||
| app:layout_constraintBottom_toBottomOf="parent" | ||
| app:layout_constraintEnd_toEndOf="parent" | ||
| app:layout_constraintHorizontal_bias="0.0" | ||
| app:layout_constraintStart_toStartOf="parent" | ||
| app:layout_constraintTop_toBottomOf="@+id/toolbar3" /> | ||
|
|
||
| </androidx.constraintlayout.widget.ConstraintLayout> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
При каждом обновлении списка перерисовываются все элементы через notifyDataSetChanged. Если будем использовать ListAdapter с DiffUtil.ItemCallback, то обновит только измененные элементы и улучшит производительность.