رابط کاربری اپلیکیشن موزیک پلیر برای ios با Adobe XD
رابط کاربری UI اپلیکیشن موزیک پلیر برای ios با Adobe XD
1397-10-13
نمودار دایره ای در اندروید
رسم نمودار دایره ای pie chart در اندروید با کاتلین
1397-10-19

آموزش Expandable RecyclerView در اندروید با کاتلین

آموزش Expandable RecyclerView در اندروید

آموزش Expandable RecyclerView در اندروید

آموزش Expandable RecyclerView در اندروید با کاتلین ، در این پست آموزشی ما یکی از پرکاربردترین ابزارهای اندروید یعنی RecyclerView رو داریم که میخوایم اون رو بصورت Expandable یا قابل گسترش دربیاریم !

آموزش Expandable RecyclerView در اندروید با کاتلین

کتابخونه هایی هستند که این کا ررو برای ما انجام میدن اما خب چکاریه زمانی که میتونیم خودمون اون رو پیاده و ایجاد کنیم بریم و کتایخونه ای به پروژه ایمپورت کنیم که حجم رو بالا میبره و هم ممکنه مشکلات دیگری از قبیل تداخب کتابخونه ها برامون بوجود بیاره(البته این مشکلات در خیلی استفاده از خیلی از کتابخانه ها بوجود نمیاد اما همیشه پیشگیری بهتر از درمانه 😀  ).

نتیجه آموزش زیر بصورت زیر خواهد بود (برای مشاهده گیف پایین روی اون کلیک کنید :)‌  )

آموزش Expandable RecyclerView در اندروید با کاتلین

آموزش Expandable RecyclerView در اندروید با کاتلین

ما تو این آموزش لیست قابل گسترش یا Expandable رو با کاستومایز کردن اداپتر و دیتا مدل مربوط به آیتم های لیست بصورت زیر ایجاد میکنیم.

خب بریم سراغ کدزدن 😉

اولین کاری که باید انجام بدیم این است که یک کلاس مدل برای دیتاهایی که میخوایم داخل لیست نمایش بدیم ایجاد کنیم که در کاتلین با کلمه کلیدی data model ایجاد میشه

نکته جالب درباره کلاس های کاتلین این است که دیگه خبری از getter , setter ها (یا اصطلاحا boilerplate code ها ) نیست بلکه کافیه از خود پراپرتی ها استفاده کنیم و فقط درصورتی که مثلا بخواهیم ادیتی در getter دهیم آنرا ایجاد میکنیم.

package dn.marjan.bosscompanysample

data class Users(var id: Int,var name: String,var family: String 
                 , var age: Int,var city: String ,var isSubFalg: Boolean)

فایل colors.xml نیز بصورت زیر است

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#801515</color>
    <color name="colorPrimaryDark">#550000</color>
    <color name="colorAccent">#D46A6A</color>
    <color name="white">#ffffff</color>
</resources>

من یک فایل استایل برا ردیوس دار کردن کانسترینت لیوت آیتم لیست نیز ایجاد کردم که بصورت زیر هستش

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!--<solid android:color="#FFFFFF"/>-->
    <!--<stroke android:width="3dp" android:color="#B1BCBE" />-->
    <corners android:radius="10dp"/>
    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>

در ادامه این فایل را با پراپرتی background به کانسرینت لیوت اختصاص دادم.

حالا لایه اصلی برنامه را یپاده میکنیم که تنها یک RecyclerView را درخود جای داده

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
    >

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">


            <android.support.v7.widget.RecyclerView
                android:id="@+id/rcv_pms"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_marginTop="8dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
        </android.support.constraint.ConstraintLayout>

    </android.support.v4.widget.NestedScrollView>


</android.support.constraint.ConstraintLayout>

و درادامه لایه آیتم های لیست را نیز پیاده میکنیم که براساس کلاس دیتا مدل هر تعداد تکست ویو یا هر آبجکت دیگر به آن اضافه میکنیم

ما در این لایه دو  ConstraintLayout داخلی و یک ConstraintLayout روت داریم که آن دو کانسترینت داخلی اهداف ما هستند و در اداپتر با آنها سروکار داریم.

بدین صورت که یکی از آنها که نام layout_sub_header بطور پیشفرض نمایش داده نمیشود بلکه زمانی که کاربر روی کانسترینت با نام layout_header کلیک کرد ، آن لایه نمایش داده میشود که این روند در اداپتر با استفاده از فیلد isSubFlag انجام میپذیرد (در ادامه خواهیم دید)

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView 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="wrap_content"
    android:layout_margin="10dp"
    app:cardCornerRadius="15dp">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/radios_style"
        >

        <android.support.constraint.ConstraintLayout
            android:id="@+id/layout_header"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorAccent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <TextView
                android:id="@+id/textView8"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginLeft="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:layout_marginRight="16dp"
                android:text="شناسه :‌"
                android:textColor="@color/white"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"
                app:layout_constraintStart_toEndOf="@+id/txv_id"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/txv_id"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView"
                android:textColor="@color/white"
                app:layout_constraintBottom_toBottomOf="@+id/textView8"
                app:layout_constraintEnd_toStartOf="@+id/textView8"
                app:layout_constraintHorizontal_bias="1.0"
                app:layout_constraintHorizontal_chainStyle="packed"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/textView8" />

            <TextView
                android:id="@+id/textView10"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginLeft="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:layout_marginRight="16dp"
                android:text="نام :"
                android:textColor="@color/white"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"
                app:layout_constraintStart_toEndOf="@+id/txv_name"
                app:layout_constraintTop_toBottomOf="@+id/textView8" />

            <TextView
                android:id="@+id/txv_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView"
                android:textColor="@color/white"
                app:layout_constraintBottom_toBottomOf="@+id/textView10"
                app:layout_constraintEnd_toStartOf="@+id/textView10"
                app:layout_constraintHorizontal_bias="1.0"
                app:layout_constraintHorizontal_chainStyle="packed"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/textView10" />

            <TextView
                android:id="@+id/textView12"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginLeft="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:layout_marginRight="16dp"
                android:layout_marginBottom="16dp"
                android:text="نام خانوادگی :"
                android:textColor="@color/white"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"
                app:layout_constraintStart_toEndOf="@+id/txv_family"
                app:layout_constraintTop_toBottomOf="@+id/textView10" />

            <TextView
                android:id="@+id/txv_family"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView"
                android:textColor="@color/white"
                app:layout_constraintBottom_toBottomOf="@+id/textView12"
                app:layout_constraintEnd_toStartOf="@+id/textView12"
                app:layout_constraintHorizontal_bias="1.0"
                app:layout_constraintHorizontal_chainStyle="packed"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/textView12" />

        </android.support.constraint.ConstraintLayout>

        <android.support.constraint.ConstraintLayout
            android:id="@+id/layout_sub_header"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="13dp"
            android:visibility="visible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/layout_header"
            app:layout_constraintVertical_bias="0.0">

            <TextView
                android:id="@+id/textView16"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginLeft="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:layout_marginRight="16dp"
                android:text="سن :"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"
                app:layout_constraintStart_toEndOf="@+id/txv_age"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/txv_age"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView"
                app:layout_constraintBottom_toBottomOf="@+id/textView16"
                app:layout_constraintEnd_toStartOf="@+id/textView16"
                app:layout_constraintHorizontal_bias="1.0"
                app:layout_constraintHorizontal_chainStyle="packed"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/textView16" />

            <TextView
                android:id="@+id/textView20"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginLeft="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:layout_marginRight="16dp"
                android:layout_marginBottom="8dp"
                android:text="شهر :"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"
                app:layout_constraintStart_toEndOf="@+id/txv_city"
                app:layout_constraintTop_toBottomOf="@+id/textView16" />

            <TextView
                android:id="@+id/txv_city"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView"
                app:layout_constraintBottom_toBottomOf="@+id/textView20"
                app:layout_constraintEnd_toStartOf="@+id/textView20"
                app:layout_constraintHorizontal_bias="1.0"
                app:layout_constraintHorizontal_chainStyle="packed"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/textView20" />

        </android.support.constraint.ConstraintLayout>
    </android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>

 

حالا فقط کافیه که کلاس اداپتر مربوط به ریسایکلرویو رو بسازیم

نکته خیلی مهم در این کلاس استفاه از متغیر isSubFlag دیتامدل هست که ما دراداپتر براساس این  متغیر تصمیم میگیریم که یک آیتم کلیک شده(لایه layout_sub_header باز شده) یا خیر که پیشفرض برای تمام آیتم ها False به معنی بسته خواهد بود

 

package dn.marjan.bosscompanysample

import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.item_user.view.*

class UsersAdapter(val usersList: ArrayList<Users>): RecyclerView.Adapter<UsersAdapter.MyViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_user,parent,false)
        return MyViewHolder(view)
    }

    override fun getItemCount(): Int = usersList.size

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val  user = usersList[position]

        holder.setItems(user)

        //decide that sub item should show or hidden
        if (user.isSubFalg)
            holder.itemView.layout_header.visibility = View.VISIBLE
        else
            holder.itemView.layout_sub_header.visibility =View.GONE

        //when click on item to show or hidden sub item
        holder.view.layout_header.setOnClickListener {
            if (user.isSubFalg){
                holder.itemView.layout_sub_header.visibility = View.GONE
                user.isSubFalg = false
            }else{
                holder.itemView.layout_sub_header.visibility =View.VISIBLE
                user.isSubFalg = true
            }
        }
    }

    class MyViewHolder(val view: View): RecyclerView.ViewHolder(view) {
        fun setItems(user: Users) {
            view.txv_age.text = user.age.toString()
            view.txv_name.text = user.name
            view.txv_family.text = user.family
            view.txv_id.text = user.id.toString()
            view.txv_city.text = user.city
        }

    }

}

و در انتها نیزفقط کلاس اکتیویتی اصلی مونده که در اون فقط آرایه ای برای نمایش در لیست ایجاد و مقدار دهی میکنیم

 

package dn.marjan.bosscompanysample

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.layout_base.*

class BaseActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_base)

        rcv_pms.layoutManager = LinearLayoutManager(this)

        setData()
    }

    private fun setData() {
        val list = ArrayList<Users>()
        list.add(Users(1, "ali", "asadi", 32, "shiraz",false))
        list.add(Users(1, "reza", "shahedi", 12, "esfahan",false))
        list.add(Users(1, "saeed", "hamedi", 24, "tehran",false))
        list.add(Users(1, "hamid", "jolan", 33, "tabriz",false))
        list.add(Users(1, "kave", "javadi", 32, "yaz",false))
        list.add(Users(1, "javad", "saeed", 21, "gilan",false))
        list.add(Users(1, "kian", "ilani", 22, "zanjan",false))

        val adapter = UsersAdapter(list)
        rcv_pms.adapter = adapter
    }
}

در انتها برنامه رو ران کنید وبا کلیک روی هرآیتم (layout_header) خواهید دید لایه زیرین آن (layout_sub_header) باز خواهد شد.

 

امیدوارم این پست براتون مفید بوده باشه و ازش استفاده کنید. از طریق راه های ارتباطی زیر میتونید با ما برای درخواست آموزش های اختصاصی و انواع پروژه ها در ارتباط باشید.

 

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *