ชุดแอป Kriptofolio - ตอนที่ 2
แล้วคุณจะเริ่มสร้างแอพใหม่ได้อย่างไร? สิ่งแรกที่คุณควรทำคืออะไร? หากคุณคิดว่าเราจำเป็นต้องเปิดตัว Android Studio และข้ามไปที่โค้ดโดยตรง ให้คิดใหม่ นั่นคือสิ่งที่ฉันไม่แนะนำให้ทำเพราะมันสามารถสร้างความเสียหายได้มากกว่าผลดี แต่การเริ่มเขียนโค้ดบรรทัดแรกโดยเร็วที่สุดเป็นเรื่องที่น่าดึงดูดใจมาก
แต่ฉันขอแนะนำให้มุ่งเน้นไปที่การวางแผนอย่างชาญฉลาดด้วยการจำลอง UI จำไว้ว่าทุกโปรเจ็กต์แอพใหม่ที่ดีควรเริ่มต้นด้วยสิ่งนั้น ด้วยวิธีการนี้ คุณจะไม่เสียเวลามากนักและจะสามารถสร้างผลิตภัณฑ์คุณภาพสูงได้ตั้งแต่ต้น
ดังนั้นในภาคนี้ของซีรีส์ ฉันจะนำเสนอแอปจำลอง “Kriptofolio” (ก่อนหน้านี้คือ “My Crypto Coins”) และหารือเกี่ยวกับวิธีการสร้าง นอกจากนี้ เรากำลังจะสร้างเค้าโครง UI ทั้งหมด เลย์เอาต์เหล่านี้จะกลายเป็นรากฐานที่มั่นคงของเราซึ่งระบุได้ชัดเจนว่าควรเขียนโค้ดอะไร สุดท้าย เราจะแปลแอปของเราเป็นภาษาต่างๆ และเรียนรู้วิธีจัดการกับภาษาที่เขียนจากขวาไปซ้าย
เนื้อหาซีรีส์
- บทนำ:แผนงานในการสร้างแอป Android ที่ทันสมัยในปี 2018–2019
- ส่วนที่ 1:การแนะนำหลักการ SOLID
- ส่วนที่ 2:วิธีเริ่มสร้างแอป Android:การสร้าง Mockups, UI และเลย์เอาต์ XML (คุณอยู่ที่นี่)
- ส่วนที่ 3:ทั้งหมดเกี่ยวกับสถาปัตยกรรมนั้น:สำรวจรูปแบบสถาปัตยกรรมต่างๆ และวิธีใช้งานในแอปของคุณ
- ส่วนที่ 4:วิธีการใช้ Dependency Injection ในแอปของคุณด้วย Dagger 2
- ส่วนที่ 5:จัดการ RESTful Web Services โดยใช้ Retrofit, OkHttp, Gson, Glide และ Coroutines
ภาพจำลอง
มีหลายวิธีในการสร้างแบบจำลองโครงการของคุณ วิธีที่ง่ายที่สุดคือการหยิบดินสอกับกระดาษหนึ่งแผ่นแล้วเริ่มวาด ส่วนที่ดีที่สุดคือวิธีนี้ไม่เสียค่าใช้จ่ายใดๆ และคุณสามารถเริ่มต้นได้ทันที อ้อ เกือบลืมไปเลย คุณควรหายางลบให้ตัวเองด้วย เพราะจะไม่มีฟังก์ชันเลิกทำ ?
หากคุณรู้สึกว่าคุณต้องการฟังก์ชันเพิ่มเติม เช่นเดียวกันกับฉัน ให้พิจารณาใช้ซอฟต์แวร์พิเศษเพื่อสร้างแบบจำลองที่มีรายละเอียด ฉันชอบใช้ซอฟต์แวร์แทนดินสอและกระดาษ ถึงแม้ว่าคุณจะต้องลงทุนด้วยเงินเพื่อซื้อและใช้เวลาในการเรียนรู้วิธีใช้งาน
มีตัวเลือกซอฟต์แวร์ต่างๆ ในตลาดให้เลือก คุณจะต้องทำการตรวจสอบด้วยตัวเองว่าอันไหนที่ตรงกับความต้องการของคุณมากที่สุด สำหรับโปรเจ็กต์จำลองทั้งหมดของฉันตอนนี้ฉันกำลังใช้แอพ Balsamiq Mockups สำหรับเดสก์ท็อป Balsamiq เป็นซอฟต์แวร์ทำโครงลวดที่รวดเร็ว มีประสิทธิภาพ และใช้งานง่ายมาก เนื่องจากฉันค่อนข้างพอใจกับมัน ฉันจึงแนะนำให้สร้างแอป Android ดังนั้นโปรดลองใช้ดู
ฉันเริ่มโปรเจ็กต์แอป My Crypto Coins ด้วยการสร้างแบบจำลองที่คิดมาอย่างดีและมีรายละเอียดมาก ฉันคิดกับตัวเองว่าถ้าฉันสร้างทุกอย่างอย่างละเอียดถี่ถ้วน ฉันจะหลีกเลี่ยงข้อผิดพลาด ฉันจะไม่เสียเวลากับการเปลี่ยนแปลงการทำงานกะทันหันในระหว่างกระบวนการพัฒนา หากคุณใช้ความพยายามอย่างมากในการสร้างแบบจำลองที่ดี มากกว่าการใช้จินตนาการเพียงเล็กน้อย คุณจะเห็นและสัมผัสได้ถึงผลิตภัณฑ์ขั้นสุดท้าย
เป้าหมายของฉันคือการมีทุกอย่างที่กำหนดไว้ในแบบจำลองอย่างที่ควรจะเป็นในผลิตภัณฑ์ขั้นสุดท้าย เพื่อที่ฉันจะได้พยายามไม่เร่งรีบแต่ใช้เวลาให้มากที่สุดเท่าที่ฉันต้องการ นี่คือแบบจำลองสุดท้ายของฉันสำหรับแอป My Crypto Coins:
การออกแบบสต็อค — วัสดุ
สิ่งสำคัญอีกอย่างที่ต้องพูดถึงคือการออกแบบภาพของแอป ในขณะที่เขียนบทความนี้ การออกแบบวัสดุคือการออกแบบภาพสต็อกที่แนะนำโดย Google สำหรับแอป Android ทั้งหมด และคาดเดาอะไร — คุณจะไม่ผิดพลาดกับการออกแบบสต็อก
สำหรับแอพ My Crypto Coins เราจะใช้ดีไซน์ Material แอปปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดที่กำหนดไว้ในหลักเกณฑ์ออนไลน์โดยละเอียด
Material.io/guidelines — เอกสารข้อกำหนดการใช้ชีวิตของดีไซน์ Material อย่างเป็นทางการ ซึ่งจะเป็นแนวทางการออกแบบของเราสำหรับโครงการนี้
เลย์เอาต์
เมื่อเราเตรียมไวร์เฟรมของแอปแล้ว ก็ถึงเวลาสร้าง UI จริง อีกครั้งเราสามารถกระโดดลงไปในการเขียนโค้ดได้ แต่ทำไมต้องรีบ? ฉันขอแนะนำให้เน้นที่การสร้างเลย์เอาต์ XML ทั้งหมดของคุณแทน คำแนะนำของฉันในที่นี้คือยิ่งคุณสามารถใส่ลงใน XML ได้มากเท่าไหร่ คุณก็จะยิ่งต้องเขียนโค้ดน้อยลงเท่านั้น
ทีมงาน Android ปรับปรุงวิธีการสร้าง UI ของคุณอย่างต่อเนื่องโดยเพิ่มคุณสมบัติใหม่ให้กับเค้าโครง XML บางครั้งการเขียนโค้ดไม่กี่บรรทัดเพื่อให้ได้รูปลักษณ์ที่ต้องการก็เป็นเรื่องที่น่าดึงดูดใจ แต่ควรตรวจสอบหัวข้ออย่างลึกซึ้งยิ่งขึ้นเพื่อค้นหาว่าสามารถทำได้โดยไม่ต้องใช้โค้ดหรือไม่ ข้อควรจำ:โค้ดที่น้อยลงทำให้โปรเจ็กต์ของคุณดูสะอาดตา นอกจากนี้ยังจะเข้าใจได้ง่ายขึ้นสำหรับนักพัฒนาคนอื่นๆ และง่ายต่อการบำรุงรักษา
สุดท้าย เมื่อคุณสร้างเลย์เอาต์ XML ทั้งหมด คุณจะรู้สึกเหมือนได้สร้างแอปขึ้นมา คุณจะสามารถเปิดใช้งานและดูว่าผู้ใช้รู้สึกอย่างไร ไม่สำคัญว่าจะแสดงข้อมูลปลอมและไม่ทำอะไรเลย ตอนนี้คุณมีโอกาสสุดท้ายที่จะทำการเปลี่ยนแปลงครั้งใหญ่
หากคุณกำลังสร้างแอปสำหรับคนอื่น เป็นเวลาที่ดีที่จะนำเสนอ บางทีคุณอาจถูกขอให้ทำการเปลี่ยนแปลงในนาทีสุดท้ายที่น่าประหลาดใจ ด้วยวิธีนี้คุณจะหลีกเลี่ยงการเขียนโค้ดสำหรับฟังก์ชันที่ไม่เคยใช้งาน หลายคนไม่มีจินตนาการเพียงพอ และพวกเขาต้องเห็นและสัมผัสก่อนเพื่อตัดสินใจว่ามันเป็นสิ่งที่พวกเขาต้องการหรือไม่ ดังนั้นอย่าปล่อยให้เค้าโครงของคุณเป็นขั้นตอนสุดท้ายในกระบวนการทำงานของคุณ
สำหรับแอปนี้ ฉันจะใช้ส่วนประกอบต่างๆ ที่พบได้ทั่วไปในแอป Android สมัยใหม่ทั้งหมด:
- CoordinatorLayout — FrameLayout ที่ทรงพลัง จุดเด่นหลักอยู่ที่ความสามารถในการประสานแอนิเมชั่นและการเปลี่ยนมุมมองภายใน
- AppBarLayout — LinearLayout แนวตั้งซึ่งนำฟีเจอร์มากมายของแนวคิดแถบแอปของดีไซน์ Material ไปใช้ ซึ่งก็คือการเลื่อนหน้าจอ
- แถบเครื่องมือ — ลักษณะทั่วไปของแถบการทำงานสำหรับใช้ภายในเค้าโครงแอปพลิเคชัน
- CollapsingToolbarLayout — wrapper สำหรับ Toolbar ซึ่งใช้แถบแอปที่ยุบ ออกแบบมาเพื่อใช้เป็นลูกโดยตรงของ AppBarLayout
- ConstraintLayout — ViewGroup ที่ให้คุณจัดตำแหน่งและปรับขนาดวิดเจ็ตด้วยวิธีที่ยืดหยุ่น ลองนึกภาพเค้าโครงสัมพัทธ์กับสเตียรอยด์
- SwipeRefreshLayout — วิดเจ็ตที่อนุญาตให้ใช้รูปแบบอินเทอร์เฟซผู้ใช้แบบปัดเพื่อรีเฟรชทั้งหมด โดยจะตรวจจับการเลื่อนในแนวตั้ง แสดงแถบความคืบหน้าที่โดดเด่น และเรียกใช้วิธีการโทรกลับในแอปของคุณ
- FloatingActionButton — ปุ่มวงกลมที่ทริกเกอร์การทำงานหลักใน UI ของแอปของคุณ
สำหรับหน้าจอหลัก เราจะใช้ส่วนประกอบเหล่านี้ร่วมกันเพื่อสร้าง UI/UX ที่ดี ผู้ใช้สามารถขยายและยุบส่วนบนของเลย์เอาต์เพื่อค้นหามูลค่ารวมของพอร์ตสกุลเงินดิจิตอลทั้งหมดของพวกเขา โดยสามารถตรวจสอบการเปลี่ยนแปลงมูลค่าในช่วง 24 ชั่วโมงที่ผ่านมาและเปลี่ยนสกุลเงินคำสั่งที่เลือกได้
แน่นอนว่ายังมีองค์ประกอบอื่นๆ นอกเหนือจากเก้าชิ้นนี้ สิ่งสำคัญคือต้องควบคุมจานสีส่วนประกอบทั้งหมดให้เชี่ยวชาญเพื่อทราบว่าจะใช้จานสีใดในกรณีใดกรณีหนึ่ง ด้วยแนวโน้มของมือถือที่เปลี่ยนแปลงเป็นครั้งคราวจานสีก็จะขยายตัวเช่นกัน
ฉันจะไม่พูดถึงทุกองค์ประกอบ แต่คำแนะนำของฉันคือการตรวจสอบด้วยตัวคุณเอง สำหรับฉันวิธีที่ดีที่สุดในการทำความเข้าใจคือพยายามสร้างเลย์เอาต์ XML ด้วยตนเองแทนที่จะใช้เครื่องมือลากและวางอัตโนมัติใน Android Studio
รูปแบบ สี ขนาด สตริง ไอคอน
เมื่อมองแวบแรก สิ่งที่กล่าวถึงในหัวข้อนี้อาจดูไม่สำคัญ อย่างไรก็ตาม ฉันขอให้คุณใช้ความพยายามในการสร้างมันในแอพใดๆ หากคุณต้องการทำให้มันทันสมัยและพิเศษสุด จำชุดโพสต์บล็อกนี้เป็นวิธีการสร้างแอพ MODERN Android! ไม่ว่าจะผิดแค่ไหน ผู้คนมักจะตัดสินแอปของคุณด้วยรูปลักษณ์ก่อน ไม่ใช่จากฟังก์ชัน
ดังนั้นนี่คือโอกาสที่ดีที่จะได้รับความรักจากผู้ใช้ใหม่ตั้งแต่ต้น นี่คือคำแนะนำของฉัน:
- เมื่อสร้างไฟล์เลย์เอาต์ XML คุณควรจำตำแหน่งที่คุณทำซ้ำแอตทริบิวต์ทั่วไปบางอย่างสำหรับมุมมอง ย้ายเพื่อกำหนดเป็นสไตล์ XML ที่แยกจากกัน ด้วยวิธีนี้ คุณจะมีไฟล์เลย์เอาต์ XML ที่สั้นลง คุณสามารถควบคุมลักษณะการออกแบบแอปทั้งหมดได้จากที่อื่น ลองนึกดูว่ามันจะให้ประโยชน์อะไรกับคุณ ตัวอย่างเช่น คุณอาจอนุญาตให้ผู้ใช้เลือกสกินของแอป (สว่าง มืด ฯลฯ)
- กำหนดสีแอปทั้งหมดของคุณในไฟล์แยกต่างหาก และเพลิดเพลินกับความสามารถในการทดลองกับรูปลักษณ์โดยเปลี่ยนทันที บางครั้งผลิตภัณฑ์เดียวกันสามารถให้ชีวิตใหม่และดึงดูดผู้ใช้อีกครั้งโดยเพียงแค่รีเฟรชด้วยสีใหม่ มีเว็บไซต์ไม่กี่แห่งที่สามารถช่วยคุณเลือกสีที่สวยงามได้ แต่เว็บไซต์ที่ฉันชอบคือ MaterialPalette.com ลองดูสิ
- กำหนดขนาดแอปของคุณในไฟล์แยกต่างหาก วิธีนี้จะช่วยให้คุณปรับแต่งแอปให้ดูดีในหน้าจอขนาดต่างๆ ได้
- สตริงทั้งหมดของคุณไม่ควรถูกฮาร์ดโค้ด และ Android Studio จะแจ้งให้คุณทราบหากคุณลืม อย่าละเลยสิ่งนั้น ส่วนที่ดีที่สุดเมื่อแยกสตริงคือคุณสามารถแปลแอปเป็นภาษาต่างๆ ได้
- เมื่อใช้ไอคอนสำหรับแอปของคุณ ควรใช้รูปแบบเวกเตอร์ XML ที่วาดได้เสมอ นั่นคือมาตรฐานใหม่ที่แนะนำและเป็นวิธีที่ชาญฉลาดในการหลีกเลี่ยงภาพพิกเซล หากต้องการค้นหาไอคอนสไตล์ดีไซน์ Material ที่สร้างขึ้นอย่างมืออาชีพจากชุมชน โปรดดู MaterialDesignIcons.com ฉันใช้เว็บไซต์นี้เพื่อรับไอคอนสำหรับแอป My Crypto Coins
RecyclerView
หน้าจอหลักของแอพ My Crypto Coins จะประกอบด้วยรายการ cryptocurrencies ที่ผู้ใช้ถืออยู่ เพื่อจุดประสงค์นี้ วิดเจ็ต RecyclerView เหมาะสมที่สุด เป็นวิดเจ็ตที่แสดงรายการเลื่อนขององค์ประกอบตามชุดข้อมูลขนาดใหญ่ (หรือข้อมูลที่เปลี่ยนแปลงบ่อย)
เนื่องจากข้อดีของมัน RecyclerView จึงเป็นส่วนประกอบที่แนะนำสำหรับการสร้างหน้าจอรายการใดๆ เป็นเวอร์ชันขั้นสูงและยืดหยุ่นกว่าของคอมโพเนนต์ ListView ที่เรียบง่ายกว่า เราจะพูดถึงมันในภายหลังด้วย ในส่วนนี้ เรากำลังสร้างแค่เลย์เอาต์ เราไม่เน้นเขียนโค้ด
หากต้องการดูแอปของเราเป็นภาพ เราจะต้องติดตั้ง RecyclerView โดยการเขียนโค้ด นี่คือขั้นตอนในการติดตั้ง RecyclerView:
1. เพิ่มองค์ประกอบ RecyclerView
MainActivity
ของเรา เลย์เอาต์คือ activity_main.xml
. เลย์เอาต์นี้รวม content_main.xml
เลย์เอาต์ซึ่งเป็นชิ้นส่วน MainActivityListFragment
นี้ เลย์เอาต์พองตัว fragment_main_list.xml
. ดังนั้นคุณควรเพิ่มองค์ประกอบ RecyclerView ที่นี่
...
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview_fragment_main_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorForMainListBackground"
android:clipToPadding="false"
android:paddingBottom="72dp"
android:paddingTop="5dp"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical" />
...
อย่างที่คุณเห็นเรากำหนดค่า RecyclerView ของเราให้เหลือช่องว่างที่ด้านล่าง เราทำเช่นนี้เพื่อหลีกเลี่ยงการครอบคลุมรายการสุดท้ายด้วย FloatingActionButton นอกจากนี้เรายังเปิดแถบเลื่อนแนวตั้งเพื่อให้ใช้งานได้
2. สร้างเค้าโครงแถว RecyclerView
สำหรับจุดประสงค์แรกเริ่ม เราจะตั้งชื่อรายการสำหรับแต่ละแถวเท่านั้น เลย์เอาต์ที่เรียบง่ายของเราควรมีลักษณะดังนี้
<android.support.v7.widget.CardView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/main_cardview_list_item_outer_top_bottom_margin"
android:layout_marginEnd="@dimen/main_cardview_list_item_outer_start_end_margin"
android:layout_marginStart="@dimen/main_cardview_list_item_outer_start_end_margin"
android:layout_marginTop="@dimen/main_cardview_list_item_outer_top_bottom_margin"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="@color/colorForMainListItemBackground">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/main_cardview_list_item_inner_margin">
...
<android.support.v7.widget.AppCompatTextView
android:id="@+id/item_name"
style="@style/MainListItemPrimeText"
android:layout_marginEnd="@dimen/main_cardview_list_item_text_between_margin"
android:layout_marginStart="@dimen/main_cardview_list_item_inner_margin"
app:layout_constraintBottom_toTopOf="@+id/item_amount_symbol"
app:layout_constraintEnd_toStartOf="@+id/guideline1_percent"
app:layout_constraintStart_toEndOf="@+id/item_image_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread"
tools:text="@string/sample_text_item_name" />
...
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
3. สร้างคลาสอะแดปเตอร์ข้อมูล
อะแดปเตอร์ของเราในตอนนี้จะยอมรับข้อมูลสตริง ต่อมาเราจะต้องสร้างแบบจำลองข้อมูลคลาสแยกต่างหาก เราจะต้องส่งข้อมูลมากกว่าหนึ่งสตริงเท่านั้น
class MainRecyclerViewAdapter(val dataList: ArrayList<String>) : RecyclerView.Adapter<MainRecyclerViewAdapter.CustomViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.fragment_main_list_item, parent, false)
return CustomViewHolder(v)
}
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
holder.txtName?.text = dataList[position]
}
override fun getItemCount(): Int {
return dataList.size
}
inner class CustomViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val txtName = itemView.findViewById<TextView>(R.id.item_name)
}
}
4. เชื่อมต่อ RecyclerView กับอะแดปเตอร์ที่กำหนดเอง
class MainActivityListFragment : Fragment() {
private lateinit var recyclerView: RecyclerView
private lateinit var recyclerAdapter: MainRecyclerViewAdapter
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val v: View = inflater.inflate(R.layout.fragment_main_list, container, false)
recyclerView = v.findViewById(R.id.recyclerview_fragment_main_list)
return v
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupList()
}
private fun setupList() {
val data = ArrayList<String>()
data.add("Bitcoin")
data.add("Etherium")
data.add("Ripple")
data.add("Bitcoin Cash")
data.add("Litecoin")
data.add("NEO")
data.add("Stellar")
data.add("EOS")
data.add("Cardano")
data.add("Stellar")
data.add("IOTA")
data.add("Dash")
data.add("Monero")
data.add("TRON")
data.add("NEM")
data.add("ICON")
data.add("Bitcoin Gold")
data.add("Zcash")
data.add("Verge")
recyclerView.layoutManager = LinearLayoutManager(activity)
recyclerAdapter = MainRecyclerViewAdapter(data)
recyclerView.adapter = recyclerAdapter
}
}
เสร็จแล้ว! ตอนนี้หน้าจอหลักของเรามีลักษณะดังนี้:
ListView
ในโครงการนี้ เราจะใช้ ListView สำหรับหน้าจอที่คุณสามารถเพิ่ม crypto coin ที่คุณมีอยู่แล้วได้ เนื่องจากข้อบกพร่องในช่วงไม่กี่ปีที่ผ่านมาจึงแทบจะไม่ได้ใช้อีกต่อไป
ดังนั้น ฉันเดาว่าตอนนี้พวกคุณหลายคนกำลังสงสัยว่าทำไมฉันจึงตัดสินใจใช้มันในแอป My Crypto Coins ในเมื่อเราสามารถสร้างฟังก์ชันเดียวกันได้อย่างง่ายดายด้วย RecyclerView
โปรดจำไว้ว่า โครงการนี้ถูกสร้างขึ้นเพื่อวัตถุประสงค์ในการฝึกอบรมก่อน ฉันคิดว่าการได้รับข้อมูลเชิงลึกเกี่ยวกับ ListView และวิธีการทำงานจะเป็นประโยชน์ นักพัฒนาซอฟต์แวร์ทุกคนอาจใช้งาน ListView ในโค้ดเดิมได้ และวิธีที่ดีที่สุดคือต้องรู้วิธีใช้งาน นอกจากนี้ รายการที่เราจะสร้างนั้นเรียบง่ายมาก โดยที่ข้อจำกัดทางเทคนิคของ ListView จะไม่สร้างปัญหาใดๆ ให้กับเรา
มาทำตามขั้นตอนที่คล้ายกันมากเพื่อใช้งาน ListView:
1. เพิ่มองค์ประกอบ ListView
สิ่งแรกที่ต้องทำคือเพิ่ม ListView ใน AddSearchActivity
. เปิดไฟล์รูปแบบกิจกรรม activity_add_search.xml
แล้วจะเห็นว่ามี content_add_search.xml
. เราจะเพิ่มองค์ประกอบ ListView ที่นั่น
...
<ListView
android:id="@+id/listview_activity_add_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
...
2. สร้างเค้าโครงแถว ListView
เช่นเคย เพื่อจุดประสงค์เบื้องต้น เราจะตั้งชื่อรายการสำหรับแต่ละแถวเท่านั้น นี่คือเลย์เอาต์แบบง่าย:
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/add_search_list_item_inner_margin">
...
<android.support.v7.widget.AppCompatTextView
android:id="@+id/item_name"
style="@style/AddSearchListItemPrimeText"
android:layout_marginEnd="@dimen/add_search_list_item_text_between_margin_2x"
android:layout_marginStart="@dimen/add_search_list_item_text_between_margin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/item_symbol"
app:layout_constraintStart_toEndOf="@+id/item_image_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/sample_text_item_name" />
...
</android.support.constraint.ConstraintLayout>
3. สร้างคลาสอะแดปเตอร์ข้อมูล
เช่นเดียวกับ RecyclerView อะแดปเตอร์ ListView ของเราในตอนนี้จะยอมรับเฉพาะข้อมูลสตริงเพื่อรับชื่อรายการและแสดงบนหน้าจอ ต่อมาเราจะใช้โมเดลข้อมูลคลาสที่แยกจากกัน สำหรับส่วนนี้ เราต้องการสร้างรายการง่ายๆ ที่แสดงเฉพาะชื่อสกุลเงินดิจิทัล แทนที่จะสร้างอะแดปเตอร์แบบกำหนดเอง เราสามารถใช้ ArrayAdapter ที่เป็นค่าเริ่มต้น
class AddSearchListAdapter(context: Context, private val dataSource: ArrayList<String>) : BaseAdapter() {
private val inflater: LayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view: View
val holder: CustomViewHolder
if (convertView == null) {
view = inflater.inflate(R.layout.activity_add_search_list_item, parent, false)
holder = CustomViewHolder()
holder.nameTextView = view.findViewById(R.id.item_name)
view.tag = holder
} else {
view = convertView
holder = convertView.tag as CustomViewHolder
}
val nameTextView = holder.nameTextView
nameTextView.text = getItem(position) as String
return view
}
override fun getItem(position: Int): Any {
return dataSource[position]
}
override fun getItemId(position: Int): Long {
return position.toLong();
}
override fun getCount(): Int {
return dataSource.size
}
inner class CustomViewHolder {
lateinit var nameTextView: AppCompatTextView
}
}
ดังที่คุณเห็นในโค้ดอแดปเตอร์ โดยการสร้าง CustomViewHolder
วัตถุฉันใช้รูปแบบ ViewHolder มันเก็บการอ้างอิงมุมมองแถวรายการ เรียก findViewById()
วิธีการเกิดขึ้นสองครั้งเท่านั้น ช่วยให้เราสามารถเลื่อนรายการของเราได้อย่างราบรื่นและมีประสิทธิภาพ
ListView ไม่ต้องการให้เราใช้รูปแบบ ViewHolder อะแดปเตอร์ของ RecyclerView ให้การป้องกันแบบนั้นโดยค่าเริ่มต้น เนื่องจากบังคับให้เราต้องใช้งาน
4. เชื่อมต่อ ListView กับอะแดปเตอร์ที่กำหนดเอง
ด้วย ArrayAdapter เริ่มต้น อาจดูเหมือน val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, data)
. นั่นคือความสวยงามขององค์ประกอบ ListView หากต้องการ คุณสามารถสร้างรายการง่ายๆ ได้อย่างรวดเร็วโดยไม่ต้องสร้างอะแดปเตอร์หรือเค้าโครงแถว (ข้ามขั้นตอนที่ 2 และ 3)
class AddSearchActivity : AppCompatActivity() {
private lateinit var listView: ListView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_search)
setSupportActionBar(toolbar2)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val data = ArrayList<String>()
data.add("Bitcoin")
data.add("Etherium")
data.add("Ripple")
data.add("Bitcoin Cash")
data.add("Litecoin")
data.add("NEO")
data.add("Stellar")
data.add("EOS")
data.add("Cardano")
data.add("Stellar")
data.add("IOTA")
data.add("Dash")
data.add("Monero")
data.add("TRON")
data.add("NEM")
data.add("ICON")
data.add("Bitcoin Gold")
data.add("Zcash")
data.add("Verge")
val adapter = AddSearchListAdapter(this, data)
listView = findViewById(R.id.listview_activity_add_search)
listView.adapter = adapter
}
...
}
การตั้งค่า ListView พร้อมแล้ว!
SearchView
ในหน้าจอเดียวกันกับที่แสดงรายการ cryptocurrencies ทั้งหมด เราจำเป็นต้องเพิ่ม SearchView ด้วย การค้นหาจะเป็นฟังก์ชันที่มีประโยชน์สำหรับผู้ใช้ที่ต้องการค้นหาสกุลเงินดิจิทัลเฉพาะโดยพิมพ์ชื่อ สำหรับส่วนนี้ เราจะไม่สร้างฟังก์ชันการทำงานทั้งหมด แต่จะใช้งานส่วนที่มองเห็นได้เท่านั้น ทำตามขั้นตอนเหล่านี้เพื่อเพิ่ม SearchView ในโครงการ:
1. ประกาศการกำหนดค่าที่ค้นหาได้ใน XML
ควรเพิ่มไฟล์คอนฟิกูเรชันที่ค้นหาได้ในไดเร็กทอรี res ของคุณที่ชื่อ xml คุณสามารถระบุแอตทริบิวต์สำหรับองค์ประกอบ SearchView ซึ่งกำหนดลักษณะการทำงานได้ที่นี่
<searchable
xmlns:android="https://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/search_hint">
</searchable>
2. สร้างกิจกรรมใหม่ซึ่งจะกลายเป็นกิจกรรมที่เราค้นหาได้
เรากำลังจะสร้างกิจกรรมว่างใหม่ที่ขยาย AppCompatActivity()
. เราจะตั้งชื่อมันว่า AddSearchActivity
.
3. ระบุกิจกรรมที่สร้างขึ้นใหม่ในไฟล์ Manifest ของ Android ให้ค้นหาได้
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.baruckis.mycryptocoins">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<activity
android:name=".AddSearchList.AddSearchActivity"
android:launchMode="singleTop"
android:parentActivityName=".MainList.MainActivity"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
...
</application>
</manifest>
เราจะให้ระบบ Android จัดการกระบวนการค้นหา นั่นเป็นเหตุผลที่เราเพิ่มการค้นหาการกระทำโดยเจตนาและข้อมูลเมตาในองค์ประกอบกิจกรรมของ AddSearchActivity
. ข้อมูลเมตามีชื่อและทรัพยากรที่เชื่อมโยงกับไฟล์การกำหนดค่าที่ค้นหาได้ซึ่งอยู่ในโฟลเดอร์ res/xml
4. สร้างเมนูค้นหา
ภายในโฟลเดอร์ res/menu เราจะสร้างไฟล์ทรัพยากรเมนู
<menu xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto">
<item
android:id="@+id/search"
android:icon="@drawable/ic_search"
android:title="@string/action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView" />
</menu>
5. เพิ่มเมนูค้นหาให้กับกิจกรรม
เราจะเพิ่มวิดเจ็ตการค้นหาของ Android เป็นมุมมองการทำงานของเมนู
class AddSearchActivity : AppCompatActivity() {
...
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_search, menu)
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
val searchView = menu?.findItem(R.id.search)?.actionView as SearchView
searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName))
searchView.maxWidth = Integer.MAX_VALUE
return true
}
}
ตอนนี้เพิ่ม SearchView ลงในกิจกรรมแล้ว ยังคงฟังก์ชันการค้นหาไม่ทำงาน แต่เราได้ดำเนินการตามที่เราต้องการสำหรับส่วนนี้
การตั้งค่า
หากคุณต้องการสร้างแอป Android ที่ทันสมัย เราขอแนะนำให้คุณรวมหน้าจอการตั้งค่าและให้สิทธิ์เข้าถึงการตั้งค่าแอปสำหรับผู้ใช้ การรวมการตั้งค่าในแอปของคุณทำให้ผู้ใช้มีอำนาจในการควบคุมฟังก์ชันการทำงานบางอย่างของแอปซึ่งทำให้พวกเขามีความสุขมากขึ้น ตอนนี้พวกเขาเป็นผู้ควบคุมลักษณะการทำงานของแอป ดังนั้นเราจะสร้างหน้าจอการตั้งค่าสำหรับแอป My Crypto Coins ด้วย
คุณสามารถสร้างหน้าจอการตั้งค่าด้วยเทมเพลต Android Studio และจะสร้างรหัสทั้งหมดที่คุณต้องการ โดยค่าเริ่มต้นในขณะที่เขียนโพสต์ในบล็อกนี้ กิจกรรมการตั้งค่าจะถูกสร้างขึ้นด้วยส่วนหัวของการตั้งค่า นั่นไม่ใช่สิ่งที่เราต้องการสำหรับแอปเล็กๆ ที่เราวางแผนไว้ว่าจะมีการตั้งค่าเพียงเล็กน้อยในตอนแรก
ดังนั้นเราจะสร้างทุกอย่างด้วยตนเอง หน้าจอการตั้งค่าได้รับการออกแบบด้วยเลย์เอาต์ที่เหมือน XML ไปทีละขั้นตอนเพื่อสร้างอีกครั้งเฉพาะส่วนที่มองเห็นสำหรับโพสต์ในบล็อกนี้:
1. สร้างไฟล์ XML หน้าจอการตั้งค่า
เรากำลังจะสร้างไฟล์ XML หน้าจอการตั้งค่าซึ่งควรวางไว้ในไดเร็กทอรี res/xml
<PreferenceScreen xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools">
<PreferenceCategory android:title="@string/pref_general_category_title">
<ListPreference
android:defaultValue="@string/pref_default_language_value"
android:entries="@array/pref_language_list_entries"
android:entryValues="@array/pref_language_list_values"
android:icon="@drawable/ic_translate"
android:key="language_list"
android:summary="@string/pref_default_language_entry"
android:title="@string/pref_language_title"
tools:summary="@string/pref_default_language_entry" />
<ListPreference
android:defaultValue="@string/pref_default_fiat_currency_value"
android:entries="@array/pref_fiat_currency_list_entries"
android:entryValues="@array/pref_fiat_currency_list_values"
android:icon="@drawable/ic_cash"
android:key="fiat_currency_list"
android:summary="@string/pref_default_fiat_currency_entry"
android:title="@string/pref_fiat_currency_title"
tools:summary="@string/pref_default_fiat_currency_entry" />
<ListPreference
android:defaultValue="@string/pref_default_date_format_value"
android:entries="@array/pref_date_format_list_entries"
android:entryValues="@array/pref_date_format_list_values"
android:icon="@drawable/ic_date_range"
android:key="date_format_list"
android:summary="@string/pref_default_date_format_entry"
android:title="@string/pref_date_format_title"
tools:summary="@string/pref_default_date_format_entry" />
<SwitchPreference
android:defaultValue="true"
android:icon="@drawable/ic_calendar_clock"
android:key="24h_switch"
android:summary="@string/pref_24h_switch_summary"
android:title="@string/pref_24h_switch_title" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_support_category_title">
<Preference
android:icon="@drawable/ic_star"
android:title="@string/pref_rate_app_title" />
<Preference
android:icon="@drawable/ic_share"
android:title="@string/pref_share_app_title" />
<Preference
android:icon="@drawable/ic_attach_money"
android:summary="@string/pref_donate_view_summary"
android:title="@string/pref_donate_view_title" />
<Preference
android:icon="@drawable/ic_currency_btc"
android:summary="@string/pref_donate_crypto_summary"
android:title="@string/pref_donate_crypto_title" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_support_about_title">
<Preference
android:icon="@drawable/ic_web"
android:summary="@string/pref_website_summary"
android:title="@string/pref_website_title" />
<Preference
android:icon="@drawable/ic_human_greeting"
android:summary="@string/pref_author_summary"
android:title="@string/pref_author_title" />
<Preference
android:icon="@drawable/ic_github_circle"
android:summary="@string/pref_source_summary"
android:title="@string/pref_source_title" />
<Preference
android:icon="@drawable/ic_file_multiple"
android:title="@string/pref_open_source_title" />
<Preference
android:icon="@drawable/ic_copyright"
android:summary="@string/pref_license_summary"
android:title="@string/pref_license_title" />
<Preference
android:icon="@drawable/ic_info_outline"
android:summary="@string/pref_app_summary"
android:title="@string/pref_app_title" />
</PreferenceCategory>
</PreferenceScreen>
2. สร้างส่วนการตั้งค่า
จากนั้นเราควรสร้างแฟรกเมนต์เปล่าอย่างง่าย — SettingsFragment
ซึ่งควรขยาย PreferenceFragment()
. ส่วนนี้จะสร้างการกำหนดค่าตามความชอบจากทรัพยากร XML ที่เราสร้างขึ้น ในอนาคต ส่วนนี้จะมีวิธีการที่จำเป็นทั้งหมดเพื่อขยายการตั้งค่า XML นอกจากนี้ยังให้การโทรกลับเมื่อการตั้งค่ามีการเปลี่ยนแปลง
class SettingsFragment : PreferenceFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addPreferencesFromResource(R.xml.pref_main);
}
}
3. สร้างกิจกรรมการตั้งค่า
ด้วยส่วนการตั้งค่าพร้อมแล้ว มาสร้างกิจกรรมใหม่ — AppCompatPreferenceActivity
ซึ่งขยาย PreferenceActivity()
. คลาสนี้มีความเข้ากันได้กับอุปกรณ์และเวอร์ชันทั้งหมด
abstract class AppCompatPreferenceActivity : PreferenceActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
delegate.installViewFactory()
delegate.onCreate(savedInstanceState)
super.onCreate(savedInstanceState)
}
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
delegate.onPostCreate(savedInstanceState)
}
val supportActionBar: ActionBar?
get() = delegate.supportActionBar
fun setSupportActionBar(toolbar: Toolbar?) {
delegate.setSupportActionBar(toolbar)
}
override fun getMenuInflater(): MenuInflater {
return delegate.menuInflater
}
override fun setContentView(@LayoutRes layoutResID: Int) {
delegate.setContentView(layoutResID)
}
override fun setContentView(view: View) {
delegate.setContentView(view)
}
override fun setContentView(view: View, params: ViewGroup.LayoutParams) {
delegate.setContentView(view, params)
}
override fun addContentView(view: View, params: ViewGroup.LayoutParams) {
delegate.addContentView(view, params)
}
override fun onPostResume() {
super.onPostResume()
delegate.onPostResume()
}
override fun onTitleChanged(title: CharSequence, color: Int) {
super.onTitleChanged(title, color)
delegate.setTitle(title)
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
delegate.onConfigurationChanged(newConfig)
}
override fun onStop() {
super.onStop()
delegate.onStop()
}
override fun onDestroy() {
super.onDestroy()
delegate.onDestroy()
}
override fun invalidateOptionsMenu() {
delegate.invalidateOptionsMenu()
}
private val delegate: AppCompatDelegate by lazy {
AppCompatDelegate.create(this, null)
}
}
4. สร้างกิจกรรมการตั้งค่า
class SettingsActivity : AppCompatPreferenceActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupActionBar()
fragmentManager.beginTransaction().replace(android.R.id.content, SettingsFragment()).commit()
}
private fun setupActionBar() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
override fun onMenuItemSelected(featureId: Int, item: MenuItem): Boolean {
val id = item.itemId
if (id == android.R.id.home) {
if (!super.onMenuItemSelected(featureId, item)) {
NavUtils.navigateUpFromSameTask(this)
}
return true
}
return super.onMenuItemSelected(featureId, item)
}
}
5. เพิ่มรายการการตั้งค่าไปที่เมนูหลัก
<menu xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
tools:context="com.baruckis.mycryptocoins.MainList.MainActivity">
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>
6. เปิดกิจกรรมการตั้งค่าที่สร้างขึ้นใหม่เมื่อเลือกการตั้งค่าจากเมนูรายการเพิ่มเติม
class MainActivity : AppCompatActivity() {
...
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_settings -> {
startActivity(Intent(this@MainActivity, SettingsActivity::class.java));
return true
}
else -> super.onOptionsItemSelected(item)
}
}
}
7. ระบุกิจกรรมการตั้งค่าที่สร้างขึ้นใหม่ในไฟล์ Manifest ของ Android
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.baruckis.mycryptocoins">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<activity
android:name=".Settings.SettingsActivity"
android:label="@string/title_activity_settings"
android:parentActivityName=".MainList.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.baruckis.mycryptocoins.MainList.MainActivity" />
</activity>
</application>
</manifest>
ขอแสดงความยินดี ในที่สุดคุณสามารถเปิดการตั้งค่าจากรายการเมนูของแถบเครื่องมือได้
การใช้ไลบรารีของบุคคลที่สาม — มุมมองปุ่มพลิกวงกลมสไตล์ Gmail
ตกลง มีความคิดเห็นต่างๆ มากมายเกี่ยวกับการใช้ไลบรารีของบุคคลที่สาม — โค้ดที่สร้างโดยผู้พัฒนารายอื่นที่ไม่ใช่ผู้จำหน่ายดั้งเดิมของแพลตฟอร์มการพัฒนา บางคนหลีกเลี่ยงพวกเขาเนื่องจากไม่ชัดเจนว่าจะนานแค่ไหนและจะได้รับการสนับสนุนได้ดีเพียงใด ในขณะที่คนอื่นใช้เพราะสามารถเร่งกระบวนการพัฒนาได้
การตัดสินใจใช้ควรขึ้นอยู่กับกรณีของคุณ คุณควรตรวจสอบห้องสมุดด้วยตนเองและพิจารณาว่าห้องสมุดมีความยืดหยุ่นเพียงพอที่จะตอบสนองความต้องการทั้งหมดของคุณหรือไม่
สำหรับแอป My Crypto Coins มีสถานการณ์ที่ฉันต้องการสร้างมุมมองภาพวงกลม ภาพนี้ควรแสดงไอคอนสกุลเงินดิจิทัลเฉพาะภายในรูปวงกลม แต่ถ้าไม่มีไอคอน ฉันต้องการแสดงตัวอักษรสามตัวแรกของรหัสสกุลเงินดิจิทัล
นอกจากทั้งหมดที่ฉันต้องการที่จะสามารถเลือกภาพโดยคลิกที่พวกเขา ควรนำเสนอการเลือกเป็นภาพเคลื่อนไหวมุมมองพลิกสั้น
UX ทั้งหมดที่ฉันอธิบายไม่ได้ถูกประดิษฐ์ขึ้นโดยฉันในตอนแรก คุณสามารถหาพฤติกรรมที่คล้ายกันได้ในแอป Gmail และดูดีมาก
แต่เราจะสร้างมันขึ้นมาได้อย่างไร? อันที่จริง มุมมองภาพวงกลมไม่ใช่แม้แต่องค์ประกอบเริ่มต้นที่คุณสามารถหาได้ในจานสีของคอมโพเนนต์ Android Studio
คุณอาจพยายามอย่างหนักและพยายามสร้างทุกอย่างด้วยตัวเอง แต่อาจเสียเวลาและพลังงานไปเปล่าๆ คุณสามารถเลือกใช้หนึ่งในไลบรารีโอเพนซอร์สที่สร้างขึ้นโดยเฉพาะสำหรับสิ่งนั้นแทนได้
สำหรับข้อกำหนด UI/UX ของฉัน ฉันพบห้องสมุดบน GitHub davideas/FlipView หลังจากการสอบสวน ฉันตัดสินใจว่ามันถูกสร้างขึ้นมาอย่างมืออาชีพจริงๆ ง่ายต่อการใช้งานและรองรับนานพอที่จะทดลองใช้ เพื่อเริ่มต้นใช้งาน เราจะทำตามขั้นตอนง่ายๆ เหล่านี้:
1. เพิ่มการพึ่งพา
นำเข้าไลบรารีลงในโครงการของคุณ
dependencies {
implementation 'eu.davidea:flipview:1.1.3'
}
2. ใช้เลย
กำหนดค่า FlipView ด้วยแอตทริบิวต์แอปปกติและแบบกำหนดเองของ Android มันไม่ง่ายเหรอ?
<android.support.v7.widget.CardView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
...
<eu.davidea.flipview.FlipView
android:id="@+id/item_image_icon"
style="@style/FlipView"
android:clickable="true"
android:focusable="true"
app:layout_constraintBottom_toTopOf="@+id/item_ranking"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
...
</android.support.v7.widget.CardView>
ดังนั้นอย่าคิดค้นล้อใหม่ พิจารณาใช้ไลบรารี่ก่อนเสมอเพื่อให้ผลลัพธ์เร็วขึ้น และถ้าโปรเจ็กต์ของคุณยุ่งเหยิง มันไม่ใช่การตำหนิไลบรารี่เก่าแต่คุณจะจัดโครงสร้างโค้ดของคุณได้ดีเพียงใด หากโครงการของคุณเป็นแบบโมดูลาร์เพียงพอ ก็จะไม่มีปัญหา แต่นั่นเป็นหัวข้อแยกต่างหาก และฉันจะพูดถึงสถาปัตยกรรมโครงการในโพสต์บล็อกในภายหลัง
รองรับหลายภาษาด้วย RTL
เมื่อฉันตัดสินใจสร้างแอปนี้ ฉันตั้งเป้าหมายให้ตัวเองไม่เพียงแค่สร้างแอปด้วย UI ภาษาอังกฤษเริ่มต้นเท่านั้น แต่ยังต้องแปลเป็นภาษาลิทัวเนียเป็นภาษาแม่ของฉันด้วยตั้งแต่เริ่มพัฒนา
เป้าหมายนี้ทำให้ฉันได้เรียนรู้เกี่ยวกับการแปลเป็นภาษาท้องถิ่นใน Android สิ่งที่ฉันพบคือการเพิ่มการรองรับหลายภาษานั้นง่ายมาก ดังที่ได้กล่าวมาแล้ว ก่อนอื่นคุณต้องแยกสตริงทั้งหมดของคุณเป็นไฟล์ strings.xml จากนั้นคุณสามารถเปิดเครื่องมือแก้ไขการแปลภายใน Android Studio ซึ่งจะทำให้คุณสามารถเพิ่มการรองรับภาษาใหม่ได้
คุณจะเห็นว่าอินเทอร์เฟซนั้นใช้งานง่ายมาก ตอนนี้ คุณต้องแปลแต่ละสตริงจากไฟล์ strings.xml เป็นภาษาใหม่ ไฟล์ใหม่จะถูกสร้างขึ้นโดย IDE ในไดเร็กทอรีแยกต่างหาก ตัวอย่างเช่น สำหรับภาษาลิทัวเนีย ก็คือ values-lt/strings.xml
. แค่นั้นแหละ! ?
หากคุณเปลี่ยนภาษาของระบบอุปกรณ์ Android เป็นภาษาที่คุณเพิ่งแปลไป จากนั้นเรียกใช้แอปของคุณ UI ทั้งหมดจะได้รับการอัปเดตเป็นคำแปลของคุณโดยอัตโนมัติ นอกจากนี้ สำหรับแอป My Crypto Coins ในภายหลัง ฉันวางแผนที่จะเพิ่มความสามารถในการสลับภาษาในขณะใช้งาน นั่นคือเหตุผลที่คุณจะสังเกตเห็นตัวสลับภาษาในหน้าจอการตั้งค่า
การแปลแอปของคุณเป็นภาษาต่างๆ จะทำให้ผู้ชมของคุณกว้างขึ้นอย่างแน่นอน ทำไมไม่ลองเพิ่มการสนับสนุนสำหรับภาษาพิเศษบางภาษาที่เขียนจากขวาไปซ้าย (RTL) เช่น อาหรับ ฮิบรู หรือเปอร์เซีย
จริงๆแล้วการเพิ่มการสนับสนุน RTL นั้นไม่ยากเลย เพียงเพิ่มแอตทริบิวต์ support ลงในไฟล์รายการของคุณ:
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.baruckis.mycryptocoins">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
</application>
</manifest>
ขอแสดงความยินดี แอปของคุณรองรับ RTL แล้ว อย่างไรก็ตาม คุณไม่สามารถวางใจอย่างสุ่มสี่สุ่มห้าได้ว่าทุกอย่างจะทำงานได้อย่างถูกต้องในทันที คุณควรตรวจสอบว่าตัวเองรองรับได้ดีเพียงใด โดยเลือกภาษา RTL ภาษาใดภาษาหนึ่งเป็นภาษาหลักของอุปกรณ์
เคล็ดลับบางประการสำหรับ RTL:
- ในเลย์เอาต์ทั้งหมดของคุณ คุณจะต้องแทนที่ทั้งหมด
Left
และRight
คุณสมบัติเลย์เอาต์ด้วยStart
และEnd
เทียบเท่า. เช่นandroid:paddingLeft
ควรแทนที่ด้วยandroid:paddingStart
. - หากคุณไม่มี drawable พิเศษสำหรับ RTL บางทีคุณอาจต้องการจำลองสิ่งปัจจุบันของคุณด้วย
autoMirrored
พิเศษ แอตทริบิวต์
<vector xmlns:android="https://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="@color/colorForPreferenceIcon"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M1.5,4V5.5C1.5,9.65 3.71,13.28 7,15.3V20H22V18C22,15.34 16.67,14 14,14C14,14 13.83,14 13.75,14C9,14 5,10 5,5.5V4M14,4A4,4 0 0,0 10,8A4,4 0 0,0 14,12A4,4 0 0,0 18,8A4,4 0 0,0 14,4Z" />
</vector>
- หากมีสถานที่บางแห่งที่คุณจำเป็นต้องมี LTR แทน RTL คุณก็สามารถทำได้เช่นกัน ตัวอย่างเช่น หากต้องการบังคับเลย์เอาต์ใดๆ ให้ LTR เพียงเพิ่ม
android:layoutDirection="ltr"
สู่มุมมองนั้น หากคุณต้องการบังคับทิศทางข้อความในมุมมองข้อความมากกว่าใช้android:textDirection="ltr"
.
อีกอย่าง เมื่อใช้ Translations Editor มีฟีเจอร์ที่มีประโยชน์มากในการสั่งซื้อบริการแปลแบบมืออาชีพ แม้ว่าโดยส่วนตัวแล้วฉันไม่รู้อะไรเลยเกี่ยวกับภาษาฮิบรู แต่ฉันก็ยังตั้งเป้าหมายที่จะเพิ่มการสนับสนุนเป็นภาษา RTL ตัวอย่างสำหรับโครงการ My Crypto Coins ดังนั้นคุณลักษณะนี้จึงดูเหมือนเป็นความคิดที่ดีที่จะลอง ฉันสั่งการแปลจากภาษาอังกฤษเป็นภาษาฮิบรูได้สำเร็จโดยตรงจาก IDE ด้วยการคลิกเพียงไม่กี่ครั้ง
ความคิดสุดท้าย
ในส่วนที่สองของซีรีส์นี้ เราได้สร้างเลย์เอาต์ UI ทั้งหมดด้วยโค้ดเริ่มต้นบางส่วนตามการจำลองแบบละเอียด ฉันไม่ต้องการลงรายละเอียดมากเกินไปในแต่ละหัวข้อเพื่อไม่ให้คุณสับสน เป้าหมายของฉันคือแสดงให้คุณเห็นวิธีมองภาพใหญ่ วิธีเน้นรายละเอียดเล็ก ๆ ก่อน และหลีกเลี่ยงข้อผิดพลาดที่มีราคาแพงในภายหลัง
หากคุณพบว่ามีบางสิ่งที่ยังไม่ครอบคลุมเพียงพอ ให้ใช้มันเป็นจุดเริ่มต้นในการทำวิจัยของคุณเอง มีแหล่งข้อมูลดีๆ มากมายในเว็บให้เรียนรู้อยู่เสมอ ?
ที่เก็บ
คุณสามารถค้นหาเลย์เอาต์และโค้ด XML ทั้งหมดที่สร้างขึ้นสำหรับส่วนนี้ได้ที่นี่:
ดูซอร์สบน GitHub
อาชิอู! ขอบคุณที่อ่าน! ฉันเผยแพร่โพสต์นี้สำหรับบล็อกส่วนตัวของฉัน www.baruckis.com เมื่อวันที่ 14 พฤษภาคม 2018