কম্পোজ অ্যাক্সেসিবিলিটি উন্নত করার জন্য মূল পদক্ষেপ

অ্যাক্সেসযোগ্যতার প্রয়োজন আছে এমন লোকেদের আপনার অ্যাপটি সফলভাবে ব্যবহার করতে সাহায্য করার জন্য, মূল অ্যাক্সেসিবিলিটি প্রয়োজনীয়তাগুলিকে সমর্থন করার জন্য আপনার অ্যাপটি ডিজাইন করুন।

ন্যূনতম স্পর্শ লক্ষ্য আকার বিবেচনা করুন

যে কোনও অন-স্ক্রিন উপাদান যা কেউ ক্লিক করতে, স্পর্শ করতে বা ইন্টারঅ্যাক্ট করতে পারে তা নির্ভরযোগ্য ইন্টারঅ্যাকশনের জন্য যথেষ্ট বড় হওয়া উচিত। এই উপাদানগুলিকে আকার দেওয়ার সময়, মেটেরিয়াল ডিজাইন অ্যাক্সেসিবিলিটি নির্দেশিকাগুলি সঠিকভাবে অনুসরণ করতে সর্বনিম্ন আকার 48dp সেট করা নিশ্চিত করুন৷

উপাদান উপাদানগুলি — যেমন Checkbox , RadioButton , Switch , Slider , এবং Surface — এই ন্যূনতম আকারটি অভ্যন্তরীণভাবে সেট করুন, কিন্তু শুধুমাত্র যখন উপাদানটি ব্যবহারকারীর ক্রিয়াগুলি গ্রহণ করতে পারে৷ উদাহরণস্বরূপ, যখন একটি Checkbox onCheckedChange প্যারামিটার একটি নন-নাল মান সেট করা থাকে, তখন চেকবক্সে প্যাডিং অন্তর্ভুক্ত থাকে যার প্রস্থ এবং উচ্চতা কমপক্ষে 48 ডিপি থাকে৷

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

যখন onCheckedChange প্যারামিটারটি নাল সেট করা হয়, তখন প্যাডিং অন্তর্ভুক্ত করা হয় না, কারণ উপাদানটির সাথে সরাসরি যোগাযোগ করা যায় না।

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

চিত্র 1. প্যাডিং ছাড়া একটি চেকবক্স।

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)
        }
    }
}

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

নিম্নলিখিত উদাহরণে একটি খুব ছোট ক্লিকযোগ্য 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)
        )
    }
}

ক্লিক লেবেল যোগ করুন

আপনি একটি কম্পোজেবলের ক্লিক আচরণে শব্দার্থগত অর্থ যোগ করতে একটি ক্লিক লেবেল ব্যবহার করতে পারেন। ক্লিক লেবেল বর্ণনা করে যখন ব্যবহারকারী কম্পোজেবলের সাথে ইন্টারঅ্যাক্ট করে তখন কী ঘটে। অ্যাক্সেসিবিলিটি পরিষেবাগুলি নির্দিষ্ট প্রয়োজনের ব্যবহারকারীদের কাছে অ্যাপটি বর্ণনা করতে সাহায্য করার জন্য ক্লিক লেবেল ব্যবহার করে।

clickable মডিফায়ারে একটি প্যারামিটার পাস করে ক্লিক লেবেল সেট করুন:

@Composable
private fun ArticleListItem(openArticle: () -> Unit) {
    Row(
        Modifier.clickable(
            // R.string.action_read_article = "read article"
            onClickLabel = stringResource(R.string.action_read_article),
            onClick = openArticle
        )
    ) {
        // ..
    }
}

বিকল্পভাবে, যদি আপনার ক্লিকযোগ্য মডিফায়ারে অ্যাক্সেস না থাকে, তাহলে শব্দার্থবিদ্যা মডিফায়ারে ক্লিক লেবেল সেট করুন:

@Composable
private fun LowLevelClickLabel(openArticle: () -> Boolean) {
    // R.string.action_read_article = "read article"
    val readArticleLabel = stringResource(R.string.action_read_article)
    Canvas(
        Modifier.semantics {
            onClick(label = readArticleLabel, action = openArticle)
        }
    ) {
        // ..
    }
}

চাক্ষুষ উপাদান বর্ণনা করুন

আপনি যখন একটি Image বা Icon কম্পোজযোগ্য সংজ্ঞায়িত করেন, তখন অ্যাপটি কী প্রদর্শন করছে তা বোঝার জন্য 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 প্রয়োজন কিনা তা সিদ্ধান্ত নেওয়া আপনার উপর নির্ভর করে। নিজেকে জিজ্ঞাসা করুন যে উপাদানটি তথ্য প্রকাশ করে যা ব্যবহারকারীকে তাদের কাজ সম্পাদন করতে হবে। যদি তা না হয় তবে বর্ণনাটি ছেড়ে দেওয়া ভাল।

উপাদান একত্রিত করুন

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

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

যৌক্তিক গোষ্ঠী গঠন করে এমন কম্পোজেবলের একটি সেট থাকা সম্ভব, কিন্তু সেই গোষ্ঠীটি ক্লিকযোগ্য বা তালিকা আইটেমের অংশ নয়। আপনি এখনও অ্যাক্সেসিবিলিটি পরিষেবাগুলিকে একটি উপাদান হিসাবে দেখতে চান৷ উদাহরণস্বরূপ, একটি কম্পোজেবল কল্পনা করুন যা একজন ব্যবহারকারীর অবতার, তাদের নাম এবং কিছু অতিরিক্ত তথ্য দেখায়:

ব্যবহারকারীর নাম সহ UI উপাদানগুলির একটি গ্রুপ৷ নাম নির্বাচন করা হয়।

আপনি semantics মডিফায়ারে mergeDescendants প্যারামিটার ব্যবহার করে এই উপাদানগুলিকে একত্রিত করতে রচনা সক্রিয় করতে পারেন। এইভাবে, অ্যাক্সেসিবিলিটি পরিষেবাগুলি শুধুমাত্র মার্জ করা উপাদান নির্বাচন করে, এবং বংশধরদের সমস্ত শব্দার্থিক বৈশিষ্ট্য একত্রিত হয়।

@Composable
private fun PostMetadata(metadata: Metadata) {
    // Merge elements below for accessibility purposes
    Row(modifier = Modifier.semantics(mergeDescendants = true) {}) {
        Image(
            imageVector = Icons.Filled.AccountCircle,
            contentDescription = null // decorative
        )
        Column {
            Text(metadata.author.name)
            Text("${metadata.date}  ${metadata.readTimeMinutes} min read")
        }
    }
}

অ্যাক্সেসিবিলিটি পরিষেবাগুলি এখন তাদের বিষয়বস্তু একত্রিত করে পুরো কন্টেইনারে ফোকাস করে:

ব্যবহারকারীর নাম সহ UI উপাদানগুলির একটি গ্রুপ৷ সমস্ত উপাদান একসঙ্গে নির্বাচন করা হয়.

কাস্টম অ্যাকশন যোগ করুন

নিম্নলিখিত তালিকা আইটেমটি একবার দেখুন:

একটি সাধারণ তালিকা আইটেম, একটি নিবন্ধের শিরোনাম, লেখক, এবং বুকমার্ক আইকন রয়েছে।

আপনি যখন স্ক্রিনে কী প্রদর্শিত হচ্ছে তা শুনতে Talkback-এর মতো স্ক্রিন রিডার ব্যবহার করেন, এটি প্রথমে পুরো আইটেমটি এবং তারপর বুকমার্ক আইকনটি নির্বাচন করে৷

তালিকা আইটেম, সব উপাদান একসঙ্গে নির্বাচিত.

তালিকা আইটেম, শুধুমাত্র বুকমার্ক আইকন নির্বাচিত সঙ্গে

একটি দীর্ঘ তালিকায়, এটি খুব পুনরাবৃত্তি হতে পারে। একটি ভাল পদ্ধতি হল একটি কাস্টম অ্যাকশন সংজ্ঞায়িত করা যা একজন ব্যবহারকারীকে আইটেম বুকমার্ক করতে দেয়। মনে রাখবেন যে এটি অ্যাক্সেসিবিলিটি পরিষেবা দ্বারা নির্বাচিত নয় তা নিশ্চিত করার জন্য আপনাকে বুকমার্ক আইকনের আচরণকে স্পষ্টভাবে সরাতে হবে৷ এটি clearAndSetSemantics মডিফায়ার দিয়ে করা হয়:

@Composable
private fun PostCardSimple(
    /* ... */
    isFavorite: Boolean,
    onToggleFavorite: () -> Boolean
) {
    val actionLabel = stringResource(
        if (isFavorite) R.string.unfavorite else R.string.favorite
    )
    Row(
        modifier = Modifier
            .clickable(onClick = { /* ... */ })
            .semantics {
                // Set any explicit semantic properties
                customActions = listOf(
                    CustomAccessibilityAction(actionLabel, onToggleFavorite)
                )
            }
    ) {
        /* ... */
        BookmarkButton(
            isBookmarked = isFavorite,
            onClick = onToggleFavorite,
            // Clear any semantics properties set on this node
            modifier = Modifier.clearAndSetSemantics { }
        )
    }
}

একটি উপাদানের অবস্থা বর্ণনা করুন

একটি কম্পোজেবল শব্দার্থবিদ্যার জন্য একটি stateDescription সংজ্ঞায়িত করতে পারে যা অ্যান্ড্রয়েড ফ্রেমওয়ার্ক কম্পোজেবলটি যে অবস্থায় রয়েছে তা পড়ার জন্য ব্যবহার করে৷ উদাহরণস্বরূপ, একটি টগলযোগ্য কম্পোজেবল একটি "চেক করা" বা "আনচেক করা" অবস্থায় হতে পারে। কিছু ক্ষেত্রে, আপনি ডিফল্ট স্টেট বর্ণনা লেবেলগুলিকে ওভাররাইড করতে চাইতে পারেন যা রচনা করে। আপনি একটি কম্পোজেবলকে টগলযোগ্য হিসাবে সংজ্ঞায়িত করার আগে রাজ্যের বর্ণনার লেবেলগুলি স্পষ্টভাবে উল্লেখ করে তা করতে পারেন:

@Composable
private fun TopicItem(itemTitle: String, selected: Boolean, onToggle: () -> Unit) {
    val stateSubscribed = stringResource(R.string.subscribed)
    val stateNotSubscribed = stringResource(R.string.not_subscribed)
    Row(
        modifier = Modifier
            .semantics {
                // Set any explicit semantic properties
                stateDescription = if (selected) stateSubscribed else stateNotSubscribed
            }
            .toggleable(
                value = selected,
                onValueChange = { onToggle() }
            )
    ) {
        /* ... */
    }
}

শিরোনাম সংজ্ঞায়িত করুন

অ্যাপগুলি কখনও কখনও একটি স্ক্রোলযোগ্য পাত্রে একটি স্ক্রিনে অনেকগুলি সামগ্রী দেখায়৷ উদাহরণস্বরূপ, একটি স্ক্রীন একটি নিবন্ধের সম্পূর্ণ বিষয়বস্তু দেখাতে পারে যা ব্যবহারকারী পড়ছেন:

একটি স্ক্রোলযোগ্য পাত্রে নিবন্ধের পাঠ্য সহ একটি ব্লগ পোস্টের স্ক্রিনশট৷

অ্যাক্সেসিবিলিটি প্রয়োজন ব্যবহারকারীদের এই ধরনের স্ক্রীন নেভিগেট করতে অসুবিধা হয়। নেভিগেশন সাহায্য করতে, কোন উপাদান শিরোনাম নির্দেশ করুন. পূর্ববর্তী উদাহরণে, প্রতিটি উপধারার শিরোনাম অ্যাক্সেসযোগ্যতার শিরোনাম হিসাবে সংজ্ঞায়িত করা যেতে পারে। কিছু অ্যাক্সেসিবিলিটি পরিষেবা, যেমন টকব্যাক, ব্যবহারকারীদের সরাসরি শিরোনাম থেকে শিরোনামে নেভিগেট করতে দেয়।

কম্পোজে, আপনি ইঙ্গিত করেন যে একটি কম্পোজেবল একটি শিরোনাম তার semantics বৈশিষ্ট্য সংজ্ঞায়িত করে:

@Composable
private fun Subsection(text: String) {
    Text(
        text = text,
        style = MaterialTheme.typography.headlineSmall,
        modifier = Modifier.semantics { heading() }
    )
}

কাস্টম কম্পোজেবল হ্যান্ডেল

যখনই আপনি কাস্টম সংস্করণের সাথে আপনার অ্যাপে কিছু উপাদানের উপাদান প্রতিস্থাপন করবেন, আপনাকে অবশ্যই অ্যাক্সেসযোগ্যতার বিবেচনাগুলি মনে রাখতে হবে।

বলুন আপনি আপনার নিজস্ব বাস্তবায়নের সাথে উপাদান Checkbox প্রতিস্থাপন করছেন। আপনি triStateToggleable সংশোধক যোগ করতে ভুলে যেতে পারেন, যা এই উপাদানটির জন্য অ্যাক্সেসযোগ্যতার বৈশিষ্ট্যগুলি পরিচালনা করে।

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

একাধিক অ্যাক্সেসিবিলিটি পরিষেবার সাথে আপনার কাস্টম উপাদান বাস্তবায়ন পরীক্ষা করুন এর আচরণ যাচাই করতে।

অতিরিক্ত সম্পদ