@ScaledMetric একটি SwiftUI property wrapper যা ব্যবহারকারীর Dynamic Type সেটিংস অনুযায়ী স্বয়ংক্রিয়ভাবে একটি সংখ্যামান স্কেল করে। মানটি @ScaledMetric-এ মোড়ানো হয় এবং সিস্টেম ফন্টের আকার পরিবর্তন হলে পুনরায় গণনা করা হয়, যা দৃষ্টি প্রতিবন্ধী ব্যক্তিদের জন্য ইন্টারফেসের অ্যাক্সেসযোগ্যতা নিশ্চিত করে। Apple Developer Documentation (2026) অনুসারে, @ScaledMetric preferred content size category-এর ভিত্তিতে আপেক্ষিক স্কেল গণনা করতে UIFontMetrics স্কেল ব্যবহার করে। অ্যাক্সেসিবিলিটি সম্পর্কে আরও জানতে SwiftUI অ্যাক্সেসিবিলিটি নিবন্ধ দেখুন।
মূল বিষয়
@ScaledMetric একটি SwiftUI property wrapper, যা iOS 14-এ যোগ করা হয়েছে, যা স্বয়ংক্রিয়ভাবে একটি সংখ্যামান (CGFloat, Int, Double) বর্তমান Dynamic Type ফন্টের আকারে স্কেল করে। ফন্টের জন্য .font(.body) এর বিপরীতে, @ScaledMetric যেকোনো সংখ্যামান প্যারামিটার স্কেল করে: padding, spacing, cornerRadius, iconSize — সবকিছু যা বড় টেক্সটের সাথে আনুপাতিকভাবে বাড়া উচিত।
@ScaledMetric-এর মূল উদ্দেশ্য অ-টেক্সট ইন্টারফেস উপাদানের জন্য অ্যাক্সেসিবিলিটি স্কেলিং প্রদান করা। যখন ব্যবহারকারী iOS সেটিংসে ফন্টের আকার বাড়ায়, বাটন, আইকন এবং স্পেসিং ইন্টারফেস ভারসাম্য রাখতে আনুপাতিকভাবে স্কেল হওয়া উচিত। @ScaledMetric ম্যানুয়াল গুণক গণনা ছাড়াই স্বয়ংক্রিয়ভাবে এটি পরিচালনা করে।
মৌলিক সিনট্যাক্স @ScaledMetric একটি ডিফল্ট মান এবং একটি ঐচ্ছিক relativeTo প্যারামিটার ব্যবহার করে। যদি relativeTo নির্দিষ্ট করা হয়, স্কেলিং একটি নির্দিষ্ট টেক্সট স্টাইলের (UIFontTextStyle) সাথে আবদ্ধ হয়। যদি না হয়, .body স্কেল ব্যবহার করা হয়।
struct AccessibleButton: View {
@ScaledMetric private var padding: CGFloat = 12
@ScaledMetric(relativeTo: .title) private var iconSize: CGFloat = 24
var body: some View {
Label("Submit", systemImage: "checkmark.circle.fill")
.font(.body)
.padding(padding)
.imageScale(.init(rawValue: iconSize / 24) ?? .medium)
}
}
padding .body (ডিফল্ট) এর সাপেক্ষে স্কেল হবে, iconSize .title এর সাপেক্ষে। বড় টেক্সটের সাথে, স্পেসিং এবং আইকন আনুপাতিকভাবে স্কেল হবে। @ScaledMetric ছাড়া, padding ফন্টের আকার নির্বিশেষে 12 pt-এ থাকবে, যা ভিজ্যুয়াল অসামঞ্জস্য সৃষ্টি করবে।
@ScaledMetric প্রক্রিয়া UIKit-এর UIFontMetrics-এর উপর ভিত্তি করে। যখন SwiftUI একটি @ScaledMetric ইনস্ট্যান্স তৈরি করে, এটি বর্তমান preferred content size category (UIContentSizeCategory) এর ভিত্তিতে একটি গুণক গণনা করে। বেস মান নির্দিষ্ট টেক্সট স্টাইলের জন্য UIFontMetrics থেকে scaledValue দ্বারা গুণ করা হয়।
গাণিতিকভাবে: ScaledMetricValue = baseValue × UIFontMetrics.scaledValue(for: relativeTo)। যদি relativeTo নির্দিষ্ট না করা হয়, UIFontMetrics.default ব্যবহার করা হয়, যা .body-এর সাথে আবদ্ধ। যখন Dynamic Type পরিবর্তন হয়, SwiftUI View বডি পুনরায় তৈরি করে, @ScaledMetric একটি নতুন scaledValue গণনা করে, এবং UI @State-সদৃশ PropertyWrappers প্রক্রিয়ার মাধ্যমে স্বয়ংক্রিয়ভাবে আপডেট হয়।
iOS মাপনী 11টি আকার অন্তর্ভুক্ত করে: .extraSmall (5 pt) থেকে .accessibilityExtraExtraExtraLarge (77 pt for .body) পর্যন্ত। .body-এর জন্য স্কেলিং ফ্যাক্টর বেস মানের সাপেক্ষে 0.85 (XS) থেকে 1.71 (XXXL) পর্যন্ত হয়। @ScaledMetric ঠিক এই মাপনী ব্যবহার করে, তাই 12 pt-এর padding মান সর্বোচ্চ অ্যাক্সেসিবিলিটি আকারে ~20 pt হতে পারে।
| কন্টেন্ট সাইজ ক্যাটাগরি | ফ্যাক্টর (body) | উদাহরণ @ScaledMetric(12) |
|---|---|---|
| extraSmall | 0.85 | ~10 pt |
| small | 0.93 | ~11 pt |
| medium (default) | 1.00 | 12 pt |
| large | 1.07 | ~13 pt |
| extraLarge | 1.15 | ~14 pt |
| extraExtraLarge | 1.28 | ~15 pt |
| accessibilityExtraLarge | 1.47 | ~18 pt |
| accessibilityXXXL | 1.71 | ~20 pt |
relativeTo নির্বাচন: বডি টেক্সট সম্পর্কিত মানের (padding, spacing in lists) জন্য .body ব্যবহার করুন, বড় উপাদানের (iconSize, imageSize) জন্য .title, ছোট উপাদানের (badge size) জন্য .caption। এটি নিশ্চিত করে যে উপাদানগুলি আশেপাশের টেক্সটের সাথে সামঞ্জস্য রেখে স্কেল হয়।
Dynamic Type একটি iOS বৈশিষ্ট্য যা ব্যবহারকারীদের সেটিংস → ডিসপ্লে ও ব্রাইটনেস → টেক্সট সাইজ-এ সিস্টেম ফন্টের আকার সামঞ্জস্য করতে দেয়। পরিবর্তনটি সকল অ্যাপে বৈশ্বিকভাবে প্রযোজ্য হয়। @ScaledMetric এই পরিবর্তনে স্বয়ংক্রিয়ভাবে সাড়া দেয়: SwiftUI UIContentSizeCategory পরিবর্তন হলে সমস্ত @ScaledMetric ভেরিয়েবল আপডেট করে।
গুরুত্বপূর্ণ: @ScaledMetric শুধুমাত্র সংখ্যামান স্কেল করে, এটি সরাসরি ফন্ট পরিচালনা করে না। ফন্টের জন্য, একটি টেক্সট স্টাইল (.body, .title, .headline) সহ .font() ব্যবহার করুন — SwiftUI স্বয়ংক্রিয়ভাবে ফন্ট স্কেল করে। @ScaledMetric padding, spacing এবং উপাদানের আকারের জন্য ফন্ট স্কেলিং পরিপূরক করে।
Canvas Preview Dynamic Type সমর্থন করে: Canvas টুলবারে বিভিন্ন ফন্টের আকারে UI পরীক্ষা করার জন্য একটি টেক্সট সাইজ স্লাইডার (A–A) আছে। স্পেসিং এবং আকার সঠিকভাবে স্কেল হচ্ছে কিনা তা নিশ্চিত করতে @ScaledMetric-এর সাথে এটি ব্যবহার করুন।
struct CardView: View {
@ScaledMetric private var cornerRadius: CGFloat = 16
@ScaledMetric private var spacing: CGFloat = 8
var body: some View {
VStack(spacing: spacing) {
Text("Card Title")
.font(.headline)
Text("Description with dynamic type support")
.font(.body)
}
.padding(spacing * 2)
.background(.regularMaterial)
.cornerRadius(cornerRadius)
}
}
struct CardView_Previews: PreviewProvider {
static var previews: some View {
CardView()
.dynamicTypeSize(.large)
.previewDisplayName("Large")
CardView()
.dynamicTypeSize(.accessibility5)
.previewDisplayName("Accessibility 5")
}
}
cornerRadius সর্বোচ্চ অ্যাক্সেসিবিলিটি আকারে 16 pt থেকে ~27 pt পর্যন্ত স্কেল হয়। spacing — 8 থেকে ~14 pt পর্যন্ত। এটি নিশ্চিত করে যে কার্ড যেকোনো ফন্টের আকারে দৃশ্যমানভাবে ভারসাম্যপূর্ণ থাকে।
উদাহরণ: Dynamic Type সমর্থিত আইকন. Image(systemName:) আইকনের আকার ডিফল্টভাবে Dynamic Type অনুযায়ী স্কেল হয় না। @ScaledMetric বর্তমান স্কেল ফ্যাক্টরের ভিত্তিতে imageScale বা ফ্রেমের আকার পরিবর্তন করে এই সমস্যার সমাধান করে।
struct IconLabel: View {
let title: String
let icon: String
@ScaledMetric private var iconDimension: CGFloat = 28
@ScaledMetric(relativeTo: .body) private var spacing: CGFloat = 6
var body: some View {
HStack(spacing: spacing) {
Image(systemName: icon)
.resizable()
.frame(width: iconDimension, height: iconDimension)
Text(title)
.font(.body)
}
}
}
উদাহরণ: অ্যাক্সেসযোগ্য ব্যাজ উপাদান. একটি সংখ্যাযুক্ত ব্যাজ টেক্সটের অনুপাতে স্কেল হওয়া উচিত। ন্যূনতম ব্যাজ আকারের জন্য @ScaledMetric নিশ্চিত করে যে বৃত্তাকার ব্যাজ বড় টেক্সটের সাথে দৃশ্যমান থাকে।
struct BadgeView: View {
let count: Int
@ScaledMetric(relativeTo: .caption) private var badgeSize: CGFloat = 20
@ScaledMetric(relativeTo: .caption) private var fontScale: CGFloat = 1
var body: some View {
ZStack {
Circle()
.fill(.red)
.frame(width: badgeSize, height: badgeSize)
Text("\(count)")
.font(.caption)
.foregroundColor(.white)
.scaleEffect(fontScale)
}
.fixedSize()
}
}
fontScale বর্ধিত badgeSize-এর সাথে মেলাতে Circle কন্টেন্ট অতিরিক্তভাবে স্কেল করে। fontScale ছাড়া, ব্যাজের ভিতরের টেক্সট বড় টেক্সটের সাথে ফিট নাও হতে পারে।
@ScaledMetric এবং @State উভয়ই property wrappers যা পরিবর্তন ট্র্যাক করে, কিন্তু ভিন্ন আপডেট উৎস সহ। @State প্রোগ্রাম্যাটিক পরিবর্তনে ($stateBinding-এর মাধ্যমে) মান আপডেট করে। @ScaledMetric সিস্টেম Dynamic Type পরিবর্তন হলে স্বয়ংক্রিয়ভাবে মান আপডেট করে, কিন্তু কোড থেকে সরাসরি মান পরিবর্তন করার অনুমতি দেয় না।
মূল পার্থক্য: @ScaledMetric ডেভেলপারের জন্য শুধুমাত্র-পঠনযোগ্য এবং সিস্টেমের জন্য শুধুমাত্র-লিখনযোগ্য। আপনি setter-এর মাধ্যমে scaledValue পরিবর্তন করতে পারেন না — এটি SwiftUI দ্বারা বেস মান এবং বর্তমান Dynamic Type-এর ভিত্তিতে গণনা করা হয়। @State, অন্যদিকে, সম্পূর্ণরূপে ডেভেলপার-নিয়ন্ত্রিত। যদি আপনার একটি মানের প্রয়োজন যা Dynamic Type অনুযায়ী স্কেল হয় এবং প্রোগ্রাম্যাটিকভাবে পরিবর্তনও হয় — @ScaledMetric-কে @State-এর সাথে একত্রিত করুন অথবা একটি গণনাকৃত প্রপার্টি ব্যবহার করুন।
| বৈশিষ্ট্য | @ScaledMetric | @State |
|---|---|---|
| আপডেট উৎস | Dynamic Type (সিস্টেম) | প্রোগ্রাম্যাটিক (ডেভেলপার) |
| মানের ধরন | CGFloat, Int, Double | যেকোনো |
| কোড থেকে পরিবর্তন | অনুমোদিত নয় | binding-এর মাধ্যমে অনুমোদিত |
| View পুনরাঙ্কন | Dynamic Type পরিবর্তনে | মান পরিবর্তনে |
| iOS সংস্করণ | iOS 14+ | iOS 13+ |
সংযুক্ত প্যাটার্ন: যদি আপনার Dynamic Type অনুযায়ী স্কেলিং করার সময় প্রোগ্রাম্যাটিকভাবে padding পরিবর্তন করার প্রয়োজন হয় (যেমন, ট্যাপ অ্যানিমেশন), বেস স্কেল করা মানের জন্য @ScaledMetric এবং অ্যানিমেশন গুণকের জন্য @State তৈরি করুন। চূড়ান্ত মান = scaledValue × animationMultiplier।
ভুল 1: ফন্টের জন্য @ScaledMetric ব্যবহার করা। @ScaledMetric সংখ্যা স্কেল করে, ফন্ট নয়। ফন্টের জন্য, .font(.body) ব্যবহার করুন — SwiftUI স্বয়ংক্রিয়ভাবে Dynamic Type প্রয়োগ করে। @ScaledMetric কখনও font(.system(size: scaledSize))-এর সাথে ব্যবহার করবেন না — এটি সিস্টেম অ্যাক্সেসিবিলিটি ভঙ্গ করে।
ভুল 2: ভিন্নধর্মী উপাদানের জন্য relativeTo-এর অভাব। যদি আপনার কাছে padding (.body-এর সাথে আবদ্ধ) এবং iconSize (.title-এর সাথে আবদ্ধ) থাকে, প্রতিটির জন্য সঠিক relativeTo নির্দিষ্ট করুন। relativeTo ছাড়া, উভয়ই .body দ্বারা স্কেল হবে, যার ফলে এর টেক্সট প্রসঙ্গের সাপেক্ষে আইকনের অসামঞ্জস্যপূর্ণ স্কেলিং হবে।
ভুল 3: ViewModel/@ObservableObject-এ @ScaledMetric। @ScaledMetric একটি SwiftUI property wrapper যা শুধুমাত্র View-এর ভিতরে কাজ করে। এটি ViewModels বা সার্ভিসে ব্যবহার করা যাবে না। ViewModel-এ স্কেলিংয়ের জন্য, View থেকে স্কেল করা মান প্যারামিটার হিসেবে পাস করুন অথবা View-তে @Environment(\.sizeCategory) ব্যবহার করুন।
@Environment(\.sizeCategory) View-তে বর্তমান Dynamic Type পাওয়ার একটি বিকল্প উপায়। এটি ব্যবহার করুন যখন আপনার আরও নিয়ন্ত্রণের প্রয়োজন হয়: একটি কাস্টম গুণক গণনা করা, ViewModel-এ sizeCategory পাস করা, অথবা নমনীয় স্কেলিংয়ের জন্য @ScaledMetric-এর সাথে একত্রিত করা।
struct CustomScaledView: View {
@Environment(\.sizeCategory) private var sizeCategory
@ScaledMetric private var basePadding: CGFloat = 12
private var extraPadding: CGFloat {
if sizeCategory >= .accessibilityLarge {
return basePadding * 0.5
}
return 0
}
var body: some View {
Text("Custom scaled content")
.font(.body)
.padding(basePadding + extraPadding)
}
}
অতিরিক্ত padding extraPadding শুধুমাত্র অ্যাক্সেসিবিলিটি আকারে যোগ করা হয়, যা বেস @ScaledMetric লজিক পরিবর্তন না করেই বড় টেক্সটের জন্য আরও জায়গা দেয়।
সচরাচর জিজ্ঞাসিত প্রশ্ন
@ScaledMetric সংখ্যা স্কেল করার জন্য একটি অফিসিয়াল SwiftUI property wrapper। @ScaledFont একটি স্ট্যান্ডার্ড API হিসেবে বিদ্যমান নেই — এটি কমিউনিটি দ্বারা বাস্তবায়িত একটি কাস্টম wrapper। ফন্টের জন্য, সর্বদা টেক্সট স্টাইল (.body, .title) সহ বিল্ট-ইন .font() ব্যবহার করুন, এবং padding, spacing এবং আকারের জন্য @ScaledMetric ব্যবহার করুন।
@ScaledMetric iOS 14+, watchOS 7+, tvOS 14+ এবং macOS 11+-এ উপলব্ধ। watchOS-এ, Dynamic Type একটি ছোট পরিসরে সীমাবদ্ধ — অ্যাক্সেসিবিলিটি আকার ছাড়া .extraSmall থেকে .extraLarge পর্যন্ত আকার উপলব্ধ। tvOS-এ, Dynamic Type উপলব্ধ নয় — @ScaledMetric সর্বদা বেস মান ফেরত দেয়।
হ্যাঁ, @ScaledMetric পরীক্ষা করার জন্য @ScaledMetric সহ একটি View তৈরি করুন এবং .environment(\.sizeCategory, .extraExtraLarge)-এর মাধ্যমে এনভায়রনমেন্ট .sizeCategory মান পাস করুন। তারপর GeometryReader বা SwiftUI Inspector-এর মাধ্যমে উপাদানের আকার পান। বিকল্পভাবে, একটি পৃথক মডিউলে UIFontMetrics-এর মাধ্যমে স্কেলিং লজিক পরীক্ষা করুন।
.dynamicTypeSize একটি View মডিফায়ার যা একটি হায়ারার্কির জন্য সর্বোচ্চ Dynamic Type সীমিত করে (যেমন, .dynamicTypeSize(...large))। @ScaledMetric এই সীমা সম্মান করে: যদি .dynamicTypeSize সেট করা থাকে, স্কেল করা মান সংশ্লিষ্ট আকার অতিক্রম করবে না। সঠিক নিয়ন্ত্রণের জন্য উভয় API একত্রিত করুন।
নিশ্চিত করুন যে View অভ্যন্তরীণভাবে @ScaledMetric ব্যবহার করে (ViewModel-এ নয়)। পরীক্ষা করুন যে View Dynamic Type-এ সাবস্ক্রাইব করে: @ScaledMetric স্বয়ংক্রিয়ভাবে body রিফ্রেশ ট্রিগার করে, কিন্তু যদি View .equatable() বা .id() ব্যবহার করে, প্রক্রিয়াটি ভেঙে যেতে পারে। ফলব্যাক হিসেবে @Environment(\.sizeCategory) ব্যবহার করুন।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন