24 January 2019

[Android Design] รับมือกับปัญหาชวนปวดหัวกับขนาดของตัวอักษรเมื่อต้องเจอกับฟอนต์ที่หลากหลาย



        ถ้าพูดถึงเรื่องฟอนต์บนแอนดรอยด์ ผู้ที่หลงเข้ามาอ่านก็คงนึกถึง Roboto เนอะ เพราะมันเป็นฟอนต์ที่ใช้บน Android 5.0 Lollipop เป็นต้นมา ถ้าทำแอปส่วนตัวก็คงไม่ต้องสนใจอะไรมาก แล้วใช้ฟอนต์ Roboto เนี่ยแหละ แต่ทว่าในโลกของการพัฒนาแอปนั้นบอกได้เลยว่า แค่เพียงฟอนต์เดียวก็อาจจะไม่เพียงพอเสมอไป

         สำหรับโลกของการดีไซน์นั้น ลักษณะของฟอนต์นั้นมีผลต่อความรู้สึกและอารมณ์ ดังนั้นการเลือกฟอนต์ที่เหมาะสมกับรูปแบบของแอปนั้นจะช่วยเพิ่มความน่าสนใจและความสวยงามให้มากขึ้น ดั่งเช่นที่ทีมดีไซน์ของ Airbnb ได้สร้างฟอนต์ขึ้นเอง โดยมีชื่อว่า Airbnb Cereal เพื่อเพิ่มเอกลักษณ์ให้กับแอปของตัวเอง


        ซึ่งการเปลี่ยนไปใช้ฟอนต์อื่นๆบนแอนดรอยด์นั้นก็ทำได้ไม่ยาก เพราะสมัยนี้มี Font Resource ให้ใช้งานอยู่แล้ว แถมรองรับเวอร์ชันเก่าๆด้วย อยากจะได้กี่ฟอนต์ก็บอกมาได้เลย

        แต่สิ่งหนึ่งที่เหล่า Designer นั้นซีเรียสกันมากๆก็คือ "ขนาดของตัวหนังสือ" นั่นเอง และถ้าผู้ที่หลงเข้ามาอ่านมีประสบการณ์คลุกคลีอยู่กับเรื่อง Typography ก็จะค้นพบว่า

        ฟอนต์แต่ละตัวไม่ได้มีขนาดเท่ากันเป๊ะๆ

        ซึ่งเป็นเรื่องที่เหล่า Designer มักจะรู้กันอยู่แล้ว จึงทำให้เวลาเปลี่ยนฟอนต์ภายในแอปจึงไม่ค่อยซีเรียสเรื่องขนาดตัวหนังสือที่เปลี่ยนไปมากนัก


        แนะนำ - ถ้าจำเป็นต้องใช้ TH Sarabun New แนะนำให้ใช้ Sarabun ที่อยู่ใน Google Fonts แทนดีกว่านะ

        ถ้าทั้งแอปใช้อยู่แค่ฟอนต์เดียว การเปลี่ยนไปเป็นฟอนต์อื่นก็คงไม่รู้สึกอะไรมากนัก แต่เมื่อแอปมีหลายฟอนต์และมีหลายขนาด ก็จะพบว่าขนาดของฟอนต์เหล่านี้มีการเหลื่อมล้ำนิดหน่อย เช่น Title ที่ควรจะมีขนาด 18sp และ Content ขนาด 16sp แต่ฟอนต์ที่ใช้ใน Title ดันเล็กกว่าปกตินิดหน่อย ก็เลยทำให้มีขนาดเท่ากับฟอนต์ที่ใช้ใน Content ซะงั้น

        สิ่งที่ต้องทำก็คือชดเชยขนาดฟอนต์ที่มีขนาดเล็กกว่าใช่มั้ยล่ะ?

        แต่อยู่ๆจะไปเปลี่ยนขนาดของฟอนต์ที่ Title ให้ใหญ่กว่าปกติเลยมันก็สุ่มเสี่ยงไปหน่อย เพราะถ้ามีหน้าอื่นๆต้องแสดงขนาดเดียวกันแต่เป็นฟอนต์อื่นก็จะพลอยซวยไปด้วยนั่นเอง

        ดังนั้นถ้ารู้สึกว่าวิธีการจัดการ Layout ของผู้ที่หลงเข้ามาอ่านนั้นมีปัญหาแบบนี้อยู่ มาเปลี่ยนวิธีกันเถอะ

กำหนดชื่อเรียกสำหรับตัวอักษรแต่ละขนาดแล้วหรือยัง?


        ถ้าผู้ที่หลงเข้าประสบปัญหาจำไม่ได้ว่าฟอนต์ตรงไหนใช้ขนาดเท่าไร แทนที่จะจำตัวเลขก็ให้เปลี่ยนเป็นชื่อเรียกดีกว่า เพราะว่าขนาดของฟอนต์นั้นแปรผันไปตามฟอนต์ที่เลือกใช้ ถ้ามีการเปลี่ยนฟอนต์หรือใช้หลายๆฟอนต์ในแอปเดียวกัน ก็จะเพิ่มความสับสนมากขึ้น เวลาคุยกับคนในทีมก็อาจจะเข้าใจไม่ตรงกัน

ขนาดของแต่ละฟอนต์ไม่ควรใช้ร่วมกัน

        ถึงให้กำหนดชื่อเรียกไงล่ะ จะได้ใช้ชื่อเรียกเป็นตัวกลางในการสื่อสารระหว่างทีมได้สะดวกขึ้น

        จากนั้นลองสร้างแอปเปล่าๆขึ้นมาซักตัวเพื่อเปรียบเทียบขนาดของฟอนต์เสียก่อน แล้วเทียบกับจากฟอนต์ปกติของตัวเครื่อง (Roboto นั่นเอง)

        และถ้าแอปมีฟอนต์หลายขนาดก็ให้เทียบทุกขนาดเลยนะ เพราะผลต่างของขนาดตัวอักษรไม่ได้คงที่ แต่จะแปรผันไปตามขนาดที่สูงขึ้น

        หมายเหตุ - ฟอนต์ที่ใช้เป็นตัวอย่างในบทความนี้เป็นฟอนต์ที่มาจาก Google Fonts ซึ่งอิงมาตรฐานอยู่แล้ว จึงไม่ค่อยเห็นความแตกต่างอะไรมากนัก แต่ชีวิตจริงนั้นอะไรก็เกิดขึ้นได้เสมอ

        เมื่อได้ขนาดของแต่ละฟอนต์แล้ว ก็เตรียม Dimension Resource ไว้เลย

// dimens.xml
<resources>
    // Default (Roboto)
    <dimen name="text_size_default_sub_detail">12sp</dimen>
    <dimen name="text_size_default_detail">14sp</dimen>
    <dimen name="text_size_default_content">16sp</dimen>
    <dimen name="text_size_default_sub_title">18sp</dimen>
    <dimen name="text_size_default_title">22sp</dimen>

    // Kanit
    <dimen name="text_size_kanit_sub_detail">13sp</dimen>
    <dimen name="text_size_kanit_detail">15sp</dimen>
    <dimen name="text_size_kanit_content">18sp</dimen>
    <dimen name="text_size_kanit_sub_title">19sp</dimen>
    <dimen name="text_size_kanit_title">24sp</dimen>

    // Mitr
    <dimen name="text_size_mitr_sub_detail">13sp</dimen>
    <dimen name="text_size_mitr_detail">15sp</dimen>
    <dimen name="text_size_mitr_content">17sp</dimen>
    <dimen name="text_size_mitr_sub_title">19sp</dimen>
    <dimen name="text_size_mitr_title">23sp</dimen>

    // Sarabun
    <dimen name="text_size_sarabun_sub_detail">12sp</dimen>
    <dimen name="text_size_sarabun_detail">14sp</dimen>
    <dimen name="text_size_sarabun_content">16sp</dimen>
    <dimen name="text_size_sarabun_sub_title">18sp</dimen>
    <dimen name="text_size_sarabun_title">22sp</dimen>
</resources>

        และสำคัญที่สุดก็คือการสร้าง Style Resource ขึ้นมาเพื่อจะได้ Reuse ค่าเหล่านี้ได้ง่ายขึ้น (ขนาดตัวอักษร, สี และฟอนต์)

// styles.xml
<resources>
    <style name="Text" />

    // Default (Roboto)
    <style name="Text.Default" />

    <style name="Text.Default.Black">
        <item name="android:textColor">@color/black</item>
    </style>

    <style name="Text.Default.Black.Normal">
        <item name="android:textSize">@dimen/text_size_default_normal</item>
    </style>

    <style name="Text.Default.Black.Large">
        <item name="android:textSize">@dimen/text_size_default_large</item>
    </style>

    <style name="Text.Default.Black.Small">
        <item name="android:textSize">@dimen/text_size_default_small</item>
    </style>

    // Kanit
    <style name="Text.Kanit">
        <item name="fontFamily">@font/kanit</item>
    </style>

    <style name="Text.Kanit.Black">
        <item name="android:textColor">@color/black</item>
    </style>

    <style name="Text.Kanit.Black.Normal">
        <item name="android:textSize">@dimen/text_size_kanit_normal</item>
    </style>

    <style name="Text.Kanit.Black.Large">
        <item name="android:textSize">@dimen/text_size_kanit_large</item>
    </style>

    <style name="Text.Kanit.Black.Small">
        <item name="android:textSize">@dimen/text_size_kanit_small</item>
    </style>

    // Mitr
    <style name="Text.Mitr">
        <item name="fontFamily">@font/mitr</item>
    </style>

    ...ขี้เกียจพิมพ์...

    // Sarabun
    <style name="Text.Sarabun">
        <item name="fontFamily">@font/sarabun</item>
    </style>

    ...ขี้เกียจพิมพ์...
</resources>

        ขอยกตัวอย่างเป็นตัวหนังสือสีดำทุกขนาดเฉพาะ 2 ฟอนต์แรกละกัน ขี้เกียจพิมพ์เยอะ...

พร้อมใช้งานแล้ว

         อยากจะให้ใช้ฟอนต์อะไรตรงไหน ขนาดเท่าไรก็กำหนดด้วย Style Resource ได้ตามต้องการเลย

<TextView
    style="@style/Text.Kanit.Black.Title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/any_title" />

<TextView
    style="@style/Text.Default.Black.Content"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/any_content" />

        เพียงเท่านี้ก็หมดปัญหาฟอนต์หลายตัวที่ดันมีขนาดต่างกันแล้ว ไม่ต้องตบตีกับ Designer อีกต่อไปแล้ว

สรุป

        จริงๆแล้วการทำ Pixel Perfect ให้กับตัวอักษรภายในแอปนั้นไม่ใช่เรื่องยากนัก เพราะว่าแอนดรอยด์นั้นมี XML Resource สุดเทพอย่าง Dimension Resource, Style Resource และ Font Resource ให้ใช้งานอยู่แล้ว ขอแค่เข้าใจวิธีการใช้งานร่วมกันเพื่อออกแบบให้แอปสามารถ Scale ได้ง่าย เมื่อถึงเวลาที่จำเป็นต้องแก้ไขก็สามารถทำได้ทันทีอย่างง่ายดาย ไม่ต้องมานั่งไล่แก้เองทั้งหมดให้เสียเวลาหรือต้องมานั่งบอก Designer ว่าใช้เวลาแก้เยอะ เพราะไม่ได้วางเผื่อไว้ตั้งแต่แรก