ট্রাভার্সাল অর্ডার নিয়ন্ত্রণ করুন

ডিফল্টরূপে, একটি রচনা অ্যাপে অ্যাক্সেসিবিলিটি স্ক্রিন রিডার আচরণ প্রত্যাশিত পড়ার ক্রম অনুসারে প্রয়োগ করা হয়, যা সাধারণত বাম-থেকে-ডানে, তারপর উপরে-থেকে-নিচে হয়। যাইহোক, কিছু ধরণের অ্যাপ লেআউট রয়েছে যেখানে অ্যালগরিদম অতিরিক্ত ইঙ্গিত ছাড়া প্রকৃত পড়ার ক্রম নির্ধারণ করতে পারে না। ভিউ-ভিত্তিক অ্যাপগুলিতে, আপনি 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
        )
    }
}

কোড নিম্নলিখিত অনুরূপ আউটপুট উত্পাদন করে:

পাঠ্যের দুটি কলামের লেআউট, বাম কলামে 'এই বাক্যটি বাম কলামে' এবং ডান কলামে 'এই বাক্যটি ডানদিকে রয়েছে'।
চিত্র 1. দুটি বাক্য সহ একটি বিন্যাস (একটি বাম কলামে এবং একটি ডান কলামে)।

যেহেতু কোনো শব্দার্থক সেট করা হয়নি, স্ক্রিন রিডারের ডিফল্ট আচরণ হল উপাদানগুলিকে বাম থেকে ডানে এবং উপরে থেকে নীচের দিকে যাওয়া। এই ডিফল্টের কারণে, 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 একসাথে ব্যবহার করতে পারেন।

উদাহরণ: ট্রাভার্স ঘড়ির মুখ

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

একটি ঘড়ির মুখ যার উপরে একটি সময় বাছাইকারী।
চিত্র 2. একটি ঘড়ির মুখের একটি চিত্র।

নিম্নলিখিত সরলীকৃত স্নিপেটে, একটি 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) এর ট্রাভার্সাল অর্ডারিং নিয়ন্ত্রণ করে। এই উদাহরণের ভিত্তি হল নিম্নলিখিত বিন্যাস:

একটি শীর্ষ অ্যাপ বার, নমুনা পাঠ্য, একটি ভাসমান অ্যাকশন বোতাম এবং একটি নীচের অ্যাপ বার সহ একটি লেআউট৷
চিত্র 3. একটি শীর্ষ অ্যাপ বার, নমুনা পাঠ্য, একটি ভাসমান অ্যাকশন বোতাম এবং একটি নীচের অ্যাপ বার সহ লেআউট৷

ডিফল্টরূপে, এই উদাহরণের লেআউটে নিম্নলিখিত 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 → নীচের অ্যাপ বার

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