API ডিফল্ট

Material, Compose UI এবং Foundation API ডিফল্ট হিসেবে অনেক অ্যাক্সেসিবিলিটি প্র্যাক্টিস প্রয়োগ ও অফার করে। এগুলিতে বিল্ট-ইন সিম্যান্টিক থাকে যা তাদের নির্দিষ্ট ভূমিকা এবং ফাংশন অনুসরণ করে। এর অর্থ হল, বেশিরভাগ অ্যাক্সেসিবিলিটি সহায়তা অতিরিক্ত কাজ ছাড়াই বা সামান্য কাজের মাধ্যমে প্রদান করা হয়।

উপযুক্ত উদ্দেশ্যে উপযুক্ত API ব্যবহার করার অর্থ হল, কম্পোনেন্টগুলি সাধারণত পূর্বনির্ধারিত অ্যাক্সেসিবিলিটি আচরণ সহ আসে যা স্ট্যান্ডার্ড ব্যবহারের ক্ষেত্রে কভার করে। তবে, এই ডিফল্ট সেটিংস আপনার অ্যাক্সেসিবিলিটি সংক্রান্ত প্রয়োজনীয়তা পূরণ করছে কিনা তা সবসময় ডবল-চেক করে নিন। যদি তা না হয়, তাহলে Compose আরও নির্দিষ্ট প্রয়োজনীয়তা পূরণ করার উপায় প্রদান করে।

Compose API-তে ডিফল্ট অ্যাক্সেসিবিলিটি সিম্যান্টিক্স এবং প্যাটার্ন বোঝা আপনাকে অ্যাক্সেসিবিলিটির কথা মাথায় রেখে সেগুলি ব্যবহার করতে সাহায্য করে। এটি আপনাকে আরও কাস্টম কম্পোনেন্টে অ্যাক্সেসিবিলিটি সাপোর্ট করতে সাহায্য করে।

টাচ টার্গেটের ন্যূনতম সাইজ

ক্লিক, টাচ বা ইন্টার‍্যাক্ট করতে পারেন এমন যেকোনও অন-স্ক্রিন এলিমেন্ট, নির্ভরযোগ্য ইন্টার‍্যাকশনের জন্য পর্যাপ্ত পরিমাণে বড় হতে হবে। এইসব এলিমেন্টের সাইজ নির্ধারণ করার সময়, মেটেরিয়াল ডিজাইন অ্যাক্সেসিবিলিটি নির্দেশিকা সঠিকভাবে অনুসরণ করতে, ন্যূনতম সাইজ ৪৮dp সেট করতে ভুলবেন না।

মেটেরিয়াল কম্পোনেন্ট—যেমন Checkbox, RadioButton, Switch, Slider এবং Surface—ইন্টার্নালি এই ন্যূনতম সাইজ সেট করে, তবে শুধুমাত্র কম্পোনেন্ট ব্যবহারকারীর অ্যাকশন গ্রহণ করতে পারলে তবেই এটি হয়। যেমন, Checkbox-এর onCheckedChange প্যারামিটার নন-নাল ভ্যালুতে সেট করা থাকলে, চেকবক্সে প্যাডিং অন্তর্ভুক্ত থাকে যাতে কমপক্ষে ৪৮ dp প্রস্থ ও উচ্চতা থাকে।

@Composable
private fun CheckableCheckbox() {
    Checkbox(checked = true, onCheckedChange = {})
}

৪৮ ডিপি প্রস্থ ও উচ্চতা সহ ডিফল্ট প্যাডিংয়ের চেকবক্স।
ছবি ১. ডিফল্ট প্যাডিং সহ চেকবক্স।

onCheckedChange প্যারামিটার নাল হিসেবে সেট করা হলে, প্যাডিং অন্তর্ভুক্ত করা হয় না, কারণ কম্পোনেন্টের সাথে সরাসরি ইন্টার‍্যাক্ট করা যায় না।

@Composable
private fun NonClickableCheckbox() {
    Checkbox(checked = true, onCheckedChange = null)
}

কোনও প্যাডিং নেই এমন চেকবক্স।
ছবি ২. প্যাডিং ছাড়া চেকবক্স।

Switch, RadioButton বা Checkbox-এর মতো বাছাই করার কন্ট্রোল প্রয়োগ করার সময়, আপনি সাধারণত কম্পোজেবলে ক্লিক কলব্যাক null-এ সেট করে এবং পেরেন্ট কম্পোজেবলে toggleable বা selectable মডিফায়ার যোগ করে পেরেন্ট কন্টেনারে ক্লিকেবল আচরণ লিফ্ট করেন।

@Composable
private fun CheckableRow() {
    MaterialTheme {
        var checked by remember { mutableStateOf(false) }
        Row(
            Modifier
                .toggleable(
                    value = checked,
                    role = Role.Checkbox,
                    onValueChange = { checked = !checked }
                )
                .padding(16.dp)
                .fillMaxWidth()
        ) {
            Text("Option", Modifier.weight(1f))
            Checkbox(checked = checked, onCheckedChange = null)
        }
    }
}

'বিকল্প' টেক্সটের পাশে একটি চেকবক্স যা বেছে নেওয়া ও অনির্বাচন করা হচ্ছে।
ছবি ৩. ক্লিক করা যায় এমন চেকবক্স।

ক্লিক করা যায় এমন কম্পোজেবলের সাইজ ন্যূনতম টাচ টার্গেটের সাইজের চেয়ে ছোট হলে, Compose টাচ টার্গেটের সাইজ বাড়িয়ে দেয়। এটি কম্পোজেবলের সীমানার বাইরে টাচ টার্গেটের সাইজ বাড়িয়ে এই কাজ করে।

নিচের উদাহরণে খুব ছোট ক্লিক করার মতো Box আছে। টাচ টার্গেট এলাকাটি Box-এর সীমানা ছাড়িয়ে অটোমেটিক প্রসারিত হয়, তাই Box-এর পাশে ট্যাপ করলেও ক্লিক ইভেন্ট ট্রিগার হয়।

@Composable
private fun SmallBox() {
    var clicked by remember { mutableStateOf(false) }
    Box(
        Modifier
            .size(100.dp)
            .background(if (clicked) Color.DarkGray else Color.LightGray)
    ) {
        Box(
            Modifier
                .align(Alignment.Center)
                .clickable { clicked = !clicked }
                .background(Color.Black)
                .size(1.dp)
        )
    }
}

খুব ছোট ক্লিক করার যোগ্য বক্স যা বক্সের পাশে ট্যাপ করে আরও বড় টাচ টার্গেটে প্রসারিত করা হয়।
ছবি ৪. একটি খুব ছোট ক্লিকযোগ্য বক্স যা একটি বড় টাচ টার্গেটে প্রসারিত হয়।

বিভিন্ন কম্পোজেবলের টাচ এরিয়ার মধ্যে সম্ভাব্য ওভারল্যাপ এড়াতে, কম্পোজেবলের জন্য সবসময় যথেষ্ট বড় ন্যূনতম সাইজ ব্যবহার করুন। উদাহরণে, এর অর্থ হল ভিতরের বক্সের জন্য ন্যূনতম সাইজ সেট করতে sizeIn মডিফায়ার ব্যবহার করা:

@Composable
private fun LargeBox() {
    var clicked by remember { mutableStateOf(false) }
    Box(
        Modifier
            .size(100.dp)
            .background(if (clicked) Color.DarkGray else Color.LightGray)
    ) {
        Box(
            Modifier
                .align(Alignment.Center)
                .clickable { clicked = !clicked }
                .background(Color.Black)
                .sizeIn(minWidth = 48.dp, minHeight = 48.dp)
        )
    }
}

আগের উদাহরণের খুব ছোট বক্সটির সাইজ বাড়িয়ে আরও বড় টাচ টার্গেট তৈরি করা হয়েছে।
ছবি ৫. একটি বড় বক্স টাচ টার্গেট।

এলিমেন্টকে যদি ছোট সাইজে দেখাতে হয়, তাহলে এর পরিবর্তে Material 3 থেকে minimumInteractiveComponentSize মডিফায়ার ব্যবহার করুন। এটি প্রতিটি ডাইমেনশনে লেআউট স্পেসের অন্তত ৪৮ dp রিজার্ভ করে এবং সেই স্পেসে এলিমেন্টকে সেন্টার করে, যাতে এলিমেন্টটি তার আঁকা সাইজ বজায় রাখে এবং এর চারপাশের এলিমেন্টগুলি জায়গা করে দেওয়ার জন্য সরে যায়। মডিফায়ার নিজে থেকে টাচ টার্গেট প্রসারিত করে না: এটি আগে বর্ণিত প্রসারণের জন্য লেআউটে জায়গা ছেড়ে দেয়। Checkbox-এর মতো মেটেরিয়াল কম্পোনেন্ট ইন্টার্নালি এই মডিফায়ার ব্যবহার করে। যেকোনও সাইজ মডিফায়ারের আগে এটি লিখুন, কারণ এর আগে সাইজ মডিফায়ার লিখলে এটি যে স্পেস রিজার্ভ করতে পারে তা সীমিত হয়ে যায়।

@Composable
private fun MinimumInteractiveBox() {
    var clicked by remember { mutableStateOf(false) }
    Row(verticalAlignment = Alignment.CenterVertically) {
        Box(
            Modifier
                .clickable { clicked = !clicked }
                .minimumInteractiveComponentSize()
                .size(24.dp)
                .background(if (clicked) Color.DarkGray else Color.Black)
        )
        Text("Option")
    }
}

গ্রাফিক এলিমেন্ট

আপনি যখন কোনও Image বা Icon কম্পোজেবল ডিফাইন করেন, তখন Android ফ্রেমওয়ার্কের কাছে অ্যাপটি কী দেখাচ্ছে তা বোঝার কোনও অটোমেটিক উপায় থাকে না। আপনাকে গ্রাফিক এলিমেন্টের টেক্সট বিবরণ দিতে হবে।

এমন একটি স্ক্রিনের কথা ভাবুন যেখানে ব্যবহারকারী বর্তমান পৃষ্ঠাটি বন্ধুদের সাথে শেয়ার করতে পারবেন। এই স্ক্রিনে ক্লিক করা যায় এমন শেয়ার আইকন আছে:

ক্লিক করা যায় এমন চারটি আইকনের স্ট্রিপ, যার মধ্যে 'শেয়ার করুন' আইকন হাইলাইট করা আছে।
ছবি ৬. 'শেয়ার করুন' আইকন বেছে নেওয়া সহ ক্লিক করা যায় এমন আইকনের একটি সারি।

শুধুমাত্র আইকনের উপর ভিত্তি করে, Android ফ্রেমওয়ার্ক দৃষ্টিশক্তির সমস্যা যুক্ত ব্যবহারকারীকে এটি বর্ণনা করতে পারে না। Android ফ্রেমওয়ার্কে আইকনের অতিরিক্ত টেক্সট বিবরণ প্রয়োজন।

contentDescription প্যারামিটার গ্রাফিক এলিমেন্টের বিবরণ দেয়। লোকালাইজ করা স্ট্রিং ব্যবহার করুন, কারণ এটি ব্যবহারকারী দেখতে পাবেন।

@Composable
private fun ShareButton(onClick: () -> Unit) {
    IconButton(onClick = onClick) {
        Icon(
            imageVector = Icons.Filled.Share,
            contentDescription = stringResource(R.string.label_share)
        )
    }
}

কিছু গ্রাফিক এলিমেন্ট শুধুমাত্র সাজানোর জন্য ব্যবহার করা হয় এবং আপনি হয়ত সেগুলি ব্যবহারকারীকে দেখাতে চাইবেন না। আপনি contentDescription প্যারামিটার null-এ সেট করলে, আপনি Android ফ্রেমওয়ার্ককে জানান যে এই এলিমেন্টের সাথে কোনও অ্যাকশন বা স্ট্যাটাস যুক্ত নেই।

@Composable
private fun PostImage(post: Post, modifier: Modifier = Modifier) {
    val image = post.imageThumb ?: painterResource(R.drawable.placeholder_1_1)

    Image(
        painter = image,
        // Specify that this image has no semantic meaning
        contentDescription = null,
        modifier = modifier
            .size(40.dp, 40.dp)
            .clip(MaterialTheme.shapes.small)
    )
}

contentDescription মূলত গ্রাফিক এলিমেন্টের জন্য ব্যবহার করা হয়, যেমন ছবি। Button বা Text-এর মতো মেটেরিয়াল কম্পোনেন্ট এবং clickable বা toggleable-এর মতো অ্যাকশনযোগ্য আচরণ, অন্যান্য পূর্বনির্ধারিত শব্দার্থবিদ্যার সাথে আসে যা তাদের অন্তর্নিহিত আচরণ বর্ণনা করে এবং অন্যান্য Compose API-এর মাধ্যমে পরিবর্তন করা যেতে পারে।

ইন্টার‌্যাক্টিভ এলিমেন্ট

Material ও Foundation Compose API এমন UI এলিমেন্ট তৈরি করে যার মাধ্যমে ব্যবহারকারীরা clickable ও toggleable মডিফায়ার API-এর সাহায্যে ইন্টার‍্যাক্ট করতে পারেন। ইন্টার‍্যাক্ট করা যায় এমন কম্পোনেন্টে একাধিক এলিমেন্ট থাকতে পারে, তাই clickable এবং toggleable ডিফল্ট হিসেবে চিলড্রেন সিম্যান্টিক মার্জ করে, যাতে কম্পোনেন্টকে একটি লজিক্যাল এন্টিটি হিসেবে বিবেচনা করা হয়।

যেমন, কোনও মেটেরিয়াল Button-এ একটি চাইল্ড আইকন এবং কিছু টেক্সট থাকতে পারে। চিলড্রেনকে আলাদা আলাদা হিসেবে বিবেচনা করার পরিবর্তে, একটি Material Button ডিফল্ট হিসেবে তার চিলড্রেন সিম্যান্টিক্স মার্জ করে, যাতে অ্যাক্সেসিবিলিটি পরিষেবা সেই অনুযায়ী তাদের গ্রুপ করতে পারে:

আনমার্জ করা বনাম মার্জ করা চাইল্ড সিম্যান্টিক সহ বোতাম।
ছবি ৭. আনমার্জ করা বনাম মার্জ করা চিলড্রেন সিম্যান্টিক সহ বোতাম।

একইভাবে, clickable মডিফায়ার ব্যবহার করলে, কম্পোজেবল তার ডিসেন্ডেন্টের সিম্যান্টিকসকে একটি এন্টিটিতে মার্জ করে, যা সংশ্লিষ্ট অ্যাকশন রিপ্রেজেন্টেশনের সাথে অ্যাক্সেসিবিলিটি পরিষেবায় পাঠানো হয়:

Row(
    // Uses `mergeDescendants = true` under the hood
    modifier = Modifier.clickable { openArticle() }
) {
    Icon(
        painter = painterResource(R.drawable.ic_logo),
        contentDescription = "Open",
    )
    Text("Accessibility in Compose")
}

এছাড়াও, আপনি অ্যাক্সেসিবিলিটি পরিষেবার জন্য অতিরিক্ত তথ্য প্রদান করতে এবং অ্যাকশনের আরও পরিমার্জিত উপস্থাপনা অফার করতে, ক্লিক করা যায় এমন পেরেন্ট এলিমেন্টে একটি নির্দিষ্ট onClickLabel সেট করতে পারেন:

Row(
    modifier = Modifier
        .clickable(onClickLabel = "Open this article") {
            openArticle()
        }
) {
    Icon(
        painter = painterResource(R.drawable.ic_logo),
        contentDescription = "Open"
    )
    Text("Accessibility in Compose")
}

উদাহরণ হিসেবে টকব্যাক ব্যবহার করে, এই clickable মডিফায়ার এবং এর ক্লিক লেবেল টকব্যাককে "এই নিবন্ধটি খুলতে ডবল ট্যাপ করুন" অ্যাকশন ইঙ্গিত প্রদান করতে সক্ষম করবে, "অ্যাক্টিভেট করতে ডবল ট্যাপ করুন" আরও জেনেরিক ডিফল্ট প্রতিক্রিয়ার পরিবর্তে।

অ্যাকশনের ধরনের উপর নির্ভর করে এই মতামত পরিবর্তিত হয়। দীর্ঘক্ষণ ক্লিক করলে "ডবল ট্যাপ করে ধরে থাকুন" টকব্যাক ইঙ্গিত প্রদান করবে, তারপরে একটি লেবেল থাকবে:

Row(
    modifier = Modifier
        .combinedClickable(
            onLongClickLabel = "Bookmark this article",
            onLongClick = { addToBookmarks() },
            onClickLabel = "Open this article",
            onClick = { openArticle() },
        )
) {}

কিছু ক্ষেত্রে, আপনার কাছে clickable মডিফায়ারের সরাসরি অ্যাক্সেস নাও থাকতে পারে (যেমন, যখন এটি কোনও নিম্ন নেস্টেড লেয়ারে সেট করা থাকে),কিন্তু তবুও আপনি ডিফল্ট থেকে ঘোষণা লেবেল পরিবর্তন করতে চান। এটি করতে, semantics মডিফায়ার ব্যবহার করে ঘোষণা পরিবর্তন করা থেকে clickable সেটিংকে আলাদা করুন এবং অ্যাকশন উপস্থাপনা পরিবর্তন করতে সেখানে ক্লিক লেবেল সেট করুন:

@Composable
private fun ArticleList(openArticle: () -> Unit) {
    NestedArticleListItem(
        // Clickable is set separately, in a nested layer:
        onClickAction = openArticle,
        // Semantics are set here:
        modifier = Modifier.semantics {
            onClick(
                label = "Open this article",
                action = {
                    // Not needed here: openArticle()
                    true
                }
            )
        }
    )
}

আপনাকে দুবার ক্লিক অ্যাকশন পাস করতে হবে না। আগে থেকে থাকা Compose API, যেমন clickable বা Button, আপনার জন্য এটি ম্যানেজ করে। মার্জিং লজিক যাচাই করে যে, উপস্থিত তথ্যের জন্য সবচেয়ে বাইরের মডিফায়ার লেবেল এবং অ্যাকশন নেওয়া হয়েছে। আগের উদাহরণে, NestedArticleListItem অটোমেটিক openArticle() ক্লিক অ্যাকশনকে সেটির clickable সিমেন্টিকে পাস করে। আপনি দ্বিতীয় সিমেন্টিক মডিফায়ার অ্যাকশনে ক্লিক অ্যাকশন নাল হিসেবে ছেড়ে দিতে পারেন। তবে, ক্লিক লেবেলটি দ্বিতীয় সিম্যান্টিক্স মডিফায়ার থেকে নেওয়া হয়েছে onClick(label = "Open this document") কারণ এটি প্রথমটিতে ছিল না।

আপনি এমন পরিস্থিতিতে পড়তে পারেন যেখানে আপনি আশা করেন যে চাইল্ড সিম্যান্টিকস প্যারেন্ট সিম্যান্টিকসের সাথে মার্জ হয়ে যাবে, কিন্তু তা হয় না। আরও বিস্তারিত তথ্যের জন্য মার্জ ও মুছে ফেলা দেখুন।

কাস্টম কম্পোনেন্ট

কাস্টম কম্পোনেন্ট তৈরি করার সময়, Material লাইব্রেরি বা অন্যান্য Compose লাইব্রেরিতে একই ধরনের কম্পোনেন্টের প্রয়োগ পর্যালোচনা করুন। তারপর, প্রয়োজন অনুযায়ী এর অ্যাক্সেসিবিলিটি আচরণ নকল বা পরিবর্তন করুন। যেমন, আপনি যদি মেটেরিয়াল Checkbox-এর পরিবর্তে আপনার নিজস্ব ইমপ্লিমেন্টেশন ব্যবহার করেন, তাহলে আগে থেকে থাকা Checkbox ইমপ্লিমেন্টেশন দেখলে আপনার triStateToggleable মডিফায়ার যোগ করার কথা মনে পড়বে, যা কম্পোনেন্টের অ্যাক্সেসিবিলিটি প্রপার্টি ম্যানেজ করে। এছাড়াও, ফাউন্ডেশন মডিফায়ার ব্যাপকভাবে ব্যবহার করুন, কারণ এগুলির মধ্যে বিল্ট-ইন অ্যাক্সেসিবিলিটি সংক্রান্ত বিবেচনা এবং এই বিভাগে কভার করা বিদ্যমান কম্পোজ অনুশীলন অন্তর্ভুক্ত রয়েছে।

এছাড়াও, আপনি সিম্যান্টিক্স বিভাগ মুছুন ও সেট করুন বিকল্পে কাস্টম টগল কম্পোনেন্টের উদাহরণ খুঁজে পাবেন, এর পাশাপাশি API নির্দেশিকায় কাস্টম কম্পোনেন্টে অ্যাক্সেসিবিলিটি কীভাবে কাজ করে সেই সম্পর্কে আরও বিস্তারিত তথ্য পাবেন।