ট্র্যাভার্সাল অর্ডার পরিবর্তন করা

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

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

স্ক্রিন রিডার ট্র্যাভার্সাল অর্ডার নিয়ন্ত্রণ করতে আপনার অ্যাপে isTraversalGroup এবং traversalIndex ব্যবহার করুন।

ট্রাভার্সালের জন্য গ্রুপ এলিমেন্ট

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

কোডটি নিম্নলিখিত আউটপুটের মতো আউটপুট তৈরি করে:

দুটি কলামে টেক্সট সহ লেআউট, বাঁদিকের কলামে লেখা আছে 'এই
  বাক্যটি বাঁদিকের কলামে আছে' এবং ডানদিকের কলামে লেখা আছে 'এই বাক্যটি ডানদিকের কলামে আছে।'
ছবি ১. দুটি বাক্য সহ একটি লেআউট (একটি বাঁদিকের কলামে এবং একটি ডানদিকের কলামে)।

যেহেতু কোনও শব্দার্থ সেট করা হয়নি, তাই স্ক্রিন রিডারের ডিফল্ট অ্যাকশন হল বাঁ থেকে ডানে এবং উপর থেকে নিচে এলিমেন্টগুলি অতিক্রম করা। এই ডিফল্ট সেটিংসের কারণে, 'টকব্যাক' ফিচার ভুল ক্রমে বাক্যের অংশ পড়ে:

"এই বাক্যটি" → "বাঁদিকের কলামে" → "আছে।" → "ডানদিকে" বিকল্পে ক্লিক করুন।

ফ্র্যাগমেন্টগুলি সঠিকভাবে সাজাতে, আসল স্নিপেটটি পরিবর্তন করে 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 পড়া হয়।

এখন, টকব্যাক সঠিক ক্রমে বাক্যের অংশগুলি পড়ে:

"এই বাক্যটি" → "বাঁদিকের কলামে আছে।" → "এই বাক্যটি" → "ডানদিকে আছে।"

ট্র্যাভার্সাল অর্ডার কাস্টমাইজ করুন

traversalIndex হল একটি ফ্লোট প্রপার্টি যা আপনাকে টকব্যাক ট্র্যাভার্সাল অর্ডার কাস্টমাইজ করতে দেয়। টকব্যাক সঠিকভাবে কাজ করার জন্য এলিমেন্ট একসাথে গ্রুপ করা যথেষ্ট না হলে, স্ক্রিন রিডারের ক্রম আরও কাস্টমাইজ করতে isTraversalGroup-এর সাথে traversalIndex ব্যবহার করুন।

traversalIndex প্রপার্টির নিম্নলিখিত বৈশিষ্ট্য আছে:

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

নিচের উদাহরণ থেকে আপনি জানতে পারবেন যে কীভাবে traversalIndex এবং isTraversalGroup একসাথে ব্যবহার করতে হয়।

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

একটি ক্লক ফেস যার উপরে একটি টাইম পিকার আছে।
ছবি ২. একটি ক্লক ফেসের ছবি।

নিচে দেওয়া সহজ স্নিপেটে, একটি CircularLayout আছে যেখানে ১২টি সংখ্যা আঁকা আছে, ১২ থেকে শুরু করে বৃত্তের চারপাশে ঘড়ির কাঁটার দিকে ঘুরছে:

@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 আরও বড় হয় কারণ স্ক্রিনে সংখ্যা যোগ করা হয়—ক্লক ভ্যালু ০-এর traversalIndex হল ০ এবং ক্লক ভ্যালু ১-এর traversalIndex হল ১। এইভাবে, টকব্যাক যে ক্রমে সেগুলি পড়ে তা সেট করা হয়। এখন, CircularLayout-এর ভেতরে থাকা নম্বরগুলি প্রত্যাশিত ক্রমে পড়া হয়।

যেহেতু সেট করা traversalIndexes শুধুমাত্র একই গ্রুপিংয়ের মধ্যে অন্যান্য ইনডেক্সের সাথে সম্পর্কিত, তাই স্ক্রিনের বাকি অংশের ক্রম সংরক্ষিত করা হয়েছে। অন্যভাবে বলতে গেলে, পূর্ববর্তী কোড স্নিপেটে দেখানো শব্দার্থিক পরিবর্তনগুলি শুধুমাত্র ঘড়ির ফেসের মধ্যে ক্রম পরিবর্তন করে যাতে isTraversalGroup = true সেট করা আছে।

মনে রাখবেন, CircularLayout's সিম্যান্টিক্স isTraversalGroup = true-এ সেট না করলেও, traversalIndex পরিবর্তন এখনও প্রযোজ্য। তবে, CircularLayout ছাড়া, ঘড়ির মুখের বারোটি সংখ্যা শেষে পড়া হয়, স্ক্রিনের অন্যান্য সমস্ত এলিমেন্ট ভিজিট করার পরে। এটি ঘটে কারণ অন্যান্য সব এলিমেন্টের ডিফল্ট traversalIndex হল 0f এবং ঘড়ির টেক্সট এলিমেন্ট অন্যান্য সব 0f এলিমেন্টের পরে পড়া হয়।

API সংক্রান্ত বিবেচনা

ট্রাভার্সাল API ব্যবহার করার সময় নিম্নলিখিত বিষয়গুলি বিবেচনা করুন:

  • গ্রুপ করা এলিমেন্ট আছে এমন পেরেন্ট এলিমেন্টে isTraversalGroup = true সেট করতে হবে।
  • traversalIndex এমন একটি চাইল্ড কম্পোনেন্টে সেট করা উচিত যাতে শব্দার্থবিদ্যা থাকে এবং অ্যাক্সেসিবিলিটি পরিষেবা দ্বারা নির্বাচিত হবে।
  • আপনি যেসব এলিমেন্ট পরীক্ষা করছেন সেগুলি একই zIndex লেভেলে আছে কিনা তা নিশ্চিত করুন, কারণ এটি শব্দার্থবিদ্যা এবং ট্র্যাভার্সাল অর্ডারকেও প্রভাবিত করে।
  • কোনও শব্দার্থ যাতে অপ্রয়োজনীয়ভাবে মার্জ না করা হয় তা নিশ্চিত করুন, কারণ এটি কোন কম্পোনেন্ট ট্রাভার্সাল ইন্ডেক্স প্রয়োগ করা হয়েছে তা প্রভাবিত করতে পারে।