পাঠ ০৯ · ৫৭-এর মধ্যে · মডিউল ২
Home / Courses / Mobile App Development / ডার্ক মোড ও থিমিং

ডার্ক মোড ও থিমিং

Dark mode and theming
৮ মিনিট পড়া শুরু · Beginner Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • ডার্ক মোড কেন সরাসরি রঙ হার্ডকোড না করে টোকেন-ভিত্তিক পদ্ধতিতে বাস্তবায়ন করা হয়
  • থিম ডিকশনারি ও resolve_color() ফাংশনের ভূমিকা
  • একই UI বর্ণনা কীভাবে ভিন্ন থিমে ভিন্ন প্রকৃত রঙে "রেন্ডার" হয় — genuinely প্রমাণিত
  • থিমিংয়ের সাথে L08-এর কালার কনট্রাস্ট বিবেচনার সম্পর্ক

১ · কেন সরাসরি রঙ হার্ডকোড করা যায় না

একটি সহজ কিন্তু ভুল উপায় হলো প্রতিটি UI কম্পোনেন্টে সরাসরি একটি রঙ কোড লিখে দেওয়া (যেমন text_color = "#1A1A1A")। সমস্যা হলো — ব্যবহারকারী ডার্ক মোডে গেলে এই একই কম্পোনেন্টের রঙ বদলাতে হবে, কিন্তু কোডটি জানেই না কোন মোড সক্রিয়। সঠিক সমাধান হলো কম্পোনেন্টকে একটি প্রকৃত রঙের বদলে একটি টোকেন-নাম (যেমন "text_primary") দিয়ে দেওয়া, এবং প্রকৃত রঙ নির্ধারণ করার দায়িত্ব একটি পৃথক "থিম রেজলভার"-এর হাতে রাখা।

টোকেন: "background" লাইট থিম background = #FFFFFF ডার্ক থিম background = #121212
একই টোকেন-নাম ("background"), কিন্তু সক্রিয় থিম ডিকশনারি অনুযায়ী resolve_color() ভিন্ন প্রকৃত রঙ ফেরত দেয়।

২ · থিম, টোকেন, ও resolve_color() — একটি সত্যিকারের সিমুলেশন

নিচের কোড সেলে দুটি থিম ডিকশনারি (light_theme, dark_theme) সংজ্ঞায়িত করা হয়েছে, প্রতিটিতে একই টোকেন-নাম কিন্তু ভিন্ন প্রকৃত রঙ। ui_elements লিস্টটি শুধু টোকেন-নাম রেফারেন্স করে, সরাসরি রঙ নয়। render_ui() ফাংশনটি একই ui_elements লিস্ট দুইবার (একবার প্রতিটি থিম দিয়ে) রেন্ডার করে, প্রমাণ করে যে UI বর্ণনা অপরিবর্তিত থেকেও ফলাফলের রঙ genuinely ভিন্ন হয়।

Python
# থিম ডিকশনারি, resolve_color(), এবং একই UI বর্ণনা দুই থিমে রেন্ডার -- genuinely ভিন্ন রঙ

light_theme = {
    "background": "#FFFFFF",
    "surface": "#F5F5F5",
    "text_primary": "#1A1A1A",
    "text_secondary": "#5F5F5F",
    "accent": "#2563EB",
}

dark_theme = {
    "background": "#121212",
    "surface": "#1E1E1E",
    "text_primary": "#EDEDED",
    "text_secondary": "#B0B0B0",
    "accent": "#60A5FA",
}

def resolve_color(token, theme):
    if token not in theme:
        raise KeyError(f"অজানা কালার টোকেন: {token}")
    return theme[token]

# UI বর্ণনা -- শুধু টোকেন-নাম রেফারেন্স করে, সরাসরি রঙ নয়
ui_elements = [
    {"name": "স্ক্রিন ব্যাকগ্রাউন্ড", "token": "background"},
    {"name": "কার্ড", "token": "surface"},
    {"name": "মূল টাইটেল টেক্সট", "token": "text_primary"},
    {"name": "সাবটাইটেল টেক্সট", "token": "text_secondary"},
    {"name": "বাটন", "token": "accent"},
]

def render_ui(elements, theme, theme_name):
    print(f"-- {theme_name} থিম --")
    for el in elements:
        color = resolve_color(el["token"], theme)
        print(f"{el['name']:20s} (token={el['token']:14s}) -> {color}")

render_ui(ui_elements, light_theme, "লাইট")
print()
render_ui(ui_elements, dark_theme, "ডার্ক")

# একই টোকেন, ভিন্ন থিম -- genuinely যাচাই করা
bg_light = resolve_color("background", light_theme)
bg_dark = resolve_color("background", dark_theme)
print(f"\n'background' টোকেন লাইটে: {bg_light}, ডার্কে: {bg_dark}")
print(f"একই UI বর্ণনা, ভিন্ন থিমে ভিন্ন প্রকৃত রঙ? {bg_light != bg_dark}")

    
লক্ষ্য করুন ui_elements লিস্টটি একবারই সংজ্ঞায়িত হয়েছে এবং render_ui()-কে দুইবার কল করার সময় এটি অপরিবর্তিত থাকে — শুধু দ্বিতীয় আর্গুমেন্ট (theme) বদলেছে। এটিই টোকেন-ভিত্তিক থিমিংয়ের মূল সুবিধা: UI বর্ণনা কোডে একবার লেখা হয়, কিন্তু রেন্ডার করা প্রকৃত রঙ সম্পূর্ণভাবে নির্ভর করে কোন থিম ডিকশনারি পাস করা হয়েছে তার উপর।
মূল কথা · Key takeaway

ডার্ক মোড কোনো "রঙ উল্টে দেওয়া" ম্যাজিক নয় — এটি একটি ডিজাইন-প্যাটার্ন সিদ্ধান্ত: UI কোড কখনো সরাসরি রঙ জানে না, শুধু টোকেন-নাম জানে, আর একটি রেজলভার ফাংশন runtime-এ প্রকৃত রঙ নির্ধারণ করে। L08-এর কনট্রাস্ট ক্যালকুলেটর প্রতিটি থিমের text_primary/background জোড়ার উপর আলাদাভাবে চালানো উচিত — একটি থিমে কনট্রাস্ট ঠিক থাকলেই আরেকটি থিমে ঠিক থাকবে, এমন নিশ্চয়তা নেই।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ যদি একজন ডেভেলপার resolve_color() এড়িয়ে সরাসরি "#FFFFFF" একটি কম্পোনেন্টে হার্ডকোড করে দেন, ডার্ক মোডে কী হবে?

সেই একটি কম্পোনেন্ট ডার্ক মোডেও সাদাই থেকে যাবে, যদিও বাকি সব কম্পোনেন্ট থিম পরিবর্তনের সাথে সঠিকভাবে বদলায়। ব্যবহারিক ফলাফল — ডার্ক মোডে একটি অস্বাভাবিক উজ্জ্বল সাদা "প্যাচ" দেখা যাবে, এবং যদি এর উপর টেক্সট text_primary (ডার্ক মোডে হালকা রঙ) ব্যবহার করে, কনট্রাস্ট সম্পূর্ণ ভেঙে যেতে পারে (হালকা টেক্সট হালকা ব্যাকগ্রাউন্ডে)। এই কারণেই হার্ডকোড করা রঙ থিমিং সিস্টেমে একটি সাধারণ বাগের উৎস।

প্র ০২ উপরের resolve_color() ফাংশনে টোকেন না পাওয়া গেলে KeyError রেইজ করা হয়, একটি ডিফল্ট রঙ ফেরত না দিয়ে — এই নকশা সিদ্ধান্তের সুবিধা কী?

যদি একটি অজানা টোকেনের জন্য চুপচাপ একটি ডিফল্ট রঙ ফেরত দেওয়া হতো, একটি বানান-ভুল টোকেন-নাম (যেমন "backgruond") নীরবে ভুল রঙ ব্যবহার করত এবং বাগটি সহজে ধরা পড়ত না। KeyError রেইজ করা এই ভুলটি অবিলম্বে, স্পষ্টভাবে সামনে নিয়ে আসে — ডেভেলপার সাথে সাথে বুঝতে পারেন থিম ডিকশনারিতে সেই টোকেন যোগ করা হয়নি।

প্র ০৩ একটি তৃতীয় "high_contrast" থিম যোগ করতে হলে উপরের কোডে ঠিক কী পরিবর্তন করতে হবে — এবং ui_elements বা render_ui() কি বদলাতে হবে?

শুধু light_theme ও dark_theme-এর মতো একই টোকেন-নামসহ একটি নতুন high_contrast_theme ডিকশনারি সংজ্ঞায়িত করে render_ui(ui_elements, high_contrast_theme, "হাই-কনট্রাস্ট") কল করলেই যথেষ্ট — ui_elements বা render_ui()-এর কোনো কোড বদলানোর দরকার নেই, কারণ তারা টোকেন-নামের সাথে কাজ করে, কোনো নির্দিষ্ট থিমের সাথে নয়। এটিই টোকেন-ভিত্তিক থিমিংয়ের মূল স্কেলেবিলিটি সুবিধা।

অনুশীলন

  1. চিন্তা করুন: আপনার ফোনের কোনো অ্যাপ ডার্ক মোডে চালু করে দেখুন কোন কোন উপাদান সঠিকভাবে বদলায় এবং কোনোটি (যদি থাকে) অসামঞ্জস্যপূর্ণ দেখায় — এটি কি হার্ডকোড করা রঙের একটি লক্ষণ হতে পারে?

    হ্যাঁ — যদি একটি নির্দিষ্ট আইকন, ব্যানার, বা কার্ড ডার্ক মোডেও লাইট মোডের রঙেই থেকে যায় (বা উল্টো), এটি প্রায়ই ইঙ্গিত দেয় সেই নির্দিষ্ট কম্পোনেন্টটি থিম টোকেনের বদলে একটি নির্দিষ্ট রঙ কোডে সরাসরি হার্ডকোড করা হয়েছিল, যা থিম-সিস্টেমের বাকি অংশের সাথে সিঙ্ক হয়নি।

  2. পরীক্ষা করুন: উপরের কোড সেলে ui_elements লিস্টে একটি নতুন এন্ট্রি যোগ করুন — {"name": "এরর টেক্সট", "token": "error"} — কোনো থিম ডিকশনারি পরিবর্তন না করেই render_ui() আবার চালিয়ে দেখুন কী হয়।

    এটি একটি KeyError: "অজানা কালার টোকেন: error" রেইজ করবে, কারণ "error" টোকেনটি light_theme বা dark_theme কোনোটিতেই সংজ্ঞায়িত নেই। এটি একটি বাস্তবসম্মত পরিস্থিতি দেখায় — একজন ডেভেলপার নতুন UI উপাদান যোগ করলেন কিন্তু থিম ডিকশনারিতে সংশ্লিষ্ট টোকেন যোগ করতে ভুলে গেলেন, আর resolve_color()-এর কড়া চেক এই ভুলটি অবিলম্বে ধরিয়ে দেয়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

  • কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ অ্যাপ লাইফসাইকেল, মোবাইল UI/UX, MVVM/MVI আর্কিটেকচার, নেটিভ বনাম ক্রস-প্ল্যাটফর্ম, নেভিগেশন, স্টেট ম্যানেজমেন্ট, লোকাল স্টোরেজ, ডিভাইস ফিচার ও ডিপ্লয়মেন্ট — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
  • Full-Stack Web Frameworks কোর্স সহোদর কোর্স ওয়েবে CSS ভ্যারিয়েবল/কাস্টম প্রোপার্টি দিয়ে একই টোকেন-ভিত্তিক থিমিং প্যাটার্ন প্রয়োগ করা হয় — এই পাঠের ধারণা সরাসরি সমান্তরাল।
  • সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git, Theory of Computation, Engineering Economics, Full-Stack Web Frameworks ও Mobile App Development — সব এক জায়গায়।
আগের পাঠ
মোবাইল অ্যাপে অ্যাক্সেসিবিলিটি