set user variables กับ system variables

ลูกศิษย์ชื่อหนึ่ง โพสต์ถามใน สมาคมโปรแกรมเมอร์ไทย เกี่ยวกับ C:\> npx react-native run-android ที่ต้องตั้งค่า JAVA_HOME แต่ผมสนใจเรื่องการตั้งค่าใน System variables และ User variables จึงเรียบเรียงมาเล่าสู่กันฟัง ซึ่งการเข้าไปตั้งค่านั้น สั่งผ่าน command line ด้วย sysdm.cpl แล้วเข้า Advanced มองหา Environment variables… ซึ่งตัวแปรที่ตั้งขึ้นนั้น มี 3 สภาพแวดล้อม (Environment) คือ 1) ตั้งขึ้นขณะอยู่ใน Current shell ที่กำลังเปิดใช้งานอยู่นั้น และหายไปเมื่อปิด shell ลง 2) ตั้งตัวแปรใน System variables จะมีตัวแปรและค่าให้ใช้ในทุกเชล และทุกยูเซอร์ ถ้ามีตัวแปรซ้ำกับที่ประกาศใน User variables ก็จะใช้ในส่วนที่ผู้ใช้เป็นผู้ประกาศขึ้นสำหรับตนเอง 3) ตั้งตัวแปรใน User variables จะใช้เฉพาะกับ user ที่ sign in ในระบบขณะนั้น ผู้ใช้คนอื่นก็จะไม่เห็นตัวแปรนั้น ซึ่งตัวแปรแบบนี้ไม่ได้เกี่ยวว่าจะอยู่ shell แบบไหน เพราะได้ค่าเหมือนกันทั้งใน user หรือ administrator หรือ powershell เช่น ตัวแปร burin มีค่าเป็น u ก็จะเป็นเช่นนั้น เมื่อเรียกใช้โดย user ปัจจุบัน แต่ถ้า sign out และมีสมาชิกคนอื่นเข้ามาในระบบ แล้วใช้ตัวแปรที่สร้างใน System variables ค่าของ burin ก็จะเป็น s ตามตัวอย่างในภาพ

อีกกรณีหนึ่ง คือ การจัดการกับ variable ใน shell หนึ่ง จะไม่มีผลไปยัง shell อื่น จะลบหรือเปลี่ยนค่า burin เมื่อเปิด shell ใหม่ ระบบก็จะ load ค่าอีกครั้งจากระบบใหม่เข้ามาใช้ใน shell ไม่ว่าจะเป็น user variables หรือ system variables ก็ตาม เพราะแต่ละ shell มีหน่วยความจำเก็บตัวแปรเป็น local variables ของตนเอง หรือแม้แต่การเข้าไปเปลี่ยนใน sysdm.cpl ก็จะไม่กระทบค่าตัวแปรใน shell ที่กำลังเปิดอยู่ หากต้องการค่า variable ที่มีการเปลี่ยนแปลง ก็ต้องปิด shell แล้วเปิดขึ้นมาใหม่

มีอัลบั้มภาพที่เกี่ยวข้อง
ที่ http://www.thaiall.com/reactnative/

#เล่าสู่กันฟัง 63-006 พลัดหลงกัน แต่หากันจนเจอ ด้วยไอที

เมื่อเดินทางท่องเที่ยว
อาจด้วยโอกาสจาก #ชิมช้อปใช้
ที่ต้องไปต่างจังหวัด ไปเดิน ไปกิน ไปใช้จ่าย
ต่างบ้านต่างเมืองที่ไม่คุ้นชิน
มองไปทางไหนก็ไม่รู้จัก คนต่างเมืองเพียบ
ไม่อู้ภาษาแถวกาดที่อู้อู้อยู่ ฟังบ่าฮู้เรื่องเลย

แต่เทคโนโลยีช่วยได้
ตอนขับรถไปถึงปากทางเข้าตลาด
คนมากมาย รถก็ไม่มีที่จอด คนในรถก็อยากลง
พอลงแล้ว เอารถไปจอด แล้วค่อยเดินหากัน
นัดสถานที่ก็ไม่ได้ นัดเวลาก็ไม่ดี เดินเพลิน

จึงใช้ facebook messenger หรือ line
แชร์ตำแหน่ง #sharelivelocation
ทำให้รู้ว่าจอดรถที่ไหน เพื่อนอยู่ไหน
แต่ละคนอยู่ตรงไหนในระแวกนั้น
แล้วก็เดินไปหา ตำแหน่งปัจจุบัน
ก็จะเคลื่อนที่ตามไปด้วย
หากันจนเจอในที่สุด
หรือประยุกต์ใช้เรื่องติดตามตำแหน่งได้

คนที่เค้าเดินทางไปเป็นหมู่คณะเป็นประจำ
คงใช้ในทุกทริป เช่น เหตุการณ์ในหนัง
เรื่องกวนมึนโอ ที่พระเอกตกทัวร์
ที่นักท่องเที่ยวพลัดหลง ก็คงไม่เกิดขึ้น

https://www.iphonemod.net/how-to-share-realtime-location-on-fb-messager.html

https://www.androidpit.com/whatsapp-tips-tricks-share-live-location

App wordpress ช่วยเขียน blog

เล่าสู่กันฟัง 62-289

แอพ wordpress คือ โปรแกรมสำหรับเชื่อมต่อกับบัญชีระบบ wordpress หากมีหลายไซต์ หรือมีหลายบัญชีในหลายไซต์ ดังนั้นการเขียน blog ผ่าน wordpress ผ่านแอพ จะช่วยให้เขียนบันทึกได้ง่ายขึ้น เพราะแอพเดียวเข้าได้ทุกไซต์ ออกแบบมาให้ทำงานได้ดีบนสมาร์ทโฟน ที่มีขนาดหน้าจอจำกัด เหมือนเฟสบุ๊คที่มีแอพ ช่วยให้ทำงานได้เร็วกว่า แต่หากมีฟังก์ชันใดที่ไม่มีบริการในแอพ ก็เข้าผ่าน browser ในโหมด desktop แทน
https://wordpress.org/support/topic/403-error-after-changing-a-setting-with-xmlrpc/

https://m.facebook.com/story.php?story_fbid=10158028917172272&id=350024507271

วิวปีหนึ่ง ถามติดตั้ง CMS ด้วยความอยากเรียนรู้

ในชั่วโมง Home room – 27 มี.ค.62
ที่ อ.แนน นัดเด็ก ๆ คุยกัน ที่ห้องแล็บคอม
คุยกันเรื่องนู้นนั้นนี้ เกี่ยวกับกิจกรรมในระดับหลักสูตร
พอมีเวลา
ผมก็ชวนคุยเรื่องการเรียนรู้ และชวนที่จะลงไปเรียนรู้หน่วยงาน
คอม กับนิก ลง joomla เสร็จหลายวันแล้ว
ส่วนวิว กับมิ้ม ก็พูดถึงการลงเซิร์ฟและ joomla
พูดถึงการสร้างฐานข้อมูลผ่าน phpmyadmin
ตอนนี้ก็รอน้องแบล็ค หนึ่ง กิม และพี่ปีสองมาพูดคุยด้วย
เป็นกิจกรรมนอกหลักสูตร เพราะไม่มีวิชาเรียนในระดับปีหนึ่ง
แต่เค้าสนใจการเรียนรู้
ที่น่าจะต้องหาเวลาเรียนรู้กันตั้งแต่ปีหนึ่งได้แล้ว


เมื่อวาน 28 มี.ค.62 พี่ปี 4
ก็เอา code OCR เขียนด้วย React Native ทำงานบน Expo
ซึ่งการเขียน Javascript สร้าง app บน Mobile นั้น
ก่อนหน้านี้ ผมก็ไม่ได้สนใจเอาซะเลย (เดี๋ยวนี้มีหลายค่าย)
เพราะเป็นสาวกของ Android Studio : Java มานาน
แต่ก็ไม่ได้ลงเต็มที่ เข้าไปสัมผัสงาน Mobile เพียงเล็กน้อย
พี่ปี 4 เอา code มาให้ทดสอบ
พบว่า น่าสนใจ React Native เขียนง่ายไม่กี่ร้อยบรรทัด
และพี่บอลก็เคยเล่าให้น้องฟังว่า
เป็นชุดซอฟต์แวร์ที่ง่ายในการพัฒนา mobile app


ลักษณะของ React native on expo
ที่พี่ปี 4 ทำเรื่อง OCR น่าสนใจดังนี้

1. เขียนบน pc แต่ทดสอบบน mobile ได้ง่าย
เช่น การเรียกผ่าน link ผ่าน QR code ในเครือข่ายเดียวกัน
2. อัพโหลดเข้า expo.io แล้วเปิดผ่าน mobile
เช่น https://expo.io/@thaiall/myapp1
หรือ exp://exp.host/@thaiall/myapp1
3. เปิดผ่าน browser ตามลิงค์ใน expo.io
มี appetize-simulator ช่วยจำลอง mobile
4. สำหรับเจ้าของ app สามารถโหลด .apk
มาติดตั้งได้ โดยโหลดจากหน้า builds
พบที่ https://expo.io/@thaiall/myapp1/builds
#เล่าสู่กันฟัง 62-057

หา driver ให้กับอุปกรณ์เก่าไม่พบ มีทั้งผิดหวัง และสมหวัง

Wireless USB Adapter
Wireless USB Adapter

มีเครื่อง PC ที่ไม่ได้เชื่อม Internet ผ่านสาย LAN
แต่มี Wireless USB Adapter ตัวเก่าตัวหนึ่ง
เอามาใช้ก็พยายามติดตั้งไปตามปกติ แบบ Off-line
พบว่า Driver ไม่ตรง หรือไม่พบที่ใช้งานได้
เล่าถึงขั้นตอน ดังนี้
1. เอายี่ห้อ และรุ่น
ไปค้นจาก website เจ้าของอุปกรณ์
ก็ไม่มี driver ให้ download เพราะอุปกรณ์เก่ามาก
เลิกดูแลลูกค้าที่ใช้อุปกรณ์เก่า
2. หาจาก google.com หลายตัว
*เริ่มมีหวัง
ลอง download ที่น่าจะใช้
ก็ไม่มีตัวไหนใช้งานได้
* ผิดหวังหลายรอบ เพราะน่าจะได้สักตัว ก็ไม่ใช่สักตัว
3. สงสัยว่าอุปกรณ์จะเสีย * เริ่มสิ้นหวัง
เปลี่ยนไปยังเครื่องที่ online
แล้วใช้ search driver แบบ online
พบว่า install hardware ได้ปกติ และใช้งานได้
* สมหวังครับ ยิ้มแป้นเลย แต่ไม่ใช่เครื่องนี้
4. เอาชื่ออุปกรณ์ที่ install hardware ได้แล้ว
ไปค้นหาจาก website ของ microsoft.com
แล้วพบแฟ้ม .cab หลายแฟ้ม ก็ download ที่น่าจะใช้มา 3 ตัว
* ก็มั่นใจว่าชื่อตรงแล้ว มาเลยหลายตัว กันพลาด
5. ใช้ winrar ทำ extract driver ที่เป็น .cab ทุกแฟ้ม
เป็น folder ที่น่าจะใช่ทุกตัว
ลุ้นไปทีละตัว สุดท้ายก็ install สำเร็จ จากที่ได้มา 1 ตัว

ภาคผนวก ก. เรื่องนี้สอนให้รู้ว่า
* มีผิดหวัง ย่อมมีสมหวัง และมีผิดหวังครั้งใหม่ วน ๆ กันไป
เมื่อมาทำงานสายไอที

ภาคผนวก ข. ที่มา
ผมถอน Fiber optic ออก ประหยัดเดือนละหลายร้อย
ต่อไปใช้ Net ความเร็ว 256 Kbps จาก 3G
ที่แชร์ Hotspot จาก Smartphone ก็พอแล้ว
ทำให้เครื่อง PC ที่เคยต่อสาย Lan เข้า Switch
เกิดต่อ Net ไม่ได้ขึ้นมากระทันหัน
http://www.thaiall.com/mis/mis05.htm

องค์การโทรศัพท์ หรือ บริษัท ทีโอที จำกัด (มหาชน)

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

ภาพโทรศัพท์ phone
ภาพโทรศัพท์ phone

https://www.facebook.com/english.jokes/

TOT เป็นรัฐวิสาหกิจ
ก่อตั้ง 24 กุมภาพันธ์ 2497 เป็น องค์การโทรศัพท์แห่งประเทศไทย
และแปลงสภาพเป็น บมจ.ทีโอที เมื่อ 31 กรกฎาคม 2545
ทำหน้าที่ให้บริการโทรคมนาคมและธุรกิจอื่นที่เกี่ยวเนื่อง
http://www.tot.co.th/Corporate/

ประวัติของ TOT
– 2424 โทรศัพท์เข้าประเทศไทย สมัย ร.5 ดูแลโดยกรมกลาโหม ใช้แจ้งข่าวเรือเข้า-ออก
– 2429 โอนกิจการจาก กรมกลาโหม ไป กรมไปรษณีย์โทรเลข เปิดบริการมีผู้เช่าประมาณ 60 คน
– 2450 ตั้งชุมสายกึ่งอัตโนมัติ ที่โทรศัพท์กลางวัดเลียบ มีพนักงานต่อสายระหว่างผู้เช่า
– 2465 เพิ่มชุมสายโทรศัพท์แห่งที่สอง คือ โทรศัพท์กลางบางรัก รองรับ 900 เลขหมาย
– 2470 วางเคเบิลเชื่อมต่อวัดเลียบ-บางรัก เพิ่มเป็น 1422 เครื่อง
– 2471 ให้บริการโทรศัพท์ทางไกล เชื่อม กทม. ธนบุรี สมุทรปราการ นนทบุรี นครปฐม
– 2478 เริ่มใช้ชุมสายระบบ Step by step อุปกรณ์จากอังกฤษ ทำให้หมุนหน้าปัดถึงกันโดยตรง
ได้ติดตั้งที่โทรศัพท์กลางวัดเลียบ 2300 เลขหมาย และโทรศัพท์กลางบางรัก 1200 เลขหมาย
เปิดบริการ 24 กันยายน 2480 และเพิ่มชุมสายเพลินจิต และชุมสายสามเสน
– 2480 ติดตั้งชุมสายอัตโนมัติครั้งแรก เปลี่ยนเป็นแบบหน้าปัดแบบหมุน ใช้เลข 5 ตัว หมุนถึงกันเองได้
– 2497 สถาปนาเป็นองค์การโทรศัพท์แห่งประเทศไทย เป็นรัฐวิสาหกิจ สังกัดกระทรวงคมนาคม
เมื่อ 24 กุมภาพันธ์ 2497 โดยแยกจากกองช่างโทรศัพท์ กรมไปรษณีย์โทรเลข มีพนักกงาน 732 คน
– 2502 สั่งซื้อชุมสายอัตโนมัติระบบ Cross bar จากสวีเดน ที่ชุมสายชลบุรี 1000 เลขหมาย
– 2503 รับโอนโทรศัพท์ในส่วนภูมิภาคจากกรมโปรษณีย์โทรเลข
ครั้งแรก 10 ชุมสาย จำนวน 1600 เลขหมาย
ครั้งที่สอง 37 ชุมสาย จำนวน 8100 เลขหมาย
– 2507 ติดตั้งชุมสาย Cross bar ในกรุงเทพ
และรับโอนจากทุกภาคมาในความรับผิดชอบครอบคลุมบริการโทรศัพท์ทางไกลทั่วประเทศ
– 2517 เปลี่ยนเลขหมายเป็น 6 หลัก
– 2518 ให้บริการโทรศัพท์ทางไกลอัตโนมัติ ไม่ต้องใช้พนักงานต่อระหว่างเชียงใหม่-กรุงเทพ
เมื่อ 9.05 วันที่ 1 กันยายน 2518
– 2519 เมื่อ 24 เมษายน เปลี่ยนใช้เลขหมายโทรศัพท์ จาก 5 และ 6 ตัว เป็น 7 ตัวในนครหลวง
และในภูมิภาคเปลี่ยนเป็น 6 ตัวทั้งหมด
– 2520 เริ่มใช้เครื่องโทรศัพท์แบบกดปุ่ม ในเขตนครหลวง
– 2521 ให้บริการโทรศัพท์ไร้สาย (Multi access radio telephone)
บริการในรัศมี 30 กิโลเมตร รอบสถานีฐานนั้น
– 2522 เปิดบริการโทรศัพท์สาธารณะ แบบไม่มีผู้ดูแล
– 2523 เปิดบริการโทรศัพท์ทางไกลอัตโนมัติทั่วประเทศ
– 2525 ให้บริการโทรศัพท์สาธารณะทางไกลอัตโนมัติ ในเขตโทรศัพท์นครหลวง เป็นครั้งแรก
– 2526 เปิดใช้ระบบ SPC (Stored program control) ที่ชุมสายภูเก็ต และบริการทางไกลไทย-มาเลเซีย
– 2527 ให้บริการโทรศัพท์ต่างประเทศระบบอัตโนมัติ สำหรับผู้เช่าในเขตกรุงเทพฯ
– 2529 เปิดให้บริการโทรศัพท์เคลื่อนที่ระบบ NMT (Nordic mobile telephone) 470 MHz
– 2530 เปิดให้ผู้เช่าสามารถซื้อเครื่องโทรศัพท์ได้เอง
– 2531 เปิดบริการพิเศษ SPC อาทิ ประชุมทางโทรศัพท์ บริการเลขหมายย่อ บริการรับสายซ้อน
และเปิดวงจรเคเบิลใต้น้ำเชื่อมต่อไทย-มาเลเซีย
– 2532 เชื่อมเครือข่ายด้วยเคเบิลใยแก้ว และไมโครเวฟ
– 2533 เปิดบริการโทรศัพท์เคลื่อนที่ระบบความถี่ 900 MHz และอีกหลายรูปแบบ
– 2534 เปิดสัมปทานโทรศัพท์สาธารณะแบบใช้บัตร (Cardphone) ในเขตนครหลวง
– 2535 เปิดบริการวิทยุสื่อสารเคลื่อนที่เฉพาะกลุ่มธุรกิจ (Trunk mobile radio)
– 2536 เปิดบริการโทรศัพท์สาธารณะทางไกลต่างประเทศชนิดหยอดเหรียญ
– 2537 ทดลองเปิดบริการ วิดีสาร (Videotex)
– 2538 ให้บริการชำระค่าบริการ โดยหักบัญชีเงินฝากทั่วประเทศ
– 2539 เมื่อ 22 เมษายน เปิดให้บริการโทรศัพท์รหัสส่วนตัว Pin phone 108 ในเขตนครหลวง
– 2540 เปลี่ยนจากระบบ Cross bar ที่เหลือเป็นแบบ SPC (แบบกดปุ่ม) ทั้งหมด
– 2541 เปิดให้บริการโทรศัพท์สาธารณะแบบใช้ TOT Card
มีรายละเอียการพัฒนาในแต่ละปีอย่างต่อเนื่อง ไปหาอ่านกันได้ครับ
http://www.tot.co.th/Corporate/HISTORY.ASPX

ที่บ้านก็ใช้ ADSL ของ TOT
เคยเขียน blog ไว้หลายเรื่องเลย อาทิ
– router:ZTE ที่ TOT ให้ตอนติด FTTx
– เล่าปัญหาลืมรหัสผ่าน adsl router ของ tot
– ทดสอบหลังใช้ @platinumcyber
– ทดสอบ bestcyber ก่อนใช้ platinumcyber
– TOT Wi-Ti ที่ Central Plaza Lampang
http://www.thaiall.com/blog/tag/tot/

#AndroidStudio ตอนที่ 11 แอพสำหรับ Tablet(Wide)/Smartphone(Narrow) มีตัวเลือกรายการด้านซ้าย รายละเอียดด้านขวา ถ้าจอกว้างพอ

#AndroidStudio ตอนที่ 11 แอพสำหรับ Tablet(Wide)/Smartphone(Narrow) มีตัวเลือกรายการด้านซ้าย รายละเอียดด้านขวา ถ้าจอกว้างพอ

<introduction>
อารัมภบท
การเขียน App สักตัว ที่ต้องการให้มี ซีกซ้าย (Left Pane) เป็นรายการตัวเลือก และซีกขวา (Right Pane) เป็นรายละเอียดหลังคลิ๊กไปที่รายการ ทาง Android เข้าใจเรา ได้เตรียม Template (อ่านได้จาก Add Code from a Template ) มาให้เราเลือก 12 แบบ พบว่า Main/Detail Flow เป็นแบบที่แบ่งจอภาพเป็น Two section สำหรับจอแบบ Wide screen แต่จะหดให้ทำงานกับ One section หากเป็น Narrow screen ซึ่งเค้ากำหนดว่า Wide screen คือ 900dp และผมใช้ Smartphone ก็จะไม่มีโอกาสได้เห็นแบบ 2 section แต่ใน code หากปรับชื่อ folder เป็น 600 dp ก็ทำให้ app รองรับการแสดงผลแบบ Main/Detail Flow บน Smartphone ได้

การเรียนรู้การทำงานของ Template นี้ ก็ต้องหา Activity เข้าไปใส่ แล้วค่อยแกะค่อยไซร้ไป ไม่งั้นจะให้พิมพ์ Hello world! กันทุก Project ก็คงจะจืดแยเลย จึงใส่ตัวเลือกเข้าไป 6 รายการ คือ API Level, Security_patch, width & height, IP Address, Date and Time และ Webview เมื่อต้องทำให้แต่ละกิจกรรมทำงานได้ พบปัญหาว่า บางกิจกรรมใช้ method ใน Dummycontent.java ไม่ได้ แก้ไขโดยไปใส่ใน Activity หลัก ซึ่งปัญหาที่พบบ่อยมี 2 สาเหตุ คือ 1) ฟังก์ชันนั้นต้องเรียกใช้ Context ของ Activity แต่ไม่มีให้ใช้ในคลาสนั้น 2) การเรียกใช้ฟังก์ชัน ไม่สามารถใช้ได้หากอยู่ใน method แบบ static จึงต้องย้ายงานไปทำใน Activity หลัก อาทิ MainActivity.java แล้วเก็บเป็นตัวแปรให้อ้างอิงได้ เมื่อ Dummy ต้องการใช้ ก็อ้างอิงเป็นวัตถุใน Dummy แล้วนึกไปใช้ได้ แต่ Project นี้มี Activity หลักอยู่ใน ItemListActivity.java

ระหว่างพัฒนา และทดสอบ ได้พบกับคำว่า Unfortunately บ่อยเลย เพราะการใช้ method ในที่ห้ามใช้ ระบบปฏิบัติการไม่อาจดำเนินการตามที่คาดไว้ แต่ Build APK ผ่าน ไม่มีปัญหานะครับ ปัญหาไปเกิดตอนประมวลผล ก็ต้องแก้ไขกันไป เพราะเงื่อนไขเยอะมาก หากันจนเจอ หรือหากันให้เจอ เมื่อต้องเจอปัญหาในแต่ละครั้ง

สรุปกระบวนการได้ 13 ขั้นตอน ประกอบด้วย 1) สร้าง Project เลือก Template แบบ Master/Detail Flow 2) ทำให้ item ใน list มีกิจกรรม 3) เพิ่มเกิจกรรมให้ตัวเลือกแต่ละตัว ใน DummyContent.java 4) การได้ ipaddress ต้องปรับ AndroidManifest.xml 5) สร้าง WebView ชื่อ aboutus.xml รับ HTML Tag 6) การเพิ่ม layout แบบ WebView แทน TextView จำนวน 1 ตัวเลือก 7) การหาขนาด Width และ Height ของจอภาพ 8) การหาค่า IP Address 9) การหาวันเวลาของเครื่อง 10) การหาเลขรุ่น API ของ Android ที่มีในโทรศัพท์แต่ละเครื่อง 11) การส่งค่าเข้าตัวแปรแบบตัวเลข และตัวอักษรใน string 12) การอ้างอิงชื่อ id, string, layout, drawable แบบอ้างอิงด้วยตัวแปร 13) การติดตั้ง Android 7.1 บน VirtualBox


ปล. แฟ้ม Project ผมบีบไว้ และแชร์ให้ Download ทั้ง .rar และ .apk ไปทดสอบกัน
ที่ http://www.thaiall.com/android (ผ่าน 4shared.com)

</introduction>
<definition>
นิยามศัพท์

  1. Template คือ แบบฟอร์มที่ยังไม่ได้ใส่เนื้อหา แต่มีเค้าโครง (Layout) หรือกิจกรรม (Activity) ที่จำเป็นมาให้แล้ว ซึ่ง Android มีให้เลือก 12 แบบ สามารถนำมาปรับแต่งเสมือนกับโครงงานที่สร้างขึ้นใหม่ แต่เทมเพลตจะช่วยล่นระยะเวลาในการพัฒนาระบบในระยะแรกให้สั้นลง แทนการเริ่มต้นจาก 0 หรือการนับ 1 ใหม่
  2. Unfortunately คือ ปัญหาที่ไม่คาดหวัง แต่มาปรากฎบนหน้าจออุปกรณ์ของเราได้ ในกรณีที่เกิดขึ้นจากการติดตั้งและใช้แอพที่ยังอยู่ในระหว่างพัฒนา ก็ลบแอพ (Uninstall) แล้วกลับไปไล่ดูเงือนไขของ command หรือ method หรือ class ที่เรียกใช้ อาจใช้บาง method ที่ใหม่เกินกว่า API ในเครื่องจะรองรับ หรือเก่าเกินไป หรือความไม่เข้ากับของการใช้คำสั่ง แต่ถ้าเป็น App ที่พัฒนา และใช้งานมาแล้วระยะหนึ่ง มีคำแนะนำให้ Clear cache and data หรือ ลบ App แล้วลงใหม่ หรือ Factory reset เป็นต้น

</definition>

กำลังเล่าเรื่อง การใช้โปรแกรม Android Studio สู่เพื่อนนักพัฒนา ผ่าน Blog

<process>
กระบวนการในการพัฒนา APP
เพื่อให้ได้แอพที่แสดงผล Main กับ Detail แยกกัน และแสดงผลต่างกันกับอุปกรณ์แบบ Wide screen และ Narrow screen
มีขั้นตอน ดังนี้

1. สร้าง Project เลือก Template แบบ Master/Detail Flow
ตั้งชื่อให้ project ว่า mainanddetail
เป็นตัวอย่างโครงงานที่น่าสนใจ สามารถนำมาปรับเป็นแอพที่ใช้งานจริงได้
หากใช้กับ Narrow screen จะมีเพียง one screen
หากใช้กับ Wide screen จะแบ่งการทำงานเป็น 2 Section
คือ ซีกซ้ายสำหรับรายการเมนู (Option List) และซีกขวาสำหรับรายละเอียดข้อมูล (Detail)
มีแฟ้มน่าสนใจ 9 แฟ้มที่จะเล่าสู่กันฟัง ดังนี้
https://inducesmile.com/android/android-fragment-masterdetail-flow-tutorial-in-android-studio/

1.1 สำรวจแฟ้ม AndroidManifest.xml
พบว่าใน <application> ได้กำหนด activity ไว้ 2 section
เพื่อเรียก .ItemListActivity และเรียก .ItemDetailActivity
โดย .ItemDetailActivity ที่มี parent คือ .ItemListActivity”
แสดงว่า 1) ItemListActivity.java คือ Activity หลัก
และทำงานคู่กับ 2) ItemDetailActivity.java อย่างที่เรียกว่าแยกกันไม่ออกทีเดียว
จะเห็นว่างานเริ่มจากการเรียก 2 Activity แต่จะแสดง Layout จากทั้ง 2 หรือไม่
ขึ้นกับว่าจอภาพที่ใช้เป็นแบบ Wide หรือ Narrow

1.2 สำรวจ Activity ที่ 1 แฟ้ม ItemListActivity.java
พบว่าใน oncreate ได้สั่ง setContentView(R.layout.activity_item_list);
ซึ่งจะไปเรียกให้ Layout แบบ CoordinatorLayout ที่มีอะไรหลายอย่างทำงานร่วมกัน
Activity นี้ควบคุมงานทางด้านซ้าย (Left Pane) คือ รายการตัวเลือก

1.3 สำรวจ Layout ที่ 1 แฟ้ม activity_item_list.xml
โครงร่างหลักสำหรับการวางวัตถุในด้านซ้าย (Left Pane)
มี Root Layout เป็น CoordinatorLayout
ที่ใช้ AppBarLayout กับ FloatingActionButton
ซึ่งพบได้ใน Template แบบ Basic Activity ที่อธิบายในตอนที่ 9 ข้อ 1
แล้วเรียก Layout อื่นให้ทำหน้าที่แสดงตัวเลือกผ่าน FrameLayout และ include
พบว่ามี Layout structure ดังนี้

<CoordinatorLayout>
 <AppBarLayout>
 <Toolbar />
 </AppBarLayout>
 <FrameLayout>
 <include layout="@layout/item_list" />
 </FrameLayout>
 <FloatingActionButton />
 </CoordinatorLayout>

1.4 สำรวจ Layout ที่ 2 แฟ้ม activity_item_detail.xml
โครงร่างหลักสำหรับการวางรายละเอียดในด้านขวา (Right Pane)
หรือเป็น Full Parent หากทำงานบน Narrow Screen
มี Root Layout เป็น CoordinatorLayout เช่นกัน
จะทำหน้าที่แสดงข้อมูลด้านขวาสำหรับจอภาพที่กว้างไม่น้อยกว่า 900 dp
แต่จะเป็น full screen แทน activity_item_list.xml หากน้อยกว่า 900 dp
– การแสดงเนื้อหามีทำงานกับ fragment แล้วนำไปรวมกันใน Layout
ซึ่งมีความสัมพันธ์ระหว่างแฟ้ม java จำนวน 3 แฟ้ม
– การแสดงข้อมูลมีกิจกรรมใน 1) ItemDetailActivity.java ทำหน้าที่รับอะไรจากใครเข้าไป
แล้วพบการเชื่อมกับ 2) ItemDetailFragment.java
ด้วยคำสั่ง arguments.putString(ItemDetailFragment.ARG_ITEM_ID, ..
และ .add(R.id.item_detail_container, fragment) ..
ซึ่ง item_detail_container อยู่ใน Layout activity_item_detail.xml
– หากเข้าไปดูใน ItemDetailFragment.java
พบว่า มีการเชื่อมกับ ARG_ITEM_ID กับ 3) DummyContent.java อีกทีหนึ่ง
มีรายละเอียดที่น่าสนใจอีกมากมายใน DummyContent.java

พบว่ามี Layout structure ดังนี้

<CoordinatorLayout>
 <AppBarLayout>
 <CollapsingToolbarLayout>
 <Toolbar />
 </CollapsingToolbarLayout>
 </AppBarLayout>
 <NestedScrollView android:id="@+id/item_detail_container" />
 <FloatingActionButton />
 </CoordinatorLayout>

1.5 สำรวจ Layout ที่ 3 แฟ้ม item_detail.xml
โครงร่างย่อยสำหรับแสดงเนื้อหาโดยตรง และรับข้อมูลแบบ TextView
ทำงานสำหรับด้านขวา (Right Pane) เท่านั้น
พบว่า TextView ถูกเชื่อมข้อมูลกับ DummyContent.java ผ่านคำสั่งใน ItemDetailFragment.java
คือ ((TextView) rootView.findViewById(R.id.item_detail)).setText(mItem.details)
เมื่อเห็นการทำงานของ Layout นี้ จึงนำไปปรับใช้เป็น WebView ในตอนท้ายของบทความนี้

พบว่ามี Layout structure ดังนี้

<TextView id="@+id/item_detail" /> (แฟ้มนี้มี Tag เดียว)

1.6 สำรวจ Layout ที่ 4 แฟ้ม item_list.xml
โครงร่างย่อยสำหรับรายการตัวเลือก ทำงานด้านซ้าย (Left Pane) เท่านั้น
พบว่า findViewById(R.id.item_list) ถูกเชื่อมเข้า View ใน ItemListActivity.java
แล้วเชื่อมโยงระหว่าง RecycleView กับ DummyContent ผ่าน .setAdapter()
หน้าที่ของ item_list คือ แสดงหน่วยข้อมูล (item) ให้เลือกแบบรายการ (List)
พบว่ามี Layout structure ดังนี้

<RecyclerView id="@+id/item_list" /> (แฟ้มนี้มี Tag เดียว)

1.7 สำรวจ Layout ที่ 5 แฟ้ม item_list.xml (w900dp)
คล้ายกับ 1.6 แต่หากจอภาพเป็นแบบ Wide Screen
รองรับการแสดง FrameLayout ที่กว้าง 900 dp ได้ ก็จะมี 2 Pane
มีการตรวจสอบ และกำหนดค่าให้กับ mTwopane = true
ซึ่งพบใน ItemListActivity.java
หากปรับขนาดจาก 900 dp เหลือ 600 dp ก็จะแสดงผลบน Smartphone ของผมได้
จึงลดขนาดด้วยการ rename folder เป็น layout-w600dp
ผ่านการ Right Click เลือก [Show in Explorer] แล้วก็ rename folder ได้เลย
http://www.appstoremarketresearch.com/articles/android-tutorial-master-detail-flow/

พบว่ามี Layout structure ดังนี้

<LinearLayout>
 <RecyclerView id="@+id/item_list" />
 <FrameLayout id="@+id/item_detail_container" />
</LinearLayout>

1.8 สำรวจ Layout ที่ 6 แฟ้ม item_list_content.xml
โครงร่างย่อยสำหรับแสดงรายการตัวเลือกแต่ละรายการ
ปกติจะมีลำดับตัวเลือก และชื่อตัวเลือก ก็จะเป็นตาม Layout นั้น
ส่วนแฟ้มที่กำหนดขนาด (Dimension) คือ dimens.xml
หากเปลี่ยน <dimen name=”text_margin”> ก็จะมีผลต่อ Layout
ที่อ้างอิงผ่าน layout_margin=”@dimen/text_margin”

พบว่ามี Layout structure ดังนี้

<LinearLayout android:orientation="horizontal">
 <TextView />
 <TextView />
</LinearLayout>

2. ทำให้ item ใน list มีกิจกรรม
พบว่าแฟ้ม DummyContent.java ควบคุมการแสดงรายการตัวเลือก
และกิจกรรมหลังเลือกตัวเลือก
หากจะปรับเปลี่ยนจำนวนตัวเลือก หรือเปลี่ยนชื่อตัวเลือก
จาก 25 รายการเป็น 10 รายการ ก็สามารถทำได้
สามารถเปลี่ยน for ใน static เป็นดังนี้

มองหา
 private static final int COUNT = 25;
 static {
 for (int i = 1; i <= COUNT; i++) {
 addItem(createDummyItem(i));
เปลี่ยนเป็น
 private static final int COUNT = 5;
 static {
 addItem(new DummyItem("1","API Level",makeDetails(1)));
 addItem(new DummyItem("2","SECURITY_PATCH",makeDetails(2)));

3. เพิ่มเกิจกรรมให้ตัวเลือกแต่ละตัว ใน DummyContent.java

มองหา
 builder.append("Details about Item: ").append(position);
 for (int i = 0; i < position; i++) { .. }
 return builder.toString();
เปลี่ยนเป็น
 builder.append("Data ID : ").append(position);
 switch(position){
 case 1:
 builder.append("\nAPI Level = ")
 builder.append(String.valueOf(Build.VERSION.SDK_INT)); // 21
 return builder.toString();

4. การได้ ipaddress ต้องปรับ AndroidManifest.xml
โดยเพิ่ม 2 tag นี้ ก่อนเปิด tag <application>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

มีตัวอย่างคำสั่งในข้อ 8

 

5. สร้าง WebView ชื่อ aboutus.xml รับ HTML Tag
สร้าง Layout ใหม่ให้มีเพียง WebView คล้ายกับ item_detail.xml
แล้วปรับให้การคลิ๊ปปุ่มบน FloatingActionButton ไปเรียก aboutus.xml
เลือกการเปลี่ยน include ใน activity_item_list.xml
ใช้วิธีการกำหนด ViewFlipper เคยเล่าในตอนที่ 10 ข้อ 1

5.1 ปรับแฟ้ม activity_item_list.xml
เพื่อสลับกันไปมาระหว่างการกดปุ่ม FloatingActionButton
คือเลือกระหว่างแสดง item_list กับ aboutus
หาก include item_list ใน wide screen จะมา 2 section
หาก include aboutus ใน wide screen จะมาเฉพาะ WebView

มองหา
 <include layout="@layout/item_list" />
เปลี่ยนเป็น
 <ViewFlipper
 android:id="@+id/view_flipper"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <include layout="@layout/item_list" />
 <include layout="@layout/aboutus" />
 </ViewFlipper>

https://developer.android.com/reference/android/webkit/WebView.html
https://www.mkyong.com/android/android-webview-example/

5.2 ปรับแฟ้ม ItemListActivity.java
ใน fab.setOnClickListener(new View.OnClickListener() { }
ซึ่งใช้ switch สนับกันสั่ง setDisplayedChild

เพิ่มคำสั่งต่อไปนี้

ViewFlipper vf = (ViewFlipper) findViewById(R.id.view_flipper);
 switch (vf.getDisplayedChild()) {
 case 0:
 vf.setDisplayedChild(1);
 WebView webView = (WebView) findViewById(R.id.webview);
 webView.getSettings().setJavaScriptEnabled(true);
 String mData = getString(R.string.mdata);
 //webView.loadData(mData, "text/html", null);
 webView.loadDataWithBaseURL("file:///android_res/drawable/",
 "<img src='test.jpg' />", "text/html", "utf-8", null);
 break;
 case 1: vf.setDisplayedChild(0); break; }

5.3 เปลี่ยนภาพปุ่ม
เลือก ic_menu_help ที่แสดงเครื่องหมาย ? บน FloatingActionButton
ด้วย app:srcCompat=”@android:drawable/ic_menu_help”

5.4 เขียน HTML แบบใช้ entity reference
คือการใช้ &lt; แทนเครื่องหมาย <

<string name="mdata">
 &lt;html>&lt;body>
 &lt;b>Hello world!&lt;/b>&lt;br/>
 &lt;center>&lt;img src="bridge.jpg" height=200 />&lt;/center>
 &lt;table width=100% bgcolor=yellow>&lt;tr>&lt;td>&lt;center>
 A bridge is in Lampang province, Thailand.
 &lt;/td>&lt;/tr>&lt;/table>
 &lt;/body>&lt;/html>
 </string>

6. การเพิ่ม layout แบบ WebView แทน TextView จำนวน 1 ตัวเลือก
พบว่า มีการส่ง R.layout.item_detail
เข้าไปใน rootView ใน ItemDetailFragment.java
ผ่านคำสั่ง rootView = inflater.inflate(R.layout.item_detail,..
ก็เพียงแต่เปลี่ยนจาก item_detail เป็น aboutus เท่านั้น
เปลี่ยนเป็น rootView = inflater.inflate(R.layout.aboutus,..
แล้วปรับแฟ้ม aboutus.xml ให้คล้าย item_detail.xml ที่มีเพียง Tag เดียว
เพื่อเข้าไปอยู่ใน rootView แล้วแสดงผลร่วมกับ appBarLayout ดังนี้

<WebView xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/webview"
 style="?android:attr/textAppearanceLarge"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:padding="16dp"
 android:textIsSelectable="true"
 tools:context="com.thaiall.www.mainanddetail.ItemDetailFragment" />

โดย rootView ใน ItemDetailFragment.java
จะถูกนำเข้า fragment แล้วรวมกับ container ใน ItemDetailActivity.java
ผ่านคำสั่ง getSupportFragmentManager().beginTransaction()
.add(R.id.item_detail_container, fragment)

7. การหาขนาด Width และ Height ของจอภาพ
ทำใน Activity หลักที่มี Context
แล้วเรียกค่าไปใช้ใน Dummy project ได้

การเรียกใช้ใน Dummy project

import com.thaiall.www.mainanddetail.ItemListActivity;
private static ItemListActivity item = new ItemListActivity();
builder.append(item.screenWidth);

ประกาศตัวแปรไว้ใต้ Class แบบ static

public static int screenHeight = 0;
 public static int screenWidth = 0;

คำสั่งสำหรับหาค่า Width กับ Height ใช้ใน Activity หลัก

// Width=720pixel Height=1280pixel
// DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); 
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); 
wm.getDefaultDisplay().getMetrics(displayMetrics);
screenHeight = displayMetrics.heightPixels;
screenWidth = displayMetrics.widthPixels;

8. การหาค่า IP Address

WifiManager wifiMan = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
 WifiInfo wifiInf = wifiMan.getConnectionInfo();
 int ipAddress = wifiInf.getIpAddress();
 ip = String.format("%d.%d.%d.%d", 
(ipAddress & 0xff),(ipAddress >> 8 & 0xff),
(ipAddress >> 16 & 0xff),(ipAddress >> 24 & 0xff));

9. การหาวันเวลาของเครื่อง

getDateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime());

10. การหาเลขรุ่น API ของ Android ที่มีในโทรศัพท์แต่ละเครื่อง

builder.append(String.valueOf(Build.VERSION.SDK_INT)); 
// I-Mobile IQ II 21
builder.append(String.valueOf(Build.VERSION.RELEASE)); 
// 5.0 (Lollipop) or 4.4.2 (Kitkat)

11. การส่งค่าเข้าตัวแปรแบบตัวเลข และตัวอักษรใน string
ตัวอย่างนี้ไม่ได้อยู่ใน project ที่ทดสอบนี้ แต่ค้นมาแล้วอยากเล่าเก็บไว้
จะรับข้อมูลจาก 3 ตัวแปร ที่ผสมระหว่างตัวเลข และตัวอักษร
จึงจะทำให้ข้อมูลสมบูรณ์ ตัวอย่างนี้ตัวแปรจะมีลำดับที่เริ่มจาก 1
ส่งเข้าไปผ่าน method getResources และ getString

<string name="x1">a= %1$d and b= %2$s and c= %3$d</string>
int a = 1024;
String b = "ASCII";
int c = 65536;
String y = getResources().getString(R.string.x1, a, b, c);

12. การอ้างอิงชื่อ id, string, layout, drawable แบบอ้างอิงด้วยตัวแปร
ตัวอย่างนี้ไม่ได้อยู่ใน project ที่ทดสอบนี้ แต่ค้นมาแล้วอยากเล่าเก็บไว้
บางครั้ง มีข้อมูลจำนวนมากใน string หรือ drawable
แล้วต้องการอ้างอิงแบบเขียน code ให้สั้น
ไม่ใช่มี 100 ภาพ ก็เขียน 100 บรรทัด ก็มีเทคนิค หรือ algorithm อยู่ครับ

int n = 1;
String tv ="R.id.x" + n;
int id = getResources().getIdentifier(tv, "id", getPackageName());
TextView v1 = (TextView) findViewById(id);
v1.setText("new value");
// R.layout.v1
// getResources().getIdentifier("v" + 1, "layout", getPackageName());
// R.string.v2
// getResources().getIdentifier("v" + 2, "string", getPackageName());
// R.drawable.v3
// getResources().getIdentifier("v" + 3, "drawable", getPackageName());

13. การติดตั้ง Android 7.1 บน VirtualBox
เริ่มต้นจากการ Download แฟ้ม .iso สำหรับติดตั้ง Android
http://www.android-x86.org/download

มีขั้นตอน ดังนี้

– Installation
– Create/Modify Partitions
แบบนี้เป็นปัญหา Other และ Other/Unknown
แบบนี้ผ่านด้วยดี Windows และ Windows 32 Bits
แบบนี้ผ่านด้วยดี Ubuntu และ Ubuntu 32 Bits
– use GPT = no
– in partition 1
– write in bootable and primary and Quit
– select SDA1 and format in ext4
– install GRUB and /system
– select [run Android-x86]
– Let’s go
– Setup as new
– Checking for update
– Get connected
– Don’t use any network for setup
– continue and Next
– name=android
– Google services > Next
– Anything else? > ALL SET
– Home screen
– chrome + accept policy
– no signin
– click O > Home screen
– click up arrow
– click Terminal emulator
– $ifconfig = ip address 192.168.1.2

</process>

<website_guide>
+ http://benzneststudios.com/../context-android-overview/
+ https://developer.android.com/../string-resource.html
+ https://stackoverflow.com/..using-getresources-in-non-activity-class
+ https://stackoverflow.com/..get-context-on-android
+ https://stackoverflow.com/..use-getsystemservice-in-a-non-activity
+ https://stackoverflow.com/..get-screen-dimensions-in-pixels
+ https://stackoverflow.com/..get-screen-width-and-height
+ https://stackoverflow.com/..getwindowmanager-by-another-java
+ https://www.youtube.com/watch?v=hjY06ZmYl8U
</website_guide>

หมายเหตุ 
ถ้าสนใจติดตามเนื้อหาในบล็อกนี้ สามารถ subscribe ด้วย email ที่อยู่ข้างขวา หรือ click here

#AndroidStudio ตอนที่ 10 สำรวจ Layout และ properties ที่น่าสนใจ 6 Layout

#AndroidStudio ตอนที่ 10 สำรวจ Layout และ properties ที่น่าสนใจ 6 Layout

<introduction>
อารัมภบท
เกิดข้อสงสัย จึงอยากชวนไปสำรวจ ว่ามี Layout อยู่เท่าไรที่เราทำเป็น Root layout เพราะ Theme: Basic Activity เตรียม CoordinatorLayout มาให้เราใช้ ส่วน Empty Activity เตรียม ConstraintLayout มาให้ เมื่อเข้า Layout Editor หรือ UI Builder เพื่อสร้าง UI แล้วเข้าส่วน Design มองใน Palatte หัวข้อ Layouts จะพบ 9 ตัวเลือก คือ ConstraintLayout, GridLayout, FrameLayout LinearLayout(horizontal), LinearLayout(vertical), RelativeLayout, TableLayout, TableRow, และ  อันที่จริงยังมี Layout มากกว่านี้ อาทิ CoordinatorLayout หรือ AppbarLayout เป็นต้น

ขณะสำรวจ และทดสอบในบทบาท ผู้ใช้โปรแกรม Android Studio ทำการสร้าง Layout ก็ย่อมมีปัญหา ไม่ได้อย่างใจหมายหลายครา ทำให้มีโอกาสสืบค้น และได้พบบทความเกี่ยวกับ Layout ที่ akexorcist.com และ devahoy.com พบว่านักเขียนเล่าอะไรหลายอย่างเกี่ยวกับ Android ทำให้เข้าใจขึ้นมาก ลองไปหาอ่านดูนะครับ

สรุปกระบวนการ ได้ 5 ขั้นตอน ประกอบด้วย 1) สร้าง Project แบบ Basic Activity ไว้เรียก Layout อื่น 2) การปรับ orientation ของ LinearLayout เป็น vertical กับ horizontal 3) การแสดงข้อมูล 3 column โดยใช้ TextView บน LinearLayout 4) การสร้าง relativelayout.xml 5) การทำภาพ overlay แบบ RelativeLayout 6) copy overlay.xml แล้ว paste constraintlayout.xml 7) การสร้าง gridlayout.xml 8) การสร้าง tablelayout.xml

ปล. แฟ้ม Project ผมบีบไว้ และแชร์ให้ Download ทั้ง .rar และ .apk ไปทดสอบกัน
ที่ http://www.thaiall.com/android (ผ่าน 4shared.com)

</introduction>

<definition>
นิยามศัพท์

  1. LinearLayout คือ เค้าโครงเพื่อจัดวางวัตถุแบบเรียงลำดับ เลือกเรียงแบบ ตามแนวตั้ง (Vertical) หรือตามแนวนอน (Horizontal) เป็น Default Layout เมื่อสร้าง Layout XML File ขึ้นใหม่
  2. RelativeLayout คือ เค้าโครงเพื่อจัดวางวัตถุที่สัมพันธ์กัน เชื่อมโยง อ้างอิง อาจอ้างอิงวัตถุอื่น หรืออ้างอิง Parent ก็ได้ การใช้ Layout Editor จะช่วยให้จัดวาง เห็นภาพใน Blueprint ทำได้สะดวกขึ้นแทนการเข้าไปกำหนดใน XML file โดยตรง
  3. ConstraintLayout คือ เค้าโครงแบบเพื่อจัดวางวัตถุแบบใหม่ คล้าย RelativeLayout มาก และ Android สนับสนุนให้ใช้ เป็นเค้าโครงที่เหมาะสำหรับนักพัฒนาที่ไม่ถนัด XML file มี Layout Editor ที่รองรับการจัดวางผ่าน Blueprint และลดจำนวนเค้าโครงที่ซับซ้อนได้
  4. GridLayout คือ เค้าโครงเพื่อจัดวางวัตถุแบบต่อเนื่อง ในช่องที่จัดเตรียมเป็นตะแกรง หรือจะหย่อนวัตถุไปตามตาที่กำหนดได้ ตัวอย่างการใช้ คือ Image Gallery หรือการแสดงรายการ App บนสมาร์ทโฟน ก็แสดงเป็น Grid
  5. TableLayout คือ เค้าโครงเพื่อจัดวางวัตถุ โดยกำหนดเป็น Row กับ Column เหมาะกับการวางข้อมูลจากระบบ Database ที่แบ่งข้อมูลเป็น Record กับ Field ไว้แล้ว แต่จะจัดวางเป็นฟอร์มสำหรับ Input ข้อมูลก็สามารถสั่งขยายช่องด้วย span ได้
  6. CoordinatorLayout คือ เค้าโครงเพื่อจัดวางวัตถุที่แตกต่างรูปแบบในหน้าเดียวกัน อาจมีทั้ง Slide, Panel, Button หรือ Stick และ Animate ก็ทำได้
  7. ViewGroup คือ เป็นกลุ่มของ View ที่ทำหน้าที่จัดวางเค้าโครง มี subclass ทั้งแบบ Direct (19 Layout) และ Indirect (63 Layout) หากต้องการหา Layout ที่ตรงกับความต้องการให้เข้ามาดูรายชื่อ subclass แล้วเข้าไปดู description และ method ได้

</definition>

กำลังเล่าเรื่อง การใช้โปรแกรม Android Studio สู่เพื่อนนักพัฒนา ผ่าน Blog

<process>
กระบวนการในการพัฒนา APP
เพื่อสำรวจการใช้งาน Layout แต่ละแบบ ว่าใช้งานแตกต่างกันอย่างไร
มีขั้นตอน ดังนี้

1. สร้าง Project แบบ Basic Activity ไว้เรียก Layout อื่น
ตั้งชื่อว่า layoutsample แล้วเตรียม menu, string, activity, layout
ในตอนนี้เราจะ include Layout แล้วเลือก include ผ่าน ViewFlipper
ตามที่เล่าใน ตอนที่ 9 ข้อ 3 ว่าเราสร้าง Menu ผ่าน ToolBar ได้
แล้วเพิ่ม include คู่กับ visible หรือ gone หลายรายการ
เพื่อคุมการ select ใน Menu ให้ได้ผลตามต้องการ
ตัวอย่างนี้ขอปรับการเลือกควบคุมสลับ visible กับ gone
เป็นการใช้ ViewFlipper คลุมใน activity_main.xml และ MainActivity.java

1.1 เริ่มจากสร้าง linearlayout.xml เปล่า ขึ้นมาก่อน
เพื่อเตรียมไว้เป็นตัวเลือกที่ 1 เพราะตัวเลือกแรก คือ content_main.xml
ที่มีมากับ Basic Activity แล้วแสดงคำว่า Hello world!

1.2 ปรับ code ใน activity_main.xml
เพื่อเพิ่ม ViewFlipper เข้าควบคุมการ include

มองหา
 <include layout="@layout/content_main" />
 เปลี่ยนเป็น
 <ViewFlipper
 android:id="@+id/view_flipper"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <include layout="@layout/content_main" />
 <include layout="@layout/linearlayout" />
 </ViewFlipper>

1.3 ปรับ code ใน MainActivity.java
เพื่อเปลี่ยนจากการใช้ if ไปใช้ switch คุมการ setDisplayedChild ที่ต้องการ

มองหา
 if (id == R.id.action_settings) {
 return true;
 }

เปลี่ยนเป็น
 import android.widget.ViewFlipper;
 ViewFlipper vf = (ViewFlipper) this.findViewById(R.id.view_flipper);
 switch (item.getItemId()) {
 case R.id.content:
 vf.setDisplayedChild(0);
 return true;
 case R.id.linearlayout:
 vf.setDisplayedChild(1);
 return true;
 }

1.4 ไปเพิ่ม <item> ใน menu_main.xml และ <string> ใน strings.xml
เพื่อให้มีตัวเลือกสำหรับการคลิ๊กใน menu
เพื่อเลือก case R.id.content และ case R.id.linearlayout
เพราะขณะนี้มี 2 layout ที่พร้อมทำงานใน menu

1.5 ระหว่างสร้าง string พบการปัดบรรทัดที่มีผลกับ layout
โดยตัวอักษรที่ปัดบรรทัด หรือ Line Break ด้วย \n
ปัญหานี้เล่าใน ตอนที่ 8.1 แต่มาพบ \n ในตอนนี้

<string name="datawith2br">a\nb\nc</string>

2. การปรับ orientation ของ LinearLayout เป็น vertical กับ horizontal
เมื่อสร้าง linearlayout.xml พบว่าค่า default ไม่ได้กำหนดว่า orientation เป็นอะไร
แต่ default เป็น horizontal แม้ไม่ได้กำหนดก็ตาม

2.1 ทดสอบเพิ่ม TextView ที่มี @string/data
ได้เพิ่มแบบไม่กำหนด id จำนวน 20 tag
ปัญหาแรก พบว่า ข้อมูลเบียนกันจนแน่นในแถวเดียว เป็นปัญหาเรื่องตำแหน่ง
หากจำนวนข้อมูลน้อยกว่า 20 tag ก็จะแสดงผลได้ปกติ แต่กรณีนี้มากไป
และไม่ได้จัดเรียงแบบ wrap ลงมาบรรทัดต่อไป
นี่เป็นค่า default ของ orientation ที่เป็นแบบ horizontal
อีกปัญหา พบว่า ทั้งใน emulator และ smart phone
บน emulator จะแสดงคำว่า data ทับ AppbarLayout
บน smartphone จะคำว่า data ถูกทับด้วย AppbarLayout

<TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/data" />

[ปัญหา]
สรุปว่า พบปัญหาการแสดงผลในทั้ง 2 อุปกรณ์
เนื่องจากต้องการให้ตำแหน่งเริ่มต้นแสดงผลต่อจาก Appbarlayout
ไม่ใช่ทับกันไปมา ระหว่าง TextView กับ Appbarlayout แบบนั้น
[วิธีแก้ไข]
เพิ่ม android:layout_marginTop=”?attr/actionBarSize” ใน layout
ทดสอบกับทั้ง linearlayout.xml และ content_main.xml
แม้จะเปลี่ยน wrap_content เป็น match_parent แล้ว ก็ไม่มีปัญหา

2.2 ทดสอบเพิ่ม android:orientation=”vertical”
* ใน layout แบบ ConstraintLayout หรือกำหนด width=”match_parent”
ผล คือ data ทับกันในตำแหน่งเดิม แสดงว่า ไม่รองรับการกำหนดเป็น vertical
* ใน layout แบบ LinearLayout
ผล คือ เรียงต่อกันมาตามแนวนอน บรรทัดละ 1 คำอย่างถูกต้อง
แม้กำหนดเป็น wrap_content ทุกตัวก็ตาม

 

3. การแสดงข้อมูล 3 column โดยใช้ TextView บน LinearLayout
กำหนดให้ แท่งแรกกว้าง 25% (0.25) แท่งที่สอง 50% (0.5) แท่งที่สาม 25% (0.25)
แก้ไขในแฟ้ม linearlayout.xml เดิม
ไปอ่านมาจาก https://devahoy.com/posts/android-layout-linear-layout/

ปรับ properties ที่ใช้ใน TextView ดังนี้

background="#00ff00" คือ สีพื้นเขียว
padding="5dp" คือ ช่องว่างระหว่างตัวอักษรกับขอบใน
gravity="center" คือ อยู่ตรงกลางของ TextView
layout_width="wrap_content" คือ ขนาดเท่าข้อมูล
layout_height="match_parent" คือ ขนาดเต็มจอ
layout_weight="0.50" คือ กว้าง 50%
layout_marginStart="5dp" คือ เว้นว่างทางซ้าย

4. การสร้าง relativelayout.xml
เลือก Layout XML File ที่มี Root Tag = RelativeLayout
แล้วเพิ่มตัวเลือกเข้าไปใน menu จะได้เรียกมาทดสอบได้ง่าย
แก้ให้ครบทุกจุดนะครับ เพราะมีเยอะเลยที่ต้องแก้ให้สอดคล้องกัน
แม้เป็นตัวเลือกที่ 3 แต่ต้องกำหนด vf.setDisplayedChild(2);
อ่านความหมายของ Layout ที่ devahoy.com
เรียบเรียงได้ว่า LinearLayout และ RelativeLayout
ต่างเป็น View Group เหมือน Container มีไว้รวบรวม Child View หรือ Widget
มีสิ่งที่ต่างกันใน 2 Layout คือ การจัดเรียง
ถ้า LinearLayout ก็จัดเรียงแบบ horizontal หรือ vertical
ถ้า RelativeLayout ก็จัดเรียงอย่างมีความสัมพันธ์ ซึ่งกันและกัน
การจัดเรียงค่อนข้างเป็นอิสระ และเชื่อมโยงตามลำดับ ทำให้นึกถึง linked list

ปรับ properties ที่ใช้ใน TextView ดังนี้

id="@+id/tv1" คือ การตั้งชื่อให้ TextView
layout_toEndOf="@+id/tv1" คือ อยู่ต่อท้าย tv1
layout_alignParentStart="true" คือ ตำแหน่งเริ่มซ้ายของจอ
textSize="16sp" คือ ขนาดตัวอักษร 16
layout_below="@+id/tv1" คือ อยู่ข้างล่างต่อจากภาพ tv1
layout_toEndOf="@+id/tv1" คือ เริ่มต่อจากด้านขวาของ tv1
gravity="center|center_vertical" คือ อักษรอยู่กลาง
layout_alignParentEnd="true" คือ ชิดด้านซ้ายของจอภาพ
layout_alignParentBottom="true" คือ ชิดด้านล่างขอจอภาพ

5. การทำภาพ overlay แบบ RelativeLayout
สร้าง Layout ใหม่ชื่อ overlay.xml และ Root Tag = RelativeLayout
ส่งภาพเข้า drawable ผมเตรียมภาพขนาด 360*640 
เพราะโทรศัพท์ของผมขนาดเท่านี้
https://www.whatismyscreenresolution.com/

ปรับ properties ที่ใช้ใน TextView ดังนี้

android:layout_marginTop="?attr/actionBarSize" คือ ของ RelativeLayout
android:contentDescription="@string/data" คือ รายละเอียดของภาพ 
android:scaleType="fitXY" คือ กำหนดให้ภาพพอดีกับตำแหน่ง X และ Y
app:srcCompat="@drawable/lp01" คือ การใส่ภาพจาก drawable
gravity="center" คือ ข้อความอยู่ตรงกลาง
textSize="60sp" คือ ขนาดตัวอักษร
textColor="#000000" คือ สีตัวอักษร
background="#00ff00" คือสีพื้น
alpha="0.3" คือ การกำหนดระดับความโปร่งแสง
layout_alignParentStart="true" คือ ชิดด้านซ้าย

 

6. copy overlay.xml แล้ว paste constraintlayout.xml
เข้าไปอ่าน blog ของ akeorcist.com เห็นชัดเลยว่า
Android เชียร์ให้ใช้ ConstraintLayout แทน RelativeLayout
เพราะจัดการง่ายผ่าน UI Builder และมีขนาดเล็กกว่า
งานที่เคยทำใน RelativeLayout สามารถแปลงเป็น ConstraintLayout อัตโนมัติ
จึงคัดลอก overlay.xml เป็นวางแฟ้มเป็นชื่อใหม่คือ constraintlayout.xml
เข้า design แล้วคลิ๊กที่ RelativeLayout ใน Component Tree
กด Right Click จะมี Convert RelativeLayout to ConstraintLayout มาให้
แล้วมีให้เลือกทำ Flatten Layout Hierarchy
กรณีของผม ต้องปรับรายละเอียดใน ImageView และ TextView
เพราะ layout เปลี่ยน properties ก็ต้องเปลี่ยน เพี้ยนไปบ้าง

ใน ImageView ก็ต้องทำให้ขอบภาพชิดกับของ parent ดังนี้

app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

แต่ข้อความใน TextView ถูกเปลี่ยนให้เชื่อมกับส่วนอื่น ทำให้อยู่ตรงกลางของจอ

app:layout_constraintRight_toRightOf="@+id/imageView"
app:layout_constraintLeft_toLeftOf="@+id/imageView"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintBottom_toTopOf="@+id/button"

7. การสร้าง gridlayout.xml
พบว่า GridLayout เป็นเค้าโครงคล้ายตาราง ใส่ข้อมูลเป็นช่องตาม row หรือ column
แล้วมี GridView ที่ช่วยให้การใส่ image เป็น gallery ได้ง่าย
รองรับการใส่ข้อมูลจำนวนมาก มีความเป็นอัตโนมัติผ่านการจัด orientation
Default คือ orientation:horizontal คือ เรียงแนวนอนไปทางขวาจนจบแถว
แล้วขึ้นแถวต่อไป
ขณะทดสอบพบว่า SDK ที่ผมใช้ตัวล่างที่ติดตั้งไว้ คือ API 19
แล้วไม่รองรับ layout_weight in LinearLayout. This is supported in API 21.

ตัวอย่างการใส่ TextView เข้าไปใน Row และ Column ที่กำหนด

<TextView
 android:layout_row="0"
 android:layout_column="0"
 android:id="@+id/textView3"
 android:textSize="16sp"
 android:background="#00ff00"
 android:layout_width="80dp"
 android:layout_height="80dp"
 android:text="@string/data" />

ตัวอย่างการใส่ Button เข้าไปอัตโนมัติ ช่องไหนว่างตาม orientation ก็เข้าไปเลย

<Button
 android:id="@+id/button6"
 android:layout_width="80dp"
 android:layout_height="80dp"
 android:text="@string/data" />

8. การสร้าง tablelayout.xml
เป็นการวางเค้าโครงให้รองรับการใส่ข้อมูลเป็น row กับ column
ทำให้นึกถึงการเขียน Table ในภาษา HTML ที่มี tr กับ td
ทำ span เพื่อขยายพื้นที่ของ cell ได้
เมื่อใส่ TextView ลงไปก็เป็นเพียงข้อมูลที่นำมาต่อกันใน 1 cell
แต่ TextView ที่มี android:layout_weight=”1″ จะมีน้ำหนักเป็น cell
มักต้องใส่ในทุก TextView เพื่อประกาศการเป็น cell

ตัวอย่างการเค้าโครงการวาง Tag ของ TableLayout

<TableLayout>
  <TableRow>
     <TextView android:layout_weight="1">
     <TextView android:layout_weight="1">
  </TableRow>
</TableLayout>

</process>

<website_guide>
https://www.whatismyscreenresolution.com/
http://www.akexorcist.com/..new-android-layout.html
https://devahoy.com/..relative-layout-tutorial/
+ http://www.journaldev.com/..viewflipper-example-tutorial
+ http://www.programcreek.com/..&method=setDisplayedChild
+ https://developer.android.com/../view/ViewGroup.html
https://developer.android.com/guide/topics/ui/layout/grid.html
+ https://developer.android.com/../widget/TableLayout.html
</website_guide>

หมายเหตุ 
ถ้าสนใจติดตามเนื้อหาในบล็อกนี้ สามารถ subscribe ด้วย email ที่อยู่ข้างขวา หรือ click here

#AndroidStudio ตอนที่ 9 Layout ของการแจ้งเตือน และการสร้าง Layout at Runtime และเมนู กับการแสดงภาพต่อตาม Vertical

#AndroidStudio ตอนที่ 9 Layout ของการแจ้งเตือน
และการสร้าง Layout at Runtime และเมนู กับการแสดงภาพต่อตาม Vertical

<introduction>
อารัมภบท
ความตั้งใจครั้งแรก คือ การวาง Layout ของการแจ้งเตือน โดยแสดง ImageView และ TextView คู่กัน เรียงเป็นบรรทัดลงไปแบบ Vertical แต่พอได้ลงไปวาง Layout พบว่า โปรแกรมแนะนำว่าให้ใช้ Drawable ตามที่เคยใช้ใน ตอนที่ 8 ข้อ 8 พอใช้ตามคำแนะนำ ก็พบปัญหา ความตั้งใจจึงเบี่ยงเบนไปเรื่องการทำ Valign=Top ว่าทำอย่างไรให้ภาพอยู่ในตำแหน่ง Top แล้วก็ไปสนใจการใช้ Layout แบบ RelativeLayout จากนั้นก็กลับมาคิดเรื่อง Notification ว่าควรลื่นไหลขณะ Runtime เหมือนที่เห็นใน FB Message
ก็พบว่าการวาง Layout ใน Android ทำได้ 2 แบบ คือ Declare UI elements in XML และ Instantiate layout elements at runtime เมื่อไปค้นดูก็ไปไม่ถึงไหน ได้แค่การสั่งให้สร้าง Layout at Runtime ใหม่ขึ้นมา พร้อมสร้าง TextView และส่งค่าเข้า TextView ที่สร้างขึ้น

ความเดิมตอนที่แล้ว เคยเล่าเรื่องการใช้ Template : Basic Activity ใน ตอนที่ 8 แต่ข้ามเรื่อง Menu ของ Toolbar ใน AppBarLayout ที่มีความสัมพันธ์กับหลายแฟ้ม ครั้งนี้กลับมาสนใจ และเพิ่มไป 3 ตัวเลือก พร้อมกิจกรรมที่ได้ทดสอบมาแล้วข้างต้น ทั้งหมดยังอยู่ใน 1 Main Layout กับ 1 Main Activity เพราะ Android Studio วางโครงสร้างให้ Activity คู่กับ Layout ส่วน Content Layout ในตัวอย่างครั้งนี้ จะถูกเรียกผ่าน Main Layout
ใช้การ include เข้าไป ก็ต้องใช้ setVisibility(View.VISIBLE); ใน Activity กำหนดให้กับ include แต่ละตัว เพราะไม่มีวิธีส่งชื่อ Layout ให้ include โดยตรง

สรุปกระบวนการได้ 5 ขั้นตอน ประกอบด้วย 1) ทำความรู้จัก CoordinatorLayout ที่มีเสน่ห์ มาพร้อม Snackbar 2) การวางภาพคู่กับข้อความ 6 แบบ เลือกใช้ที่ชอบได้เลย 3) ใส่ Activity ให้กับ Menu ใน Toolbar บน AppBarLayout 4) การสร้าง layout at runtime เพื่อ say hello 5) สร้าง Layout สำหรับแสดง ImageView โดยเฉพาะ
</introduction>

กำลังเล่าเรื่อง การใช้โปรแกรม Android Studio สู่เพื่อนนักพัฒนา ผ่าน Blog

<process>
กระบวนการในการพัฒนา APP

เพื่อนำภาพและข้อความนำเสนอต่อกันเรียงลงมาเป็นแถว การจัดการเมนู การสร้าง Layout ช่วง Runtime และการนำภาพมาเรียงต่อกันตาม Vertical
มีขั้นตอน ดังนี้

1. ทำความรู้จัก CoordinatorLayout ที่มีเสน่ห์ มาพร้อม Snackbar
เริ่มต้นก็สร้าง project ใหม่ แล้วเลือก Basic Activity ตั้งชื่อ ว่า layoutofnotification
ยังมี Template อีกมาก ทาง Android แนะนำว่าสามารถ Add Code from a Template คือ เราไม่ต้องเขียน code จาก 0 เค้ามี Template มาให้เลือกตามชอบ เคยมีอยู่ 10 ตอนนี้มี 12 และอาจเพิ่มขึ้น เลือกแล้วก็จะมี file ที่จำเป็น และเรียกใช้งานได้ในระดับหนึ่ง เราเพียงแต่นำมาปรับเพิ่ม พบว่า หน้า activity_main.xml มี Hierarchy ของ Layout ดังนี้
1. CoordinatorLayout เป็น root layout
2. AppBarLayout และภายในมี ToolBar
3. ConstraintLayout ที่ถูก include แฟ้ม content_main.xml
4. FloatingActionButton ลอยอยู่ที่ตำแหน่ง bottom|end
สำหรับ CoordinatorLayout ที่ถูกเลือกใช้นี้
ทำให้เราได้เห็นการใช้ FloatingActionButton ร่วมกับ Snackbar และ AppBarLayout

 

https://gist.github.com/thaiall/7bfcfeb57ac459b0e664f19337438908

 

ใช้โปรแกรม Android Studio ไม่ทันไร ถาม Update อีก 150 MB
รอไร .. 
เครื่องผมเหลือเนื้อที่ตั้งเยอะ 

 

2. การวางภาพคู่กับข้อความ 6 แบบ เลือกใช้ที่ชอบได้เลย
เดิม activity_main.xml จะ include แฟ้ม content_main.xml
แต่ผมลบไปแล้ว ของเดิมมี ConstraintLayout เป็น Root Layout
กับ TextView ที่เขียนว่า Hello World!
แต่ผมต้องการ LinearLayout ที่ทำ ScrollView ได้
จึงสร้าง content1_main.xml
โดยมี Hierarchy ของ Layout สำหรับ 6 คู่ ดังนี้

 <LinearLayout orientation="vertical">
 <LinearLayout>
 <TextView text="@string/information">
 </LinearLayout>
 <ScrollView>
 <LinearLayout orientation="vertical">
 <LinearLayout orientation="vertical">
 <TextView drawableStart />
 <TextView drawableStart />
 <ImageView />
 <TextView />
 </LinearLayout>
 <LinearLayout orientation="horizontal">
 <ImageView />
 <TextView />
 </LinearLayout>
 <RelativeLayout>
 <ImageView />
 <TextView />
 </RelativeLayout>
 <RelativeLayout>
 <ImageView id="@+id/imageView2" />
 <TextView layout_toEndOf="@+id/imageView2" />
 </RelativeLayout>
 </LinearLayout>
 </ScrollView>
 </LinearLayout>

ถ้าดูผลลัพธ์จากกภาพ ดูโครงสร้าง และเห็น code น่าจะนำไปใช้ต่อได้

https://gist.github.com/thaiall/304e6ddd917dd0350aa57fba72955082

3. ใส่ Activity ให้กับ Menu ใน Toolbar บน AppBarLayout
มีขั้นตอนดังนี้
3.1 วางแผนไว้ในใจ ว่าคลิ๊ก 3 จุดที่มุมบนขวา แล้วมีเมนูไหลลงมา
อยากเห็นอะไร ก็ให้เปิด app, res, menu, menu_main.xml
จากนั้นก็เพิ่มตัวเลือกตาม item ที่ต้องการ แต่ title ต้องเปิดแฟ้ม strings.xml พิมพ์ไปพร้อมกัน

<item
 android:id="@+id/content1"
 android:orderInCategory="100"
 android:title="@string/content1"
 app:showAsAction="never" />

 

https://gist.github.com/thaiall/eb8137794add90145d19daa9d1c2c0d8

3.2 เปิด MainActivity.java ขึ้นมาแก้ไข
มองหา method ชื่อ onOptionsItemSelected(MenuItem item)
เดิมจะมี if (id == R.id.action_settings) ผมก็เปลี่ยนไปใช้ switch จะได้สะดวก
ตัวอย่างนี้ต้องปรับการใช้ include ใน activity_main.xml

switch (item.getItemId()) {
 case R.id.content1:
 findViewById(R.id.content1).setVisibility(View.VISIBLE);
 findViewById(R.id.content2).setVisibility(View.GONE);
 return true;
 case R.id.content2:
 findViewById(R.id.content1).setVisibility(View.GONE);
 findViewById(R.id.content2).setVisibility(View.VISIBLE);
 return true;
 case R.id.layoutRuntime:
 layoutRuntime();
 return true;
 default:
 return super.onOptionsItemSelected(item);
 }

 

3.3 แก้ไขการ include เพราะสั่งไปว่าจะ visible หรือ gone

มองหา
 <include layout="@layout/content_main"
เปลี่ยนเป็น
 <include
 android:id="@+id/content1"
 layout="@layout/content1_main"
 android:visibility="visible" />
 <include
 android:id="@+id/content2"
 layout="@layout/content2_main"
 android:visibility="gone" />

 

https://gist.github.com/thaiall/e55bca08d5927c97dd2dec5367771085

 

4. การสร้าง layout at runtime เพื่อ say hello
เนื่องจากที่ผ่าน 8 ตอนเป็นการใช้โปรแกรม Android Studio
ผ่าน Main_Activity.java เท่านั้น และ layout ก็ไม่ได้มีเพิ่มขึ้นเป็นพิเศษ
ไม่มีการควบคุม Layout ผ่าน Main java เลย
แต่ code สร้าง Layout at runtime สำหรับ
ท่านที่ต้องการ Layout แปลกใหม่ กว่าที่มีไว้ ก็สร้างช่วง Runtime ได้
ได้ตัวอย่างมาจาก
http://www.android-examples.com

private void layoutRuntime() {
 LinearLayout linearLayout = new LinearLayout(this);
 TextView ProgrammaticallyTextView = new TextView(this);
 ProgrammaticallyTextView.setText(R.string.helloworld);
 ProgrammaticallyTextView.setTextSize(16);
 ProgrammaticallyTextView.setPadding(30, 250, 30, 100);
 linearLayout.addView(ProgrammaticallyTextView);
 this.setContentView(linearLayout, new LinearLayout.LayoutParams(
 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
 }

 

5. สร้าง Layout สำหรับแสดง ImageView โดยเฉพาะ
ใช้ภาพตัวอย่างจาก http://www.thaiall.com/actress/missgrand2017/
หากมีข่าวประกาศ หนังสือ รายงาน พรบ. หรือภาพสาวงาม จะนำมาเรียงต่อกัน
ให้เพื่อนชมผ่าน app บน Android ก็ส่งเข้าไปเลยครับ
ตอนผมทดสอบบน Smartphone มีปัญหาเรื่องจำนวนภาพเยอะ
ใช้ภาพเยอะ ๆ แล้ว error ส่งผ่าน Command line
เชื่อมผ่านเปิดแอพ WiFi ADB ซึ่งบนนั้นอาจมี Bug น่ะครับ
แต่แฟ้ม app-debug.apk นี้ส่งเข้า emulator ได้ผลปกติ
เรื่องสำคัญ คือ properties ของ ImageView เพื่อให้ลงจอภาพพอดี
โดยเฉพาะ scaleType กับ adjustViewBounds

<LinearLayout orientation="vertical">
 <ScrollView>
 <LinearLayout orientation="vertical">
 <ImageView
 android:id="@+id/imageView1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:scaleType="fitCenter"
 android:adjustViewBounds="true"
 android:contentDescription="@string/data"
 app:srcCompat="@drawable/thai1" />
 </LinearLayout>
 </ScrollView>
 </LinearLayout>

 

https://gist.github.com/thaiall/41e86984b4cabe35392e29fc05107f60

</process>

<website_guide>
+ https://developer.android.com/training/basics/firstapp/
+ http://www.techotopia.com/..User_Interface_in_Java_Code
+ https://stackoverflow.com/..without-setcontentviewr-layout-main
+ https://stackoverflow.com/..button-click-in-android
+ https://stackoverflow.com/..when-button-is-pressed
+ https://stackoverflow.com/..layout-in-android (viewstub)
+ https://developer.android.com/../declaring-layout
+ https://www.androidhive.info/..design-snackbar-example/
+ http://www.android-examples.com/..programmatically-example/
+ https://stackoverflow.com/..layout-on-java-code (setVisibility(View.GONE); and <ViewFlipper>)
+ https://developer.android.com/training/appbar/actions.html
+ https://developer.android.com/guide/topics/ui/menus.html
</website_guide>

หมายเหตุ 
ถ้าสนใจติดตามเนื้อหาในบล็อกนี้ สามารถ subscribe ด้วย email ที่อยู่ข้างขวา หรือ click here

#AndroidStudio ตอนที่ 8.1 สิ่งที่ทำได้ และไม่ได้ในการใช้ HTML ใน TextView

#AndroidStudio ตอนที่ 8.1 สิ่งที่ทำได้ และไม่ได้ในการใช้ HTML ใน TextView  

<introduction>
หลังทบทวนที่ได้ใช้โปรแกรม Android Studio แล้วพบ ปัญหา และทางออกในหลายวิธี แล้วแบ่งปันในกลุ่มเฟส สมาคมโปรแกรมเมอร์ไทย ก็มีเพื่อนมาร่วมแลกเปลี่ยน แชร์โฮมเพจดี ๆ มาให้อ่าน หลังเขียนเรื่องที่อยากเขียนแล้ว ก็นำเรื่องที่อ่านเพิ่มเติมมาเขียนในข้อที่ 8 มีอะไรอีกมากที่ต้องเรียนรู้ ทั้ง 1) properties อีกอื้อ 2) ต้องเปลี่ยนตนเองตามการเปลี่ยนรุ่นของเครื่องมือ 3) การเลือกใช้เครื่องมือที่เหมาะสมกับงาน

Google เจ้าของ Android Studio ได้เตรียมเครื่องมือไว้เยอะ บางเรื่องบางงานก็ใช้ได้หลายเครื่องมือ ยกตัวอย่างง่าย ๆ สำหรับงานง่าย ๆ ก็มี layout ให้เลือกตั้งเยอะ และตอบโจทย์สำหรับงานง่ายได้ทุก layout แต่ถ้าต้องออกแบบ layout เชิงลึกถึงจะเห็นว่างานแบบลึกนั้น จะต้องใช้ layout แบบใดที่มีคุณสมบัติเฉพาะ และใช้ layout แบบอื่นไม่ได้จริง ๆ

TextView ไม่รองรับ HTML แต่โดยดี จึงมีเรื่องมาเล่า ดังนี้ 1) ใส่ HTML Tag เข้า TextView ใน Layout โดยตรง 2) ใส่ HTML Tag ใน string ที่อยู่ใน strings.xml แล้วอ้างอิงจาก Textview ใน layout 3) การส่ง img ใน strings.xml ไป TextView ใน layout ที่แสดงผลเฉพาะตัวอักษรหนา ส่วนภาพไม่ออก 4) การส่ง img ใน MainActivity.java ไป TextView ผ่าน ImageGetter แบบใช้ได้ 5) การส่ง img ใน strings.xml เข้า MainActivity.java ไป TextView ผ่าน ImageGetter แบบใช้ได้ 6) การส่ง img ใน strings.xml เข้า MainActivity.java ไป TextView ผ่าน ImageGetter แบบสั่ง replace แทนกำหนด Html Tag 7) ปรับ ImageGetter กันดีกว่า 8) การใช้ drawableStart แทน drawableLeft

</introduction>

กำลังเล่าเรื่อง การใช้โปรแกรม Android Studio สู่เพื่อนนักพัฒนา ผ่าน Blog

<process>

1. ใส่ HTML Tag เข้า TextView ใน Layout โดยตรง

ต.ย.1 การใช้ HTML Tag ใน TextView แบบนี้ไม่ได้ เกิด Error : Build ไม่ผ่าน

android:text="<b>hello</b>"

ต.ย. 2 การใช้ Entity Reference ใน TextView แบบนี้ไม่ได้ เกิด Error : Build ไม่ผ่าน

android:text="&lt;b>hello&lt;/b>"

ต.ย. 3 การอ้างอิงข้อมูลมาใช้ ต้องเคยถูกประกาศไว้ใน strings.xml จึงจะถูกต้อง แบบนี้ดี

android:text="@string/data1"

2. ใส่ HTML Tag ใน string ที่อยู่ใน strings.xml แล้วอ้างอิงจาก Textview ใน layout 

การใช้ HTML เขียนใน strings.xml แล้วอ้างไปแสดงผลใน layout.xml ทันที แบบนี้ เป็นวิธีที่ถูกต้อง มีคำแนะนำไว้ใน guide ของ  android.com ว่าสามารถใช้ <b> <i> หรือ <u> ได้ เพื่อประกอบการแต่ข้อความที่แสดงใน TextView

ปัญหา คือ การใส่ img หรือภาพไปพร้อมข้อความใน TextView ต้องเพิ่ม code พิเศษ

<string name="data"><b>hello world</b></string>
android:text="@string/data"

3. การส่ง img ใน strings.xml ไป TextView ใน layout ที่แสดงผลเฉพาะตัวอักษรหนา ส่วนภาพไม่ออก

แบบนี้ไม่พบ error แต่ภาพไม่แสดง ต้องมี code มาช่วย จึงจะแสดงภาพใน TextView

<string name="data"><b>hello world</b> <img src="lp01" /></string>

4. การส่ง img ใน MainActivity.java ไป TextView ผ่าน ImageGetter แบบใช้ได้

บรรทัดที่ 46 มี HTML Tag ที่ทำให้ ตัวอักษรหนา และเรียกภาพมาแสดงได้จริง
ประกาศข้อมูลแบบ String ที่อยู่ภายใน MainActivity.java เอง
แบบที่่ 1 ที่ใช้งานได้ build ผ่าน และแสดงผลถูกต้อง

String mData = "<b>hello</b> <img src=\"lp01\" />";

แบบที่่ 2 ที่ใช้งานได้ เหมือนแบบแรก

String mData = "<b>hello</b> <img src=lp01 />";

แบบที่่ 3 ที่ใช้งานได้ เหมือนแบบแรก

String mData = "<b>hello</b> <img src='lp01' />";

แบบนี้ error ต้องแก้ไขทันที

String mData = "<b>hello</b> <img src="lp01" />";

บรรทัดที่ใช้ได้ทั้ง 3 ตัวอย่างข้างต้น
จะถูกส่งต่อไปให้ class ImageGetter ที่ประกาศใต้ class MainActivity
ก่อนจะส่งภาพให้ TextView ที่อยู่ใน Layout จะใช้ setText( .. )
ก็ต้องแปลงข้อมูลกันก่อน ด้วย Html.fromHtml( .. ) และใช้ ImageGetter ที่นี่
แต่ fromHtml มีหลายรุ่น จึงใช้ IF ตรวจสอบว่ารุ่นไหน ต้องเรียกใช้แบบใด

htmlTextView.setText(Html.fromHtml(mData, new ImageGetter(),null)); 

ตัวอย่าง Code ทั้งหมด 55 บรรทัดที่ใช้ใน MainActivity.java อยู่ข้างล่างนี้

https://gist.github.com/thaiall/bcd1c4a61fd16bf1cfb5dd32fc274d93

5. การส่ง img ใน strings.xml เข้า MainActivity.java ไป TextView ผ่าน ImageGetter แบบใช้ได้

เปลี่ยนจากการกำหนดค่าคงที่ (Constant) เป็นการอ้างอิงค่า (Reference) จาก R.string.data หากไม่แก้ไข MainActivity.java อีก มาดูกันว่าต้องกำหนดข้อมูลใน strings.xml อย่างไร เพื่อทำให้แสดงภาพใน TextView

String mData = res.getString(R.string.data);

ใช้ Entity Reference คือ &lt; ทำให้ภาพออก เห็นตัวอักษา แต่ตัวอักษาไม่หนา

<string name="data"><b>hello</b> &lt;img src="lp01" /></string>

ใช้ Entity Reference คือ &lt; แทน < ทำให้เห็นทั้งภาพ และตัวอักษรหนา

<string name="data">&lt;b>hello&lt;/b> &lt;img src="lp01" /></string>

ใช้ Entity Reference คือ &lt; แทน < แบบไม่มี Quote  หรือ “” ก็ได้

<string name="data">&lt;b>hello&lt;/b> &lt;img src=lp01 /></string>

 

6. การส่ง img ใน strings.xml เข้า MainActivity.java ไป TextView ผ่าน ImageGetter แบบสั่ง replace แทนกำหนด Html Tag

หากไม่ต้องการใช้ HTML Tag ระบุชื่อภาพ แต่ใช้การแทนที่ ก็สามารถเพิ่ม code ใน MainActivity.java ได้ โดยมีตัวอย่างข้อมูลใน strings.xml ดังนี้

 <string name="data">pic01 pic02 pic03</string>

เพิ่มคำสั่ง for สั่ง replace ข้อมูลใน mData หากพบ pic0 ก็ให้เปลี่ยนเป็น Img Tag ตามรูปแบบที่ต้องการ ถือเป็นการลดรูปของข้อมูลภาพใน strings.xml ไม่ต้องพิมพ์ยาว ๆ

String mData = res.getString(R.string.data);
for(int i=1;i<=3;i++) {
 mData = mData.replace("pic0" + i, "<img src=lp0" + i + " />");
}

หากกำหนดข้อมูลใน strings.xml ให้ตัวอักษรเข้ม และปัดบรรทัด
ยังต้องใช้ Entity Reference คือ &lt; แทนเครื่องหมาย < ดังอธิบายในข้อ 5

<string name="data"><b>hello</b><br/>pic01</string>

แม้จะใช้คำสั่ง replace แทนที่ < เป็น &lt; ก็ไม่ทำให้ผลลัพธ์เปลี่ยนแปลง
เหมือนกับไม่เกิดการแทนที่เกิดขึ้น ก็เพียงแต่เล่าว่า วิธีนี้ใช้มาแล้ว

mData = mData.replace("<", "&lt;");
mData = mData.replace("<b>", "&lt;b>");

แล้วถ้าข้อมูลพิมพ์ [ แทนเครื่องหมาย < แล้วสั่ง replace
ผลลัพธ์จะออกมาเป็นการแสดง source code คือ <b>hello</b><br/>และภาพ

<string name="data">[b>hello[/b>[br/>pic01</string>
mData = mData.replace("[", "&lt;");

7. ปรับ ImageGetter กันดีกว่า

7.1 บรรทัดที่ 34 คือ setBounds (.. )
เนื่องจากผมเขียนโปรแกรมทดสอบเกี่ยวกับภาพ เห็นว่าภาพใหญ่เกินไป
จึงปรับให้ขนาดเล็กจิ๋ว กว้าง 48 * 2 =96 pixel สูง 64 *2 =128 pixels
ถ้าต้องการใช้ความกว้างสูงของตัวภาพ แล้วทำให้ใหญ่ 2 เท่า หรือเล็กครึ่งหนึ่ง ก็ทำได้

d.setBounds(0,0,d.getIntrinsicWidth(), d.getIntrinsicHeight());

7.2 หากจะปรับขนาดภาพให้เป็นตามชื่อภาพ
เราก็มีชื่อภาพในตัวแปร source แก้โปรแกรม โดยเปลี่ยนบรรทัด 34 เป็น 4 บรรทัดข้างนี้
แล้วปรับขนาดได้ตามชอบใจ

if(source.equals("lp01"))
    d.setBounds(0,0,48 * 2, 64 * 2);
else
    d.setBounds(0,0,300, 400);

7.3 ปรับการตรวจสอบ id
ตรวจสอบค่าของ getPackageName(); พบมีค่า com.thaiall.www.myapplication
ทำให้โปรแกรมที่เขียนขึ้นสามารถบรรทัดที่ 18 – 21 เพราะมีบรรทัดที่ 17 อยู่แล้ว

String p = getPackageName();

8. การใช้ drawableStart แทน drawableLeft
ได้แชร์ blog ตอนที่ 8 ในเฟสกลุ่ม สมาคมโปรแกรมเมอร์ไทย
แล้วคุณ Somkiat Ake Khitwongwattana แนะนำให้อ่าน Advance Android TextView ที่เขียนโดย Chiu-Ki Chan พอเข้าไปก็เห็นว่ามีคุณสมบัติที่ชื่อ drawableTop, drawableBottom และอีกเยอะที่ทดสอบแล้วใช้ได้เลยใน TextView แต่ drawableLeft ที่น่าจะใช้ได้พบว่า Android Studio ที่ผมใช้เค้าให้เปลี่ยนเป็น drawableStart และ drawableEnd ซึ่งเป็นการเปลี่ยนแปลงตลอดระหว่างการเปลี่ยนรุ่นของเครื่องมือที่ใช้พัฒนา นี่เป็นตัวอย่าง code ที่ปรับมาจากคำแนะนำที่ไปอ่านมา และผมไม่ใช้ lp01 เพราะรูปใหญ่เกิน จึงเลี่ยงไปใช้ ic_insert_emoticon_black_24dp และใน Page ของ Chiu-Ki Chan ยังมี Guide ที่น่าสนใจอีกมาก

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/app_name"
    android:drawableStart="@drawable/ic_insert_emoticon_black_24dp"
    android:drawableEnd="@drawable/ic_insert_emoticon_black_24dp"
    android:drawableTop="@drawable/ic_insert_emoticon_black_24dp"
    android:drawableBottom="@drawable/ic_insert_emoticon_black_24dp" />

</process>

สรุปว่าวิธีที่ใส่ภาพ และ html อยู่ข้อ 5 
ส่วนข้อ 6 เป็นการเล่าเพิ่มเติม เรื่อง code

<website_guide>
http://chiuki.github.io/advanced-android-textview/#/
</website_guide>

หมายเหตุ 
ถ้าสนใจติดตามเนื้อหาในบล็อกนี้ สามารถ subscribe ด้วย email ที่อยู่ข้างขวา หรือ click here