ডিফল্টরূপে, একটি রচনা অ্যাপে অ্যাক্সেসিবিলিটি স্ক্রিন রিডার আচরণ প্রত্যাশিত পড়ার ক্রম অনুসারে প্রয়োগ করা হয়, যা সাধারণত বাম-থেকে-ডানে, তারপর উপরে-থেকে-নিচে হয়। যাইহোক, কিছু ধরণের অ্যাপ লেআউট রয়েছে যেখানে অ্যালগরিদম অতিরিক্ত ইঙ্গিত ছাড়া প্রকৃত পড়ার ক্রম নির্ধারণ করতে পারে না। ভিউ-ভিত্তিক অ্যাপগুলিতে, আপনি traversalBefore
এবং traversalAfter
বৈশিষ্ট্যগুলি ব্যবহার করে এই জাতীয় সমস্যাগুলি সমাধান করতে পারেন। রচনা 1.5 থেকে শুরু করে, রচনা একটি সমান নমনীয় API প্রদান করে, কিন্তু একটি নতুন ধারণাগত মডেল সহ।
isTraversalGroup
এবং traversalIndex
হল শব্দার্থগত বৈশিষ্ট্য যা আপনাকে এমন পরিস্থিতিতে অ্যাক্সেসযোগ্যতা এবং TalkBack ফোকাস ক্রম নিয়ন্ত্রণ করতে দেয় যেখানে ডিফল্ট সাজানোর অ্যালগরিদম উপযুক্ত নয়। isTraversalGroup
শব্দার্থগতভাবে গুরুত্বপূর্ণ গোষ্ঠীগুলিকে চিহ্নিত করে, যখন traversalIndex
সেই গোষ্ঠীগুলির মধ্যে পৃথক উপাদানগুলির ক্রম সামঞ্জস্য করে। আপনি একা isTraversalGroup
ব্যবহার করতে পারেন, বা আরও কাস্টমাইজেশনের জন্য traversalIndex
এর সাথে।
স্ক্রিন রিডার ট্রাভার্সাল অর্ডার নিয়ন্ত্রণ করতে আপনার অ্যাপে isTraversalGroup
এবং traversalIndex
ব্যবহার করুন।
isTraversalGroup
এর সাথে গ্রুপ উপাদান
isTraversalGroup
হল একটি বুলিয়ান সম্পত্তি যা একটি শব্দার্থবিদ্যা নোড একটি ট্রাভার্সাল গ্রুপ কিনা তা নির্ধারণ করে। এই ধরনের নোড হল একটি যার কাজ হল নোডের বাচ্চাদের সংগঠিত করার জন্য একটি সীমানা বা সীমানা হিসাবে কাজ করা।
একটি নোডে isTraversalGroup = true
সেট করার অর্থ হল যে নোডের সমস্ত শিশু অন্যান্য উপাদানে যাওয়ার আগে পরিদর্শন করা হয়। আপনি নন-স্ক্রিন রিডার ফোকাসযোগ্য নোড, যেমন কলাম, সারি বা বাক্সে isTraversalGroup
সেট করতে পারেন।
নিম্নলিখিত উদাহরণ isTraversalGroup
ব্যবহার করে। এটি চারটি পাঠ্য উপাদান নির্গত করে। বাম দুটি উপাদান একটি CardBox
উপাদানের অন্তর্গত, যখন ডান দুটি উপাদান অন্য একটি CardBox
উপাদানের অন্তর্গত:
// CardBox() function takes in top and bottom sample text. @Composable fun CardBox( topSampleText: String, bottomSampleText: String, modifier: Modifier = Modifier ) { Box(modifier) { Column { Text(topSampleText) Text(bottomSampleText) } } } @Composable fun TraversalGroupDemo() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is " val bottomSampleText2 = "on the right." Row { CardBox( topSampleText1, bottomSampleText1 ) CardBox( topSampleText2, bottomSampleText2 ) } }
কোড নিম্নলিখিত অনুরূপ আউটপুট উত্পাদন করে:
![পাঠ্যের দুটি কলামের লেআউট, বাম কলামে 'এই বাক্যটি বাম কলামে' এবং ডান কলামে 'এই বাক্যটি ডানদিকে রয়েছে'।](https://developer.android.com/static/develop/ui/compose/images/a11y-istraversalgroup-example.png?authuser=1&hl=bn)
যেহেতু কোনো শব্দার্থক সেট করা হয়নি, স্ক্রিন রিডারের ডিফল্ট আচরণ হল উপাদানগুলিকে বাম থেকে ডানে এবং উপরে থেকে নীচের দিকে যাওয়া। এই ডিফল্টের কারণে, TalkBack বাক্যাংশগুলিকে ভুল ক্রমে পড়ে:
"এই বাক্যটি আছে" → "এই বাক্যটি" → "বাম কলাম।" → "ডান দিকে।"
সঠিকভাবে খন্ডগুলি অর্ডার করতে, isTraversalGroup
true
করতে আসল স্নিপেটটি পরিবর্তন করুন:
@Composable fun TraversalGroupDemo2() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is" val bottomSampleText2 = "on the right." Row { CardBox( // 1, topSampleText1, bottomSampleText1, Modifier.semantics { isTraversalGroup = true } ) CardBox( // 2, topSampleText2, bottomSampleText2, Modifier.semantics { isTraversalGroup = true } ) } }
যেহেতু isTraversalGroup
প্রতিটি CardBox
এ বিশেষভাবে সেট করা আছে, তাই তাদের উপাদানগুলিকে সাজানোর সময় CardBox
সীমানা প্রযোজ্য। এই ক্ষেত্রে, বাম CardBox
প্রথমে পড়া হয়, তারপরে ডান CardBox
পড়ে।
এখন, TalkBack সঠিক ক্রমানুসারে বাক্যাংশগুলো পড়ে:
"এই বাক্যটি আছে" → "বাম কলামে।" → "এই বাক্যটি" → "ডানদিকে।"
আরও কাস্টমাইজ ট্রাভার্সাল অর্ডার
traversalIndex
হল একটি ফ্লোট প্রপার্টি যা আপনাকে TalkBack ট্রাভার্সাল অর্ডার কাস্টমাইজ করতে দেয়। টকব্যাকের সঠিকভাবে কাজ করার জন্য উপাদানগুলিকে একসাথে গোষ্ঠীবদ্ধ করা যথেষ্ট না হলে, স্ক্রিন রিডার অর্ডারিংকে আরও কাস্টমাইজ করতে isTraversalGroup
এর সাথে traversalIndex
ব্যবহার করুন।
traversalIndex
সম্পত্তির নিম্নলিখিত বৈশিষ্ট্য রয়েছে:
- নিম্ন
traversalIndex
মান সহ উপাদানগুলিকে প্রথমে অগ্রাধিকার দেওয়া হয়। - ইতিবাচক বা নেতিবাচক হতে পারে।
- ডিফল্ট মান হল
0f
। - শুধুমাত্র স্ক্রিন রিডার-ফোকাসেবল নোডগুলিকে প্রভাবিত করে, যেমন টেক্সট বা বোতামের মতো অন-স্ক্রীন উপাদানগুলি। উদাহরণস্বরূপ, একটি কলামে শুধুমাত্র
traversalIndex
সেট করা কোন প্রভাব ফেলবে না, যদি না কলামটিতেisTraversalGroup
সেট করা থাকে।
নিম্নলিখিত উদাহরণ দেখায় কিভাবে আপনি traversalIndex
এবং isTraversalGroup
একসাথে ব্যবহার করতে পারেন।
উদাহরণ: ট্রাভার্স ঘড়ির মুখ
একটি ঘড়ির মুখ একটি সাধারণ দৃশ্য যেখানে স্ট্যান্ডার্ড ট্রাভার্সাল অর্ডারিং কাজ করে না। এই বিভাগে উদাহরণ হল একটি সময় বাছাইকারী, যেখানে একজন ব্যবহারকারী ঘড়ির মুখে সংখ্যার মধ্য দিয়ে যেতে পারে এবং ঘন্টা এবং মিনিটের স্লটের জন্য সংখ্যা নির্বাচন করতে পারে।
![একটি ঘড়ির মুখ যার উপরে একটি সময় বাছাইকারী।](https://developer.android.com/static/develop/ui/compose/images/a11y-clock-face.png?authuser=1&hl=bn)
নিম্নলিখিত সরলীকৃত স্নিপেটে, একটি CircularLayout
রয়েছে যেখানে 12টি সংখ্যা আঁকা হয়েছে, 12 দিয়ে শুরু হচ্ছে এবং বৃত্তের চারপাশে ঘড়ির কাঁটার দিকে ঘুরছে:
@Composable fun ClockFaceDemo() { CircularLayout { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier) { Text((if (value == 0) 12 else value).toString()) } }
যেহেতু ঘড়ির মুখটি ডিফল্ট বাম-থেকে-ডান এবং উপরে-থেকে-নীচের ক্রমানুসারে যৌক্তিকভাবে পড়া হয় না, টকব্যাক নম্বরগুলিকে ক্রমছাড়া করে। এটি সংশোধন করতে, নিম্নলিখিত স্নিপেটে দেখানো হিসাবে বর্ধিত কাউন্টার মান ব্যবহার করুন:
@Composable fun ClockFaceDemo() { CircularLayout(Modifier.semantics { isTraversalGroup = true }) { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier.semantics { this.traversalIndex = value.toFloat() }) { Text((if (value == 0) 12 else value).toString()) } }
সঠিকভাবে ট্রাভার্সাল অর্ডার সেট করতে, প্রথমে CircularLayout
একটি ট্রাভার্সাল গ্রুপ করুন এবং isTraversalGroup = true
সেট করুন। তারপরে, প্রতিটি ঘড়ির পাঠ্য লেআউটের উপর আঁকা হয়েছে, তার সংশ্লিষ্ট traversalIndex
কাউন্টার ভ্যালুতে সেট করুন।
কারণ কাউন্টার ভ্যালু ক্রমাগত বাড়তে থাকে, প্রতিটি ঘড়ির মানের traversalIndex
স্ক্রীনে সংখ্যা যোগ করার সাথে সাথে বড় হয়—ঘড়ির মান 0-এর একটি traversalIndex
0 এবং ঘড়ির মান 1-এর একটি traversalIndex
রয়েছে 1। এইভাবে, টকব্যাকের ক্রম তাদের পড়া সেট করা হয়. এখন, CircularLayout
ভিতরের সংখ্যাগুলি প্রত্যাশিত ক্রমে পড়া হয়।
কারণ যে traversalIndexes
সেট করা হয়েছে তা শুধুমাত্র একই গ্রুপিংয়ের মধ্যে থাকা অন্যান্য সূচকগুলির সাথে আপেক্ষিক, বাকি স্ক্রীন অর্ডার সংরক্ষণ করা হয়েছে। অন্য কথায়, পূর্ববর্তী কোড স্নিপেটে দেখানো শব্দার্থিক পরিবর্তনগুলি শুধুমাত্র ঘড়ির মুখের মধ্যে ক্রম পরিবর্তন করে যাতে isTraversalGroup = true
সেট আছে।
উল্লেখ্য যে, CircularLayout's
শব্দার্থকে isTraversalGroup = true
এ সেট না করেও, traversalIndex
পরিবর্তনগুলি এখনও প্রযোজ্য। যাইহোক, তাদের আবদ্ধ করার জন্য CircularLayout
ছাড়াই, পর্দার অন্যান্য সমস্ত উপাদান পরিদর্শন করার পরে ঘড়ির মুখের বারোটি সংখ্যা শেষ পড়া হয়। এটি ঘটে কারণ অন্যান্য সমস্ত উপাদানের 0f
এর একটি ডিফল্ট traversalIndex
থাকে এবং ঘড়ির পাঠ্য উপাদানগুলি অন্যান্য সমস্ত 0f
উপাদানের পরে পড়া হয়।
উদাহরণ: ভাসমান অ্যাকশন বোতামের জন্য ট্রাভার্সাল অর্ডার কাস্টমাইজ করুন
এই উদাহরণে, traversalIndex
এবং isTraversalGroup
ম্যাটেরিয়াল ডিজাইন ফ্লোটিং অ্যাকশন বাটন (FAB) এর ট্রাভার্সাল অর্ডারিং নিয়ন্ত্রণ করে। এই উদাহরণের ভিত্তি হল নিম্নলিখিত বিন্যাস:
![একটি শীর্ষ অ্যাপ বার, নমুনা পাঠ্য, একটি ভাসমান অ্যাকশন বোতাম এবং একটি নীচের অ্যাপ বার সহ একটি লেআউট৷](https://developer.android.com/static/develop/ui/compose/images/a11y-fab-example.png?authuser=1&hl=bn)
ডিফল্টরূপে, এই উদাহরণের লেআউটে নিম্নলিখিত TalkBack ক্রম রয়েছে:
শীর্ষ অ্যাপ বার → নমুনা পাঠ্য 0 থেকে 6 → ফ্লোটিং অ্যাকশন বোতাম (এফএবি) → নীচের অ্যাপ বার
আপনি স্ক্রিন রিডার প্রথমে FAB-এ ফোকাস করতে চাইতে পারেন। একটি FAB এর মতো একটি উপাদান উপাদানে একটি traversalIndex
সেট করতে, নিম্নলিখিতগুলি করুন:
@Composable fun FloatingBox() { Box(modifier = Modifier.semantics { isTraversalGroup = true; traversalIndex = -1f }) { FloatingActionButton(onClick = {}) { Icon(imageVector = Icons.Default.Add, contentDescription = "fab icon") } } }
এই স্নিপেটে, isTraversalGroup
সাথে একটি বক্স তৈরি করা true
সেট করা এবং একই বক্সে একটি traversalIndex
সেট করা ( -1f
0f
এর ডিফল্ট মানের থেকে কম) মানে হল যে ফ্লোটিং বক্সটি অন্যান্য সমস্ত অন-স্ক্রীন উপাদানের আগে আসে৷
এর পরে, আপনি ভাসমান বাক্স এবং অন্যান্য উপাদানগুলিকে একটি স্ক্যাফোল্ডে রাখতে পারেন, যা একটি মেটেরিয়াল ডিজাইন লেআউট প্রয়োগ করে:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun ColumnWithFABFirstDemo() { Scaffold( topBar = { TopAppBar(title = { Text("Top App Bar") }) }, floatingActionButtonPosition = FabPosition.End, floatingActionButton = { FloatingBox() }, content = { padding -> ContentColumn(padding = padding) }, bottomBar = { BottomAppBar { Text("Bottom App Bar") } } ) }
TalkBack নিম্নলিখিত ক্রমে উপাদানগুলির সাথে ইন্টারঅ্যাক্ট করে:
FAB → শীর্ষ অ্যাপ বার → নমুনা পাঠ্য 0 থেকে 6 → নীচের অ্যাপ বার
অতিরিক্ত সম্পদ
- অ্যাক্সেসযোগ্যতা : সমস্ত অ্যান্ড্রয়েড অ্যাপ ডেভেলপমেন্টের জন্য সাধারণ প্রয়োজনীয় ধারণা এবং কৌশল
- অ্যাক্সেসযোগ্য অ্যাপস তৈরি করুন : আপনার অ্যাপকে আরও অ্যাক্সেসযোগ্য করতে আপনি কী পদক্ষেপ নিতে পারেন
- অ্যাপ অ্যাক্সেসযোগ্যতা উন্নত করার নীতিগুলি : আপনার অ্যাপটিকে আরও অ্যাক্সেসযোগ্য করার জন্য কাজ করার সময় মনে রাখতে হবে মূল নীতিগুলি
- অ্যাক্সেসিবিলিটির জন্য টেস্টিং : অ্যান্ড্রয়েড অ্যাকসেসিবিলিটির জন্য পরীক্ষা নীতি এবং টুল