วันอาทิตย์ที่ 20 ธันวาคม พ.ศ. 2558

การใช้ checkBox ใน listView ด้วย customAdapter

โดยปกติ ถ้าใช้ listView เราจะเรียกใช้ adapter ที่มากับ Android Studio คือ android.R.layout.simple_list_item_1 แต่ Adapter ตัวนี้ ใช้ได้เฉพาะกับ ข้อมูลใน listView ที่เป็นตัวอักษร เท่านั้น ถ้าต้องการให้มีภาพ หรือ อย่างอื่น ๆ เช่น checkBox หรือ RadioBox หรือ จัดรูปแบบให้หลากหลาย ก็ไม่สามารถทำได้ เราจึงต้องสร้างรูปแบบเอง และสร้าง Adapter ขึ้นเอง ซึ่งเรียกว่าเป็น customAdapter

ในตัวอย่างต่อไปนี้ จะเป็นการสร้าง listView ที่ประกอบด้วย checkBox และข้อความ ดังภาพ

มีขั้นตอนหลัก ๆ ดังนี้

  1. สร้าง Project ใหม่
  2. สร้าง Activity แรก และสร้าง Activity สำหรับหน้าเมนูหลักเพื่อเรียกใช้งาน listBox
  3. สร้าง layout ที่จะใช้เป็นรูปแบบของ listView ในแต่ละรายการ หรือ item ที่ประกอบด้วย checkBox และ textBox หรือกล่องข้อความ ที่จะปรากฏใตแต่ละรายการ
  4. สร้างไฟล์ java หรือ Class ใหม่ เพื่อให้เป็น customAdapter เพื่อ แปลง หรือปรับข้อมูลที่มีทั้ง checkBox และ  textBox พร้อมทั้งเรียกใช้งานใน Activity ที่ต้องการใช้ listView
วิธีการ

การสร้าง Project ใหม่
  1. สร้าง Project ใหม่ ในตัวอย่างนี้ใช้ Android Studio 1.5.1 สร้าง Project ใหม่ ระบุ API 11 และใช้ Blank Activity ซึ่ง Android Studio จะสร้างไฟล์ต่าง ๆ ให้พร้อมใช้งาน ในตัวอย่างนี้ จะใช้งาน listView ใน Activity ที่ชื่อว่า Menu_Page ดังนี้ โดยคลิกปุ่มหน้าแรก แล้วให้มาที่หน้า Menu_Page
    ส่วนวิธีการที่จะสร้างหน้าแรกอย่างไร จะไม่พูดถึง แต่จะเริ่มที่หน้า Menu_Page ที่จะแสดง listView เท่านั้น
การสร้าง Activity เพื่อเรียกใช้งาน listView
  1. สร้าง Activity หลัก โดยมีปุ่มสำหรับเมื่อกดแล้วจะมาที่ หน้าเมนูหลัก ซึ่งเรียกใช้งาน listView
  2. สร้างหน้าหน้าเมนูหลัก เพื่อใช้งาน listView โดยคลิกขวาที่ห้อง jave สำหรับไฟล์ของ Project และเลือก New > Activity >BlankActivity
  3. ตั้งชื่อว่า Menu_Page
  4. ไปที่ res > layout จะเห็นมีไฟล์ layout สำหรับ Activity ที่สร้างใหม่ 
  5. ลาก Large Text Widget และ ListView มาวาง พร้อมทั้งเปลี่ยนข้อความของ Large Text ตามต้องการ Layout นี้ จะเป็นหน้าจอหลักสำหรับเมนู 
  6. กำหนด id ของ TextView ว่า textView และ ListView ว่า menuList
  7. ไปที่ห้อง java เพื่อเขียนโค้ดในไฟล์ Menu_Page
  8. ให้ extends  AppCompatActivity เพื่อให้ครอบคลุม API รุ่นเก่าได้ ถึง API 7  
  9. กำหนดตัวแปร ListView, ArrayAdapter และตัวแปรที่เป็น Array ชื่อชุดข้อสอบ
    ListView listView;
    ArrayAdapter adapter;
    
    String[] mainMenuItems ={"Vocabulary","Vocab ชุดที่ 1","Vocab ชุดที่ 2","Vocab ชุดที่ 3","Grammar","Tense","Articles","Conversations","บทสนทนา ชุดที่ 1","บทสนทนา ชุดที่ 2","บทสนทนา ชุดที่ 3","Reading Passages","บทอ่าน ชุดที่ 1","บทอ่าน ชุดที่ 2","บทอ่าน ชุดที่ 3","รวมชุดข้อสอบ","ข้อสอบ ชุดที่ 1","ข้อสอบ ชุดที่ 2","ข้อสอบ ชุดที่ 3"};

  10. ใน on Create method ให้กำหนดให้ใช้ Layout ที่สร้างขึ้น และสัมพันธ์ id กับตัวแปรที่กำหนดขึ้น
     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_menu__page);
            listView = (ListView)findViewById(R.id.menuList );

  11. ค้างไว้แค่นี้ก่อน เพื่อไปจัดการกับ CustomAdapter
การสร้าง layout ที่จะใช้เป็นรูปแบบของ listView ในแต่ละรายการ หรือ item
  1. คลิกขวาที่ layout ในห้อง res และเลือก New > Layout resource file
  2. ตั้งชื่อไฟล์ ว่า simplerow
  3. กำหนดให้ใช้ Linear Layout กำหนดให้เป็นการเรียงแบบ Horizontal เพื่อให้ checkBox อยู่ทางซ้าย และ TextView อยู่ทางขวา โดยไปปรับ orientation ใน Code ของ Text ดังนี้
    xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent"> 
  4. ลาก checkBox และ Text View มาวาง 
  5. กำหนด id ของ checkBox ว่า chkBox และ กำหนด id  ของ TextView ว่า examName
การสร้างไฟล์ java  Class ใหม่ เพื่อให้เป็น customAdapter

ไฟล์ที่เป็น Adapter จะทำหน้าที่แปลงข้อมูล ในรูปแบบอื่น เช่น Array เพื่อให้เป็นข้อมูลใน listBox ในกรณีนี้ จะนำเอา checkBox และ TextView มาเป็นข้อมูลในรายการของ listView สำหรับ TextView จะให้รับค่ามาจาก Array ที่เป็นชื่อข้อสอบ ดังนั้น ในแต่ละรายการใน ListView จะประกอบไปด้วย checkBox และชื่อของข้อสอบ ที่ไม่ซ้ำกันในแต่ละรายการ
  1. คลิกที่ห้องเก็บ Project file ในห้อง java เลือก New > Class
  2. ตั้งชื่อไฟล์ java ว่า ClassAdapter
  3. ให้ extends ArrayAdapter ที่เป็น String เพื่อรับค่าตัวแปร Array ที่เป็นชื่อวิชา ถ้าไม่กำหนดให้เป็น String จะได้เป็น Object ซึ่งจะมีปัญหาตอนกำหนดให้รับค่าตัวแปร Array ชื่อวิชา

    class CustomAdapter extends ArrayAdapter{
    
    
  4. ใน Class นี้ กำหนด method ให้เลือกใช้ simplerow layout และให้สร้างหน้าจอ ListView โดยการ override onGetView() และกำหนดค่า โดยใช้ค่าที่เราได้กำหนดไว้แล้ว โดยสรุป คือ เขียนโค้ด ดังนี้

    import android.content.Context;
    import android.text.Layout;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.CheckBox;
    import android.widget.TextView;
    
    class CustomAdapter extends ArrayAdapter{
    
        public CustomAdapter(Context context, String[] mainMenuItems) {
           super(context,R.layout.simplerow,mainMenuItems);
        }
    
        @Override    public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater = LayoutInflater.from(getContext());
            View customView = inflater.inflate(R.layout.simplerow, parent, false);
    
            String singleRow = getItem(position);
            TextView examName = (TextView)customView.findViewById(R.id.examName);
            CheckBox checkBox = (CheckBox)customView.findViewById(R.id.chkBox);
    
            examName.setText(singleRow);
            checkBox.isChecked();
    
            return customView;
    
        }
    }
  5. กลับมาที่ Menu_Page.java เพื่อทำงานต่อ โดยสั่งให้ใช้ CustomAdapter พร้อมทั้งกำหนดว่า เมื่อคลิกที่ ListView แล้วจะให้ทำอะไร ในตัวอย่างนี้ เมื่อคลิกแล้วให้แสดงข้อความขึ้นหน้าจอ โดยใช้ Toast() โดยสรุป ใน onCreate method เขียนโค้ด ดังนี้

    @Overrideprotected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_menu__page);
        listView = (ListView)findViewById(R.id.menuList );
    
        adapter = new CustomAdapter(this,mainMenuItems);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    
            @Override        public void onItemClick(AdapterView parent, View view, int position, long id) {
    
                switch (position) {
                    case 0:
                        Toast.makeText(Menu_Page.this, "คลิกรายการที่ " + position, Toast.LENGTH_LONG).show();
                        break;
                    case 1:
                        Toast.makeText(Menu_Page.this, "คลิกรายการที่ " + position, Toast.LENGTH_LONG).show();
                        break;
                    case 2:
                        Toast.makeText(Menu_Page.this, "คลิกรายการที่ " + position, Toast.LENGTH_LONG).show();
                        break;
                    case 3:
                        Toast.makeText(Menu_Page.this, "คลิกรายการที่ " + position, Toast.LENGTH_LONG).show();
                        break;
    
                }
            }
        });
    }
    
เป็นอันเสร็จการเรียกใช้งาน CustomAdapter ที่สร้าง ListView ซึ่งประกอบด้วย checkBox และข้อความในแต่ละรายการ เมื่อ Run ดูและคลิกเลือกที่รายการ จะได้ ดังนี้

ดาวน์โหลดไฟล์ตัวอย่าง คลิกที่นี่

วันพุธที่ 16 ธันวาคม พ.ศ. 2558

การส่งออกบางส่วนของภาพ ใน illustrator cs6

สมมุติว่า เราทำ Logo หลายชิ้น ใน Adobe Illustrator CS6 และต้องการบันทึกออกเป็นไฟล์ PDF หรือไฟล์นามสกุลอื่น หรือ ต้องการส่งออกไปยังโปรแกรม Photoshop แต่ต้องการส่งออกเฉพาะบาง Logo เท่านั้น จะทำอย่างไร

ในภาพ ต้องการส่งออก หรือบันทึกเป็นไฟล์เฉพาะโลโก้ด้านซ้ายมือ ที่มีกรอบเป็นสีเหลือบเท่านั้น จะทำอย่างไรดี

มีวิธีหลายวิธี แต่วิธีที่ง่ายที่สุดคือการจัด Artboard ให้คลุมเฉพาะโลโก้ที่ต้องการ แล้วจึงส่งออก หรือบันทึกเป็นไฟล์อื่น ๆ ตามต้องการ

วิธีการ

  1. คลิกเลือกเฉพาะโลโก้ที่ต้องการส่งออก โดยใช้ Selection Tool ลากให้คลุม Artwork ที่ต้องการ
  2. จะได้ดังภาพ
  3. ไปที่ Object > Artboards > Fit to Selected Art
  4. Artboard จะย่อขนาดลงเท่ากับโลโก้ที่เลือกเอาไว้แล้ว
  5. ไปที่เมนู File > Save As... หรือ File > Export...
    • Save As เพื่อบันทึกเป็นไฟล์ของ illustrator หรือ PDF หรือ อื่น ๆ 
    • Export เพื่อส่งไปยัง Photoshop หรือ Flash หรือส่งออกเป็นภาพ BMP, JPG, WMF สำหรับ Windows Media หรือ เป็นไฟล์นามสกุลอื่น ๆ
  6. ภาพต้วอย่างส่งออกเป็น PDF
ส่วนวิธีอื่น ๆ เช่น เลือก Artwork ทั้งหมด แล้ว Shift Click เพื่อยกเลิกการเลือกเฉพาะ Artwork ที่ต้องการส่งออก แล้วไปที่ Object > Hide เพื่อซ่อน Artwork ที่ไม่ต้องการ แล้วจึงบันทีก หรือส่งออก

อีกวิธีคือ การเลือกเฉพาะ Artwork ที่ต้องการ แล้ว Cut และเปิดโปรแกรม illustrator ใหม่ แล้ว Paste เข้ามาอีกที

แต่คิดว่าวิธีที่ดีที่สุด คือ จัดการ Artboard เพราะจะได้ขนาดภาพตามที่ต้องการ ดังที่เห็นในภาพจากไฟล์ PDF 

วันอังคารที่ 15 ธันวาคม พ.ศ. 2558

การบันทึกอีแมล์ Gmail เป็นไฟล์ PDF

มีบางโอกาสที่เราจำเป็นต้องส่งไฟล์อีเมล เป็นไฟล์แนบกับจดหมายอีเมล ทำให้เราจำเป็นต้องบันทึกจดหมายอีเมลเป็นไฟล์ PDF เพื่อแนบจดหมายอีเมลอีกทีหนึ่ง ในที่นี้ จะใช้กับ Gmail เท่านั้น ส่วน อีเมลอื่น ๆ มีวิธีการที่แตกต่างกันไป

วิธีการ

  1. เข้าไปที่กล่องจดหมาย และเปิดจดหมายที่ต้องการบันทึกเป็นไฟล์ PDF
  2. คลิกปุ่ม เพิ่มเติม ซึ่งเป็นปุ่มสามเหลี่ยมชี้ลง ข้าง ๆ ลูกศรตอบกลับ
  3. เลือก พิมพ์
  4. จะเกิดหน้าจอให้ตั้งค่า พร้อมทั้งนำจดหมายอีเมลที่จะบันทึกเป็นไฟล์ PDF มาแสดงให้ดูด้วย  เสร็จแล้วกดปุ่ม บันทึก
  5. ระบุที่เก็บไฟล์ เพื่อจะได้นำไปเป็นไฟล์แนบ ต่อไป


วันจันทร์ที่ 14 ธันวาคม พ.ศ. 2558

onSaveInstanceState()

การพัฒนา Application สำหรับ Android phone มีประเด็นที่จะต้องจัดการด้วยตัวเองอย่างหนึ่งคือ เวลาผู้ใช้งานเปลียนมือถือ จากแนวตั้งเป็นแนวนอน โปรแกรมจะปรับสภาพไปสู่สภาพเดิม เหมือนเมื่อเริ่มต้นเข้ามาที่หน้าจอใหม่ ๆ ที่เป็นเช่นนี้ เพราะ Android Studio ต้องการปรับสภาพให้เข้ากับสภาวะใหม่ ดังนั้น เราจึงต้องจัดการ บันทึกสภาพปัจจุบันของหน้าจอเอาไว้ และเมื่อมีการปรับเปลี่ยนสภาพใหม่ ก็ให้ตรวจสอบข้อมูลเดิมพร้อมทั้งบันทึกเอาไว้ และนำกลับมาใช้ให้เหมือนเดิม มิฉะนั้นผู้ใช้อาจจะงงว่า ทำไมข้อมูลหน้าจอจึงเปลี่ยนไป

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

การจัดเก็บสภาพของหน้าจอ ด้วย onSaveInstanceState()

ในกรณีตัวอย่างข้อสอบข้างต้น มีการกำหนดตัวแปรคือ thisQuestionNum เพื่อเก็บหมายเลขข้อของข้อสอบ เพื่อนำข้อสอบมาแสดงตามหมายเลขนั้น ๆ โดยเริ่มต้นจากข้อ 1 และ ผู้ใช้สามารถคลิกเพิ่มไปดู ข้อ 2,3,4  ... ได้ตามลำดับ ซึ่งจะทำให้ค่าของตัวแปร thisQuestionNum เปลี่ยนไป ตามที่ผู้ใช้คลิก

ดังนั้น การจัดเก็บสภาพจึงต้องจัดเก็บค่าของตัวแปร thisQuestionNum  และนำไปใช้ เมื่อมีการ Create หน้าจอนี้

การจัดเก็บสภาพ ให้กำหนดเป็น Method ใหม่ อยู่นอก onCreate() method ดังนี้

@Overrideprotected void onSaveInstanceState(Bundle outState) {
    outState.putInt("thisQuestionNum", thisQuestionNum);
    super.onSaveInstanceState(outState);
}

การจัดเก็บข้อมูล จะเก็บไว้ใน Bundle Object และเนื่องจาก thisQuestionNum เป็นตัวเลข จึงต้องใช้ .putInt เพื่อเก็บข้อมูล การจัดเก็บจะเก็บในลักษณะ Name:Value pair โดยที่เมื่อจะเรียกใช้ จะเรียกชื่อที่อยู่ในเครื่องหมายคำพูด

Android จะเรียกใช้ Method นี้ ก่อนที่หน้าจอจะหมดสภาพ หรือ ถูก destroy และเมื่อเริ่มต้นใหม่ โดยปกติ Android จะมีการตรวจสอบอยู่แล้วใน onCreate() method 

@Overrideprotected void onCreate(Bundle savedInstanceState) {

.....
}

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

@Overrideprotected void onCreate(Bundle savedInstanceState) {

    if (savedInstanceState != null) {
        // ใช้ค่าที่เก็บไว้        thisQuestionNum = savedInstanceState.getInt("thisQuestionNum");
    } else {
        // กำหนดเป็นค่าเริ่มต้น        thisQuestionNum = 0;
    }

    super.onCreate(savedInstanceState);

......

}

เมื่อมีการเปลี่ยนแนวหน้าจอ ข้อมูลจะไม่เปลี่ยนไป ข้อมูลจะเหมือนเดิม ไม่ว่าจะเป็นแนวตั้ง หรือแนวนอน ก็ตาม




วันเสาร์ที่ 12 ธันวาคม พ.ศ. 2558

การสร้าง DialogFragment ใน Android Studio

การสร้าง Dialog เพื่อแสดงข้อความแจ้งเตือน หรือให้ข่าวสารแก่ผู้ใช้งานมือถือ Android โดยใช้  Android Studio ทำได้หลายอย่าง แต่วันนี้ จะพูดถึงการใช้ Fragment สำหรับสร้าง Dialog ซึ่งมีข้อดี คือ สามารถจัดการรูปแบบได้เองสะดวกดี เพราะใช้ Layout ที่สร้างเอง จึงนำเอาภาพ ข้อความมาจัดเรียงได้ ในตัวอย่างนี้ จะสร้าง DialogFragment โดยให้คลิกจากเมนูใน OverFlow Menu แล้วมาที่ Dialog ที่สร้างขึ้น โดยใช้ Android Studio 1.5.1

ภาพหน้าจอ DialogFragment ที่จะสร้าง ในครั้งนี้

ขั้นตอนการสร้าง

  1. สร้าง Project ใหม่
  2. สร้าง Layout ที่ต้องการให้แสดงเป็น Dialog
  3. สร้าง Java Class สำหรับ DialogFragment
  4. เรียกใช้งาน ที่ OverFlow menu
สร้าง Project ใหม่
  1. สร้าง Project ใหม่ ตั้งชื่อตามต้องการ
  2. กำหนด API 11 และ Blank Activity
สร้าง Layout สำหรับให้แสดงเป็น Dialog
  1. นำภาพไปใส่ไว้ในห้อง Drawable โดยใช้วิธี Copy แล้ว Paste ใน Android Studio
  2. สร้าง Layout โดยคลิกขวาที่ layout เลือก New > Layout Resource File
  3. ตั้งชื่อว่า df_demo  
  4. นำ ImageView  TextView และปุ่ม พร้อมทั้งนำภาพและข้อความมาวางบน Layout ดังภาพ
    • TextView ให้กำหนด LayoutWidth เป็น match parent และ กำหนด padding ตามต้องการ  ในตัวอย่างใช้ TextView จำนวน 3 TextView
    • สำหรับปุ่ม ให้กำหนด Border ห่างจาก TextView ประมาณ 60dp เพื่อให้เห็นเด่นชัด
    • เขียนข้อความบนปุ่มว่า OK
    • ตั้งชื่อ id ของปุ่มนี้ว่า btnOk สำหรับให้ปิดหน้าจอ dialog 
    • ถ้าข้อความยาวเกินหน้าจอ ให้นำ ScrollView มาครอบเพื่อให้สามารถ Scroll ได้
การสร้าง Java Class สำหรับ DialogFragment 
  1. สร้าง Java Class เพื่อให้เป็น Object ของ DialogFragment ที่จะใช้ Layout ที่สร้างขึ้น เพื่อบอก FragmentManager ว่า เราต้องการ layout นี้มาแสดง
  2. คลิกขวาในห้อง Java ที่เก็บไฟล์หลักของ Project และเลือก New > Java Class
  3. ตั้งชื่อว่า MyDialogFragmentDemo 
  4. ใน Class นี้ จะต้อง extends DialogFragment และ ใช้ layout สำหรับการรับ การคลิก โดย implements OnClickListener
  5. เรียกใช้ onCreateView เพื่อสร้างหน้าจอ
  6. ในการสร้างหน้าจอ มีการกำหนดตัวแปรของปุ่ม มีการ inflate โดยเรียกใช้ layout ที่สร้างไว้แล้ว มีการกำหนดชื่อ Dialog พร้อมทั้งรอรับการคลิกจากปุ่ม ถ้ามีการคลิก ให้ปิดหน้าจอ การ Import โปรแกรม Android Studio จะถามให้กด Alt+Enter เพือ import ในส่วนที่ต้องการ
  7. สำหรับชื่อของ Dialog สำหรับ API ที่ตำ่กว่า API 23 จะไม่มีปัญหา แต่ถ้าเป็น API 23 ต้องไปกำหนด Style ในไฟล์ style.xm ให้มี Style ที่กำหนดให้มีชื่อ และนำมาใช้กับ Dialog เมื่อมีการเรียกใช้
  8. กำหนด Style ในไฟล์ Style.xml ดังนี้
การเรียกใช้งาน ที่ OverFlow menu
  1. กำหนด item ของ Overflow menu ในไฟล์ menu.xml โดยมี id คือ action_pro และ ชื่อที่จะปรากฏ คือ รุ่น Pro
  2. เมื่อเปิดหน้าจอจะเห็นมี OverFlow menu เป็นจุด 3 จุด
  3. เมื่อคลิกที่ OverFlow menu จะเห็นมีเมนู รุ่น Pro ปรากฎ
  4. ใน Activity ที่มี Overflow menu ให้เรียกใช้งาน เมื่อเมนูถูกคลิก ใน onOptionsItemSelected method
  5. ในการเรียกใช้งาน ต้องเรียกผ่าน FragmentManager พร้อมทั้งกำหนด Style ให้ใช้ style ที่กำหนดไว้ในไฟล์ style.xml สำหรับ dialog นี้ เพื่อให้แสดงหัวเรื่องด้านบน
  6. เป็นอันเสร็จการสร้าง DialogFragment
  7. เมื่อใช้งาน โดยคลิกที่เมนู รุ่น Pro ใน OverFlow menu จะแสดง Dialog ดังภาพข้างต้น
ดาวน์โหลดไฟล์ เพื่อศึกษา คลิกที่นี่

วันอาทิตย์ที่ 29 พฤศจิกายน พ.ศ. 2558

การสร้างปุ่มแชร์ บนมือถือ Android ด้วย ShareActionProvider

ShareActionProvider extends มาจาก Action Provider Class ซึ่งเริ่มจาก Android 4.0 (API 11) ซึ่งเป็นตัวจัดการเรียกแอป social media เพื่อแชร์ข้อมูลไปยังเพื่อน ๆ หรือ กลุ่มเพื่อน โดยเรียกใช้ โซเชียลแอปที่มีในมือถือนั้น ๆ เช่น Line Facebook Email Messenger เป็นต้น แล้วแต่ว่า ในมือถือนั้น ๆ จะติดตั้งแอป อะไรไว้บ้าง ShareActionProvider ก็จะนำมาให้เลือก และจัดการให้ทั้งหมด ดังภาพ ( ภาพที่ 1 แสดงไอคอนแชร์ ภาพที่ 2 เมื่อกดปุ่มแชร์ และภาพที่ 3 เมื่อกดปุ่มอีเมล)


ปัญหาคือ แล้วจะเรียกใช้อย่างไร ปัญหามักจะอยู่ที่การเชื่อมโยงระหว่าง ShareActionProvider กับ menu itemในไฟล์ menu.xml เช่น บอกให้ไปใช้ MenuItemCompat หรือ มีปัญหาการ cast บอกว่า ไม่สามารถ cast จาก ActionProvider ไปยัง ShareActionProvider เป็นต้น 

ในตัวอย่างนี้ ใช้ Android Studio 1.5 และใช้ App Bar ไม่ใช้ Action Bar 

หลักการในการเรียกใช้งาน ShareActionProvider
  1. กำหนด Style ให้ไม่ใช้ Action Bar และเรียกใช้ใน theme ให้สอดคล้องกัน
  2. สร้าง menu item ใน menu.xml โดยไม่ต้องระบุไอคอน เพราะ ShareActionProvider จัดการให้เรียบร้อย แต่ต้องระบุชื่อ และ support class
  3. ใน Activity ที่เรียกใช้งาน ให้ inflate menu และเรียกใช้ ShareActionProvider ใน onCreateOptionsMenu method
  4. ในกรณีที่มี Overflow menu ใน onOptionsItemSelected method
รายละเอียด

ในไฟล์ Styles.xml 

ในไฟล์ AndroidManifest.xml กำหนด Style ดังนี้
android:theme="@style/AppTheme.NoActionBar"

ในไฟล์ String.xml กำหนดชื่อของเมนูแชร์
Share

ในไฟล์ menu.xml ให้กำหนด id ให้ตรงกับที่สร้างใน layout ด้วย ส่วนชื่อ ใช้ชื่ออะไรก็ได้ เผื่อให้สำหรับถ้าเกิดไปแสดงใน Overflow menu จะได้มีชื่อ

    xmlns:bwq="http://schemas.android.com/apk/res-auto" >

   
        android:id="@+id/menu_share"
        android:title="@string/menu_share"
        bwq:actionProviderClass="android.support.v7.widget.ShareActionProvider"
        bwq:showAsAction="always"/>

ในไฟล์  java ของ activity ที่เรียกใช้งาน ให้ import และเรียกใช้งาน ดังนี้

การ import

import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.ShareActionProvider;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;


การเรียกใช้งาน

เรียกใช้งานใน onCreateOptionsMenu method

//ระบุตัวแปร ให้เป็นประเภท ShareActionProvider เพื่อเรียกใช้ภายหลัง
ShareActionProvider mShareActionProvider;

//สร้าง toolbar ใน onCreate method
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
//สำหรับ Android รุ่นเก่า สามารถใช้งานได้
setSupportActionBar(toolbar);

//สร้างเมนู ใน onCreateOptionsMenu method
getMenuInflater().inflate(R.menu.menu_main, menu);

// กำหนดค่าของ item ให้เป็น item ที่ระบุไว้ในไฟล์ menu.xml
MenuItem item = menu.findItem(R.id.menu_share);

// เรียกใช้ ActionProvider และเก็บไว้ในตัวแปร
mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(item);
//เมื่อมีการคลิกที่แชร์ จะให้ไปใช้ intent ที่สร้างขี้น
mShareActionProvider.setShareIntent(getDefaultShareIntent());

สร้าง method ที่ชื่อว่า getDefaultShareIntent() ดังนี้

private Intent getDefaultShareIntent(){
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_SUBJECT, "ทดสอบการแชร์");
        intent.putExtra(Intent.EXTRA_TEXT,"ทดสอบการแชร์ผ่าน app ต่าง ๆ");
        return intent;
    }

ถ้ามีการใช้เมนูใน Overflow menu ให้เรียกใช้จาก onOptionsItemSelected method โดยอาจจะทำเป็น switch case หรือ ใช้ if หลาย ๆ ครั้ง ก็ได้ เช่น

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }


ดาวน์โหลดไฟล์ คลิกที่นี่


ที่มา
http://developer.android.com/reference/android/support/v7/widget/ShareActionProvider.html
http://developer.android.com/training/sharing/shareaction.html
http://stackoverflow.com/questions/19118051/unable-to-cast-action-provider-to-share-action-provider










วันอังคารที่ 24 พฤศจิกายน พ.ศ. 2558

การสร้างปุ่มกลับ บน Toobar ของ Android Studio

Android Studio API 21 ได้นำ Toolbar มาใช้แทน ActionBar โดยมีคุณสมบัติเพิ่มขึ้นมาก ในตัวอย่างต่อไปนี้ จะเป็นการสร้างปุ่มกลับเมนู บน Toolbar ดังภาพ

ปุ่มกลับเมนู ไม่ใช่ปุ่มกลับหน้าที่ผ่านมา แต่เป็นปุ่มกลับเมนูที่คลิกมาหน้าปัจจุบัน หรือ เมนูที่อยู่เหนืออีกชั้นหนึ่ง รายละเอียดดูที่ http://developer.android.com/design/patterns/navigation.html

ข้อดีของ Android Studio ที่ผมชอบ คือ เขามีการเขียนโค้ดเตรียมไว้ให้พร้อม เราเพียงแต่ให้รู้ว่า จะเพิ่มเติมอะไร อย่างไร นอกจากนี้ ยังมี  code hint ทำให้ทุ่นเวลาการเขียน พร้อมทั้งตรวจสอบความถูกต้องไปในตัว รุ่นที่ใช้อยู่นี้ คือ Android Studio 1.5

การสร้างปุ่มกลับ

  1. เริ่มจากสร้าง Project ใหม่ เลือก API 11 และ Blank Project
  2. เมื่อเปิดเข้ามา จะเห็นว่า Android Studio 1.5 สร้าง Toolbar ว่าง ๆ ไว้ให้แล้ว พร้อมกับสร้าง menu_main.xml ไว้ให้ด้วย เพื่อให้ตกแต่งเพิ่มเติม เช่น ใส่ปุ่มกลับ เพิ่มชื่อของ Activity เพิ่ม Overflow menu เป็นต้น
  3. ปุ่มกลับต้องมี 2 หน้า ดังนั้นต้องสร้างหน้าใหม่ หรือ Activity ใหม่ โดยไปที่  Java > [PackageName] คลิกขวา และเลือก New > Activity > Blank Activity
  4. ตั้งชื่อว่า DetailPage แล้วกด Finish
  5. ก่อนอื่น ต้องสร้างปุ่มที่หน้าแรก เพื่อคลิกไปยังหน้าที่ 2 ที่เพิ่งสร้างขึ้น
  6. ไปที่หน้าแรกที่  res > layout > content_main.xml เลือกส่วนที่เป็น Design
  7. ลากปุ่มมาวาง ที่แถบ Property เปลี่ยนข้อความหน้าปุ่มเป็น ไปหน้า 2 และ ระบุ onclick ให้ใช้ goToDetail method
  8. ไปที่ Java ของ MainActivity เพื่อสร้าง goToDetail() method ตามที่ระบุ
  9. ก่อนอื่นต้อง import android.content.Intent เข้ามาก่อน เพื่อใช้คำสั่ง intent (หรือจะพิมพ์ก่อน แล้วค่อยกด Alt+Enter เพื่อ import ก็ได้)
  10. เขียน method ใหม่ โดยเรียกใช้งาน intent และระบุหน้า DetailPage ซึ่งเป็นหน้าที่ต้องการไป พร้อมทั้งให้คำสั่ง ทำงานด้วย ดังนี้
  11. ต่อไปจะเป็นการสร้างปุ่มลูกศรกลับ ในหน้า DetailPage
  12. ที่ res > layout > content_detail_page ในหน้า Design ลาก Large Text Widget มาวาง และกำหนดข้อความว่า "หน้ารายละเอียด" หน้านี้ จะสร้างปุ่มลูกศรสำหรับกลับไปที่หน้าแรก
  13. ไปที่ Java ของ DetailPage จะเห็นว่า Android Studio เขียนโค้ด Toolbar รอไว้แล้ว ใน onCreate () method พร้อมทั้ง ทำการ extends AppcompatActivity ให้ด้วย ซึ่งทำให้สามารถใช้ได้กับ Android รุ่นก่อน ๆ ย้อนไปถึง API 7 ทีเดียว

  14. ปุ่มกลับ เป็นการเปลี่ยนลักษณะของการกลับไปหน้าแรก ให้เป็นการกลับไปยังหน้าที่มีระดับสูงกว่า 1 ขั้น โดยเรียกใช้  setDisplayHomeAsUpEnabled() ของ getSupportActionBar() โดยเขียนโค้ด ต่อจากที่มีอยู่แล้ว ใน onCreate() method (ก่อน FloatingActionButton) ซึ่งจะได้ปุ่มลูกศรกลับ บน Toolbar
  15. เมื่อมีการคลิกปุ่มกลับ บน Toolbar เราจะใช้คำสั่ง intent เพื่อให้กลับไปยังหน้าแรก 
  16. ก่อนอื่นต้อง import android.view.MenuItem; และ import android.content.Intent; เข้ามาก่อน เพื่อให้คำสังสามารถทำงานได้
  17. เพิ่ม method เพื่อรอรับการคลิก และเรียกใช้ intent เพื่อให้กลับไปยังหน้าแรก โดยตรวจสอบ id ของ item ที่คลิก ในกรณีที่มี overflow menu ก็จะตรวจสอบตรงนี้ที่เดียวกัน ถ้า id เท่ากับ home ซึ่งเราบอกว่าจะให้กลับหน้าระดับเหนือหน้านี้ชั้นหนึ่ง เราก็เขียนโค้ดรับ โดยใช้ intent และระบุหน้าที่จะกลับไป ในตัวอย่างนี้หน้าแรกคือ MainActivity
  18. ไปที่ manifest.xml เพื่อ ระบุระดับว่า หน้า MainActivity เป็นหน้าหลัก มิฉะนั้นจะใช้กับ API level 7 ไม่ได้ โดยระบุ ใน manifest.xmlในส่วนของหน้า DetailPage ดังนี้
  19. เมื่อ run ดู จะเห็นหน้าจอดังนี้
  20. เมื่อคลิกปุ่มไปหน้า 2 จะเห็นดังนี้
  21. เมื่อคลิกลูกศรกลับ จะกลับมาที่หน้าแรก
ดาวน์โหลดไฟล์ zip เพื่อนำไปศึกษาได้ คลิกที่นี่

สำหรับการสร้าง Overflow menu ไปเพิ่ม item ในไฟล์ menu เช่น


และตรวจสอบการคลิก ใน onOprionsItemSelected() เช่นเดียวกัน โดยอาจใช้ switch case หรือ ใช้  if หลาย ๆ ครั้งตรวจสอบ ก็ได้


ที่มา
http://developer.android.com/training/appbar/up-action.html
http://developer.android.com/design/patterns/navigation.html
https://guides.codepath.com/android/Using-the-App-ToolBar
http://www.android4devs.com/2014/12/how-to-make-material-design-app.html
https://www.youtube.com/watch?v=EAZv1fP-5TM