فعال و غیرفعال کردن View در اندروید

فعال و غیرفعال کردن View در اندروید
در این پست می‌خوانید:

بعضی مواقع پیش میاد که ما میخوایم بخشی از طراحی خودمون رو غیرفعال کنیم.

فرضا اگه کاربر فلان کار رو انجام نداده باشه، یه بخشی از اپلیکیشن رو نتونه ازش استفاده کنه.

اینجور مواقع اکثرا میان اون بخش هایی که غیرفعال هستن رو خاکستری میکنن که کابر متوجه بشه که این بخش در دسترس نیستش.

برای اینکار برنامه نویس ها میان 2 طرح مجزا رو طراحی میکنن.

یکی برای حالت فعال و یکی هم برای حالت غیرفعال!

خب عملا این روش بدترین روش هستش?

چون اگه بخوای تغییری توی طرح ایجاد بکنی باید برای هر 2 حالت طرحت رو تغییر بدی?

خب راه حل چیه؟ پس باید چیکار کرد؟

راه حل چیزیه که میخوام تویه این پست بگم?

 

برای اینکه بهتر منظورم رو درک کنی پشنهاد میکنم دمو رو ببینی.

دمو نتیجه انجام شده

فعال و غیرفعال کردن Viewها

توی این پست میخوام یک Custom View (ویو سفارشی) درست کنم که هر ویوای که داخل اون قرار بدین قابلیت غیرفعال کردن رو میتونه بگیره.

برای ساختن این Custom view از Constraint layout استفاده کردم.

همونطور که میدونی ConstraintLayout یکی از لایه های اندروید هستش که میشه باهاش طراحی رابط کاربری انجام داد.

 

البته به نظر من ConstraintLayout بهترین لایه اندروید هستش.

ساخت ویو سفارشی از ConstraintLayout

برای ساختن این ویو سفارشی همونطور که گفتم از Constraint Layout استفاده کردم.

من اسم این ویو رو ConstraintLayoutWithDisableSupport گذاشتم.

یعنی ConstraintLayoutای که حالت غیرفعال رو پشتیبانی میکنه?.

اول از همه از Point استفاده کردم که بتونم به واسطه اون، نقاط رنگی مختلف رو روی ویوهای خودم اعمال کنم.

بعد از اون رنگ خاکستری رو به صورت آرایه درست کردم و در این نقاط اعمال کردم.

کدی که نوشتن به شکل زیر هستش

 private val paint = Paint()

val cm = ColorMatrix()
   cm.set(
         floatArrayOf(
             0.33f, 0.33f, 0.33f, 0f, 0f,
             0.33f, 0.33f, 0.33f, 0f, 0f,
             0.33f, 0.33f, 0.33f, 0f, 0f,
             0f, 0f, 0f, 1f, 0f
         )
     )
     paint.colorFilter = ColorMatrixColorFilter(cm)

البته این بخشی از کد هستش که در ادامه کدنهایی رو هم قرار میدم.

توضیحاتی در مورد ساختار کد

بر اساس درک من از پردازش تصویر، در حالت ایده آل ما باید بتونیم هر رنگ RGB رو با یک ماتریس ضرب کنیم و در نتیجه رنگی به رنگ خاکستری بدست بیاریم.

سپس سعی کردم API مشابهی رو توی Android و ColorMatrix پیدا کنم که همراه با برخی از سفارشی سازی ها مواردی که مدنظرم بود رو میتونستم پیاده سازی کنم.

من تصمیم گرفتم یک ماتریس سفارشی رو با مقادیر مساوی قرمز، سبز و آبی آزمایش کنم.

از اون موارد واسه فیلترهای رنگی برای CustomView استفاده کردم که اجازه میداد رنگ های ویوها رو به خاکستری تغییر بدم.

نتیجه توضیحات بالا کد زیر شد، چیزی که میتونستم باهاش ویوهام رو تغییر رنگ بدم.

private val paint = Paint()
val cm = ColorMatrix()
cm.set(
    floatArrayOf(
        0.33f, 0.33f, 0.33f, 0f, 0f,
        0.33f, 0.33f, 0.33f, 0f, 0f,
        0.33f, 0.33f, 0.33f, 0f, 0f,
        0f, 0f, 0f, 1f, 0f
    )
)
paint.colorFilter = ColorMatrixColorFilter(cm)

از نقاط بالا توی Canvas با استفاده از متدهای dispatchDraw() و draw() میتونیم رنگ خاکستری رو اعمال کنیم.

به این صورت من از کد بالا توی ConstraintLayout استفاده کردم.

کدنهایی مربوط به Constraint Layout سفارشی

import android.content.Context
import android.graphics.Canvas
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.Paint
import android.util.AttributeSet
import androidx.constraintlayout.widget.ConstraintLayout

class ConstraintLayoutWithDisableSupport @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

    var disabled = false
        set(value) {
            field = value
            requestLayout()
        }

    private val paint = Paint()

    init {
        val cm = ColorMatrix()
        cm.set(
            floatArrayOf(
                0.33f, 0.33f, 0.33f, 0f, 0f,
                0.33f, 0.33f, 0.33f, 0f, 0f,
                0.33f, 0.33f, 0.33f, 0f, 0f,
                0f, 0f, 0f, 1f, 0f
            )
        )
        paint.colorFilter = ColorMatrixColorFilter(cm)
    }

    override fun dispatchDraw(canvas: Canvas?) {
        if (disabled) {
            canvas?.saveLayer(null, paint)
        }

        super.dispatchDraw(canvas)

        if (disabled) {
            canvas?.restore()
        }
    }

    override fun draw(canvas: Canvas?) {
        if (disabled) {
            canvas?.saveLayer(null, paint)
        }

        super.draw(canvas)

        if (disabled) {
            canvas?.restore()
        }
    }
}

استفاده از این ویو سفارشی

استفاده کردن از این ویو فوق‌العاده راحته.

فقط کافیه ویوهایی که میخوای فعا‌ل و غیرفعا‌ل بشن رو داخل این لایه قرار بدی.

این لایه هم از نظر ساختار درست مثل ConstraintLayout هستش و هیچ فرقی نمیکنه.

تمامی آپشن ها و امکانات اون رو داره.

من میخوام طرحی که توی دمو نشون دادم رو درست کنم.

برای اینکار از 2 تا لایه استفاده کردم.

لایه اصلی که در واقع مربوط به صفحه کلی میشه که Switch مربوط به غیرفعا‌ل کردن رو داره.

لایه دوم هم مواردی که میخوام فعا‌ل و غیرفعا‌ل بشن رو داخل اون قرار دادم.

 

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

کدهای مربوط به لایه اصلی

<?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=".disable_constraintlayout.DisableConstraintPage">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/disableConstraintPage_switchLay"
        android:layout_width="0dp"
        android:layout_height="70dp"
        android:background="@color/aquaBlue"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/disableConstraintPage_switchTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:fontFamily="@font/iran_sans"
            android:text="فعال / غیرفعال کردن لایه ها"
            android:layout_marginRight="20dp"
            android:textColor="@color/bgLight"
            android:textSize="12sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.appcompat.widget.SwitchCompat
            android:id="@+id/disableConstraintPage_switch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:checked="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/disableConstraintPage_switchTxt"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    <include
        android:id="@+id/sample_view"
        layout="@layout/disable_constraintlayout_items"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/disableConstraintPage_switchLay" />

</androidx.constraintlayout.widget.ConstraintLayout>

کدهای مربوط به ویوهای فعا‌ل و غیرفعا‌ل شده

<?xml version="1.0" encoding="utf-8"?>
<in.nouri.myinstagramtutorials.disable_constraintlayout.ConstraintLayoutWithDisableSupport 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:padding="20dp">

    <ImageView
        android:id="@+id/iv_image"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:src="@drawable/my"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="ContentDescription" />

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:fontFamily="@font/iran_sans"
        android:text="محمد نوری"
        android:textColor="@color/teal_700"
        android:textSize="26sp"
        app:layout_constraintEnd_toEndOf="@+id/iv_image"
        app:layout_constraintStart_toStartOf="@+id/iv_image"
        app:layout_constraintTop_toBottomOf="@+id/iv_image" />

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/tv_site"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="www.nouri.academy"
        android:textColor="@color/pink"
        android:textSize="16sp"
        app:layout_constraintEnd_toEndOf="@+id/iv_image"
        app:layout_constraintStart_toStartOf="@+id/iv_image"
        app:layout_constraintTop_toBottomOf="@id/tv_title" />

    <com.google.android.material.card.MaterialCardView
        android:id="@+id/item1"
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:layout_marginTop="10dp"
        app:cardBackgroundColor="@color/itemColor2"
        app:cardCornerRadius="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_site"
        app:strokeColor="@color/itemColorStroke"
        app:strokeWidth="1dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:fontFamily="@font/iran_sans"
            android:text="آیتم اول"
            android:textColor="@color/bgLight"
            android:textSize="16sp" />

    </com.google.android.material.card.MaterialCardView>

    <com.google.android.material.card.MaterialCardView
        android:id="@+id/item2"
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:layout_marginTop="10dp"
        app:cardBackgroundColor="@color/itemColor2"
        app:cardCornerRadius="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/item1"
        app:strokeColor="@color/itemColorStroke"
        app:strokeWidth="1dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:fontFamily="@font/iran_sans"
            android:text="آیتم دوم"
            android:textColor="@color/bgLight"
            android:textSize="16sp" />

    </com.google.android.material.card.MaterialCardView>

</in.nouri.myinstagramtutorials.disable_constraintlayout.ConstraintLayoutWithDisableSupport>

 

نتیجه نهایی مثل عکس زیر میشه

enable-disable-layout-active-فعال-constraintlayout

من قصد داشتم کل لایه رو غیرفعا‌ل کنم، برای همین تمامی ویوها رو داخل ConstraintLayoutWithDisableSupport نوشتم.

حالا شما با توجه به طرح خودت میتونی اون ویوها رو داخل این لایه قرار بدی.

کدهای مربوط به کاتلین

برای اینکه بتونی ویوها رو به صورت داینامیک فعا‌ل و غیرفعا‌ل باید به صورت کاتلین (یا جاوا) اون رو هندل کنی.

من برای اینکار کد زیر رو نوشتم

class DisableConstraintPage : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_disable_constraint_page)

        disableConstraintPage_switch.setOnCheckedChangeListener { _, _ ->
            if (disableConstraintPage_switch.isChecked) {
                setSampleViewToEnabled()
            } else {
                setSampleViewToDisabled()
            }
        }
    }

    private fun setSampleViewToDisabled() {
        (sample_view as ConstraintLayoutWithDisableSupport).disabled = true
    }

    private fun setSampleViewToEnabled() {
        (sample_view as ConstraintLayoutWithDisableSupport).disabled = false
    }
}

این کد 2 تا متد داره.

  • setSampleViewToDisabled : برای غیرفعا‌ل کردن ویوها
  • setSampleViewToEnabled : برای فعال کردن ویوها

برای فعا‌ل یا غیرفعا‌ل کردن لایه فقط کافیه که ID لایه رو بنویسی و بعدش از disabled استفاده کنی.
درست مثل کاری که من توی این 2 تا متد انجام دادم.

بعد از اجرا کردن اپلیکیشن و زدن دکمه غیرفعا‌ل کردن، ویوهات مثل عکس زیر خاکستری میشن.

enable-disable-layout-deactive-constraint layout-اندروید

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

دیدگاه‌ها ۱
ارسال دیدگاه جدید