22/3/59

ตัวอย่างโค้ด android การทำ Selector ของ TextView

ตัวอย่างโค้ด android การทำ Selector ของ TextView

เรามาดูตัวอย่างโค้ดการทำ Selector ใน TextView กันครับ ซึ่งถ้าเราอยากให้ TextView นั้นคลิกได้ แล้วก็มี State แต่ละอย่างต่างกัน เช่น เมื่อเป็นตัวอักษรธรรมดาก็ให้เป็นสีขาว พอกดปุ๊ปก็ให้เปลี่ยนสีตัวอักษรเป็นสีน้ำเงิน หรืออยากให้พื้นหลังของ TextView จากปกติเป็นสีขาว เมื่อกด TextView แล้วให้มันเป็นสีน้ำเงินอะไรประมาณนี้ ซึ่งในที่นี้เราจะใช้ Selector เข้ามาช่วย เรามาดูตัวอย่างวิธีทำกันครับ

เริ่มด้วยให้เราสร้าง Selector ขึ้นมาก่อน ในที่นี้จะสร้าง Selector สำหรับเปลี่ยนสีตัวอักษรเวลากด โดยผมตั้งชื่อให้มันว่า selector_text_awesome_color.xml โดยเอาไฟล์ไปไว้ใน res/color แล้วตามด้วยตัวอย่างโค้ด android ด้านล่าง

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorAccent" android:state_pressed="true" />
    <item android:color="@color/colorTextHead" />
</selector>

เมื่อได้แล้ว ผมจะสร้าง Selector ขึ้นมาอีกอันหนึ่งเอาไว้สำหรับเปลี่ยนสี Background ของ TextView ตอนเวลากด โดยเอาไฟล์ไปไว้ใน res/drawable มีตัวอย่างโค้ด android ตามด้านล่าง

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/colorPrimaryDark" android:state_pressed="true" />
    <item android:drawable="@color/colorPrimary" />
</selector>

เมื่อได้แล้ว เราก็จะมาสร้าง TextView แล้วก็ทำการเซต textColor กับ background ซึ่งมีตัวอย่างโค้ดตามด้านล่าง

<com.doesystem.educate.englishwords.views.TextViewAwesome android:id="@+id/text_awesome_close"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:text="@string/awesome_close"
                android:textAlignment="center"
                style="@style/TitleMyWords"
                android:textColor="@color/selector_text_awesome_color"
                android:clickable="true"
                android:background="@drawable/selector_text_awesome_bg_color"
                android:onClick="onBtnClick"/>

ในตัวอย่างนี้ผมใช้ TextViewAwesome ซึ่งก็มีการ extends มาจาก TextView นั่นแหละครับ ตรงนี้ให้คิดว่ามันเป็น TextView ธรรมดาละกัน ส่วนสำคัญที่ต้องดู คือในส่วนของ android:textColor="@color/selector_text_awesome_color" ซึ่งเป็นการบอกว่าสีของตัวอักษรให้ใช้ selector_text_awesome_color ตัวนี้นะ และส่วนของ android:background="@drawable/selector_text_awesome_bg_color" เป็นการบอกว่าให้เราใช้ background เป็น selector_text_awesome_bg_color ตัวนี้

และอย่าลืมที่สำคัญอีกอย่างหนึ่งนั่นคือให้เราไปเปิดคุณสมบัติของ TextView ให้สามารถคลิกได้โดยการเซตค่า android:clickable="true" เพียงแค่นี้เราก็ได้ TextView ที่คลิกได้แล้วยังเปลี่ยนสีตัวอักษรหรือพื้นหลังได้ตามต้องการแล้ว

21/3/59

การใช้ฟังก์ชัน fn:substring-before ใน XQuery Function เพื่อตัดข้อความก่อนข้อความที่ต้องการ

การใช้ฟังก์ชัน fn:substring-before ใน XQuery Function เพื่อตัดข้อความก่อนข้อความที่ต้องการ

เรามาดูตัวอย่างและวิธีการใช้ฟังก์ชัน fn:substring-before กันครับ

fn:substring-before($arg1 as xs:string?, $arg2 as xs:string?) as xs:string
fn:substring-before($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:string

fn:substring-before เป็นการตัดสตริงที่ต้องการ โดยการตัดนั้นจะตัดข้อความทั้งหมดก่อนข้อความที่กำหนด

ตัวอย่างการเรียกใช้ฟังก์ชัน fn:substring-before ใน Xquery Function

มาลองเขียนฟังก์ชันเพื่อลองทดสอบดู


เมื่อเขียนเสร็จมาลองเทสฟังก์ชันที่ได้เขียนขึ้นดูจะได้ดังรูปด้านล่าง


จากรูปจะเห็นการเรียกใช้ฟังก์ชันแบบคร่าว ๆ และการแสดงผลค่าที่รีเทิร์นออกมา มาลองดูกรณีอื่น ๆ ที่น่าสนใจกัน

substring-before('query', 'r')
-> que

substring-before('queryquery', 'ery')
-> qu

ดูฟังก์ชัน Xquery อื่น ๆ ได้ที่ http://www.doesystem.info/p/xquery.html

การใช้ฟังก์ชัน fn:substring ใน XQuery Function เพื่อตัดข้อความที่ต้องการ

การใช้ฟังก์ชัน fn:substring ใน XQuery Function เพื่อตัดข้อความที่ต้องการ

เรามาดูตัวอย่างและวิธีการใช้ฟังก์ชัน fn:substring กันครับ

fn:substring($sourceString as xs:string?, $startingLoc as xs:double) as xs:string
fn:substring( $sourceString as xs:string?, $startingLoc as xs:double, $length as xs:double) as xs:string

fn:substring เป็นฟังก์ชันที่เอาไว้สำหรับ substring หรือตัดสตริง โดยมีการกำหนด $startingLoc สำหรับตัวเริ่มต้นที่ต้องการจะตัด ซึ่งตัวแรกในการจะตัดนั้นจะเริ่มที่ 1(ไม่ใช่ 0) และมี optional $length เป็น argument ที่เอาไว้สำหรับบอกว่าจำนวนที่ต้องการจะตัดสตริง ถ้าเราไม่ได้กำหนด $length จะเป็นการเอาสตริงที่เหลือทั้งหมด

fn:substring จะรีเทิร์นค่าเป็นสตริงที่เหลือจากการตัด

ตัวอย่างการเรียกใช้ฟังก์ชัน fn:substring ใน Xquery Function

มาลองเขียนฟังก์ชันเพื่อลองทดสอบดู


เมื่อเขียนเสร็จมาลองเทสฟังก์ชันที่ได้เขียนขึ้นดูจะได้ดังรูปด้านล่าง


จากรูปจะเห็นการเรียกใช้ฟังก์ชันแบบคร่าว ๆ และการแสดงผลค่าที่รีเทิร์นออกมา มาลองดูกรณีอื่น ๆ ที่น่าสนใจกัน

substring('query', 1)
-> query

substring('query', 1, 1)
-> q

substring('query', 2, 3)
-> uer

substring('query', 2, 850)
-> uery

substring('query', -2)
-> query

substring('query', -2, 5)
-> qu

fn:substring((), 1, 3)
-> ""

ดูฟังก์ชัน Xquery อื่น ๆ ได้ที่ http://www.doesystem.info/p/xquery.html

การใช้ฟังก์ชัน fn:tokenize ใน XQuery Function เพื่อ splite string

การใช้ฟังก์ชัน fn:tokenize ใน XQuery Function เพื่อ splite string

เรามาดูวิธีการใช้ฟังก์ชัน tokenize ใน XQuery Function กันครับ

fn:tokenize เป็นฟังก์ชันสำหรับการ splits a string หรือแยกสตริง โดยใช้ regular expression

ตัวอย่างการเรียกใช้ฟังก์ชัน tokenize ใน XQuery Function

มาลองเขียนฟังก์ชันเพื่อลองทดสอบดู


เมื่อลองทำการ Test ฟังก์ชันดู จะได้ผลลัพธ์ตามรูปด้านล่าง


จากรูปจะเห็นตัวอย่างการเรียกใช้ฟังก์ชันคร่าว ๆ แล้ว มาลองดูกรณีอื่น ๆ ที่น่าสนใจกัน

tokenize('a b c', '\s')
-> ('a', 'b', 'c')

tokenize('a   b c', '\s')
-> ('a', '', '', 'b', 'c')

tokenize('a   b c', '\s+')
-> ('a', 'b', 'c')

tokenize((), '\s+')
-> ()

tokenize('a,xb,xc', ',|,x')
-> ('a', 'xb', 'xc')

ดูฟังก์ชัน Xquery อื่น ๆ ได้ที่ http://www.doesystem.info/p/xquery.html

20/3/59

การกู้คืนไฟล์ที่เผลอลบในโปรแกรม android studio

การกู้คืนไฟล์ที่เผลอลบในโปรแกรม android studio

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

เริ่มด้วยการคลิกขวาที่โปรเจ็ค จากนั้นเลือก Local History จากนั้นเลือก Show History ตามรูปด้านล่าง


เมื่อเลือกแล้วจะปรากฏหน้าต่างของ History ของโปรแกรมขึ้นมา ในช่องด้านซ้ายจะเป็นไฟล์ที่แก้ไข ยังมีเวลาที่แก้ไขไปแล้วด้วย ส่วนด้านขวาจะเป็นส่วนที่ระบบได้แก้ไขทั้งหมด ดูรูปตัวอย่างได้ตามรูปด้านล่าง


เมื่อเลือกเสร็จแล้วให้คลิกขวา แล้วเลือก Revert Selection ตามรูปเลย

เพียงแค่นี้เราก็สามารถกูคืนไฟล์ที่ลบไปแล้ว หรือยังสามารถย้อนคืนสิ่งที่แก้ไขไปแล้วได้ด้วย เหมือน Git หรือ SVN เลยใช่ไหมหละ

19/3/59

การใช้ฟังก์ชัน fn:ends-with ใน XQuery Function เพื่อค้นหาว่าลงท้ายด้วยคำที่ต้องการหรือไม่

การใช้ฟังก์ชัน fn:ends-with ใน XQuery Function เพื่อค้นหาว่าลงท้ายด้วยคำที่ต้องการหรือไม่

เรามาดูวิธีการใช้ฟังก์ชัน ends-with ใน XQuery Function กันครับ

fn:ends-with เป็นฟังก์ชัน ที่ return ค่า xs:boolean จะเป็นฟังก์ชันเอาไว้สำหรับเปรียบเทียบว่า string($arg1) นั้นมีตัวอักษรที่ลงท้ายด้วย string ตัวที่สองหรือเปล่า string($arg2) ซึ่งฟังก์ชันนี้จะรวมไปถึงการเปรียบเทียบช่องว่างด้วย ดังนั้นก่อนที่เราจะเรียกฟังก์ชันนี้ เราควรจะใช้ฟังก์ชัน fn:normalize-space เพื่อทำการ trim สตริงพวกนั้นก่อนเรียกฟังก์ชันนี้

ตัวอย่างการเรียกใช้ฟังก์ชัน ends-with ใน XQuery Function

มาลองเขียนฟังก์ชันเพื่อลองทดสอบดู


เมื่อลองทำการ Test ฟังก์ชันดู จะได้ผลลัพธ์ตามรูปด้านล่าง


จากรูปจะเห็นตัวอย่างการเรียกใช้ฟังก์ชันคร่าว ๆ แล้ว มาลองดูกรณีอื่น ๆ ที่น่าสนใจกัน

ends-with('doesystem', 'tem')
-> true

ends-with('doesystem', 'm')
-> true

ends-with('doesystem', '')
-> true

ends-with('doesystem ', 'm')
-> false

ends-with('', 'm')
-> false

ดูฟังก์ชัน Xquery อื่น ๆ ได้ที่ http://www.doesystem.info/p/xquery.html

4/3/59

Android SQLite Database with Relationship Tables

Android SQLite Database with Relationship Tables การสร้างตารางที่มีหลายตารางและมีความสัมพันธ์กัน


มาดูตัวอย่างโค้ด Android ที่มีหลาย ๆ Table แล้วแต่ละ Table มีความสัมพันธ์กัน

ก่อนอื่นเราก็ต้องมาทำการ list รายชื่อตารางและคอมลัมน์ออกมาก่อน ดังตัวอย่าง

    // WORD_GROUP_TABLE
    public static final String TABLE_WORDS_GROUP = "WORDS_GROUP";
    public static final String COL_TABLE_WORD_GROUP_ID = "ID";
    public static final String COL_TABLE_WORD_GROUP_EN = "GROUP_EN";
    public static final String COL_TABLE_WORD_GROUP_TH = "GROUP_TH";

    // WORD_ITEMS_TABLE
    public static final String TABLE_WORDS_ITEMS = "WORDS_ITEMS";
    public static final String COL_TABLE_WORD_ITEMS_ID = "ID";
    public static final String COL_TABLE_WORD_ITEMS_EN = "ITEM_EN";
    public static final String COL_TABLE_WORD_ITEMS_TH = "ITEM_TH";
    public static final String COL_TABLE_WORD_ITEMS_GROUP_REFERENCES = "ITEM_GROUP";

จากตัวอย่างข้างต้นเราจะสร้าง Table ขึ้นมา 2 Table ที่ชื่อว่า WORDS_GROUP และ WORDS_ITEMS ซึ่งจะมีความสัมพันธ์คือให้คอลัมน์ ITEM_GROUP ชี้ไปที่ ID ของ WORD_GROUP

เมื่อได้แล้ว เราก็ต้องทำการ สร้างตารางโดยเอาโค้ดไว้ในส่วน onCreate ดังตัวอย่างโค้ด

 db.execSQL("CREATE TABLE " + TABLE_WORDS_GROUP +" (" + COL_TABLE_WORD_GROUP_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
                        + COL_TABLE_WORD_GROUP_EN + " TEXT, "
                        + COL_TABLE_WORD_GROUP_TH + " TEXT);"
        );

        db.execSQL("CREATE TABLE " + TABLE_WORDS_ITEMS + " (" + COL_TABLE_WORD_ITEMS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
                        + COL_TABLE_WORD_ITEMS_EN + " TEXT, "
                        + COL_TABLE_WORD_ITEMS_TH + " TEXT, "
                        + COL_TABLE_WORD_ITEMS_GROUP_REFERENCES + " INTEGER, "
                        + "FOREIGN KEY(" + COL_TABLE_WORD_ITEMS_GROUP_REFERENCES + ") REFERENCES "
                        + TABLE_WORDS_GROUP + "(" + COL_TABLE_WORD_GROUP_ID + "));"
        );

จากตัวอย่างโค้ดเราจะสร้างตารางโดย ใช้ Query จากนั้นก็ให้เราเพิ่มข้อมูลเข้าไปได้เลย

ดูตัวอย่างเต็ม ๆ ไฟล์ได้ตามโค้ดด้านล่าง


package com.doesystem.educate.englishwords.database;

import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by Doe on 2/25/2016.
 */
public class DBHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "DOE_WORDS";
    private static final int DB_VERSION = 6;

    // WORD_GROUP_TABLE
    public static final String TABLE_WORDS_GROUP = "WORDS_GROUP";
    public static final String COL_TABLE_WORD_GROUP_ID = "ID";
    public static final String COL_TABLE_WORD_GROUP_EN = "GROUP_EN";
    public static final String COL_TABLE_WORD_GROUP_TH = "GROUP_TH";

    // WORD_ITEMS_TABLE
    public static final String TABLE_WORDS_ITEMS = "WORDS_ITEMS";
    public static final String COL_TABLE_WORD_ITEMS_ID = "ID";
    public static final String COL_TABLE_WORD_ITEMS_EN = "ITEM_EN";
    public static final String COL_TABLE_WORD_ITEMS_TH = "ITEM_TH";
    public static final String COL_TABLE_WORD_ITEMS_GROUP_REFERENCES = "ITEM_GROUP";

    public DBHelper(Context context){
        super(context, DB_NAME, null, DB_VERSION);
    }

    public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
        super(context, name, factory, version, errorHandler);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + TABLE_WORDS_GROUP +" (" + COL_TABLE_WORD_GROUP_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
                        + COL_TABLE_WORD_GROUP_EN + " TEXT, "
                        + COL_TABLE_WORD_GROUP_TH + " TEXT);"
        );

        db.execSQL("CREATE TABLE " + TABLE_WORDS_ITEMS + " (" + COL_TABLE_WORD_ITEMS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
                        + COL_TABLE_WORD_ITEMS_EN + " TEXT, "
                        + COL_TABLE_WORD_ITEMS_TH + " TEXT, "
                        + COL_TABLE_WORD_ITEMS_GROUP_REFERENCES + " INTEGER, "
                        + "FOREIGN KEY(" + COL_TABLE_WORD_ITEMS_GROUP_REFERENCES + ") REFERENCES "
                        + TABLE_WORDS_GROUP + "(" + COL_TABLE_WORD_GROUP_ID + "));"
        );

        insertDataToTable(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_WORDS_GROUP);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_WORDS_ITEMS);
        onCreate(db);
    }

    String[][] dataGroup = new String[][]{
            {"Body", "ร่างกาย"},
            {"Internal Organs", "อวัยวะภายในร่างกาย"},
            {"Family", "ครอบครัว"},
            {"House and Around the House", "บ้านและรอบ ๆ บ้าน"},
            {"Bedroom", "ห้องนอน"},
            {"In the House", "ของใช้ในบ้าน"}
    };
    String[][][] dataItems = new String[][][]{
            {
                {"abdomen", "ท้อง"},
                {"ankle", "ข้อเท้า"},
                {"arm", "แขน"},
                {"armpit", "รักแร้"},
                {"back", "หลัง (ส่วนของร่างกาย)"},
                {"bone", "กระดูก"},
                {"bottom", "ก้น"},
                {"cheek", "แก้ม"},
                {"chest", "หน้าอก"},
                {"chin", "คาง"}
            },
            {
                {"adrenal gland", "ต่อมหมวกไต"},
                {"anus", "ทวารหนัก"},
                {"appendix", "ไส้ติ่ง"},
                {"artery", "เส้นเลือดแดงที่นำเลือดแดงออกจากหัวใจ"},
                {"bladder", "กระเพาะปัสสาวะ"}
            },
            {
                {"ancestor", "บรรพบุรุษ"}
            },
            {
                {"attic", "ห้องใต้หลังคา"}
            },
            {
                {"alarm clock", "นาฬิกาปลุก"}
            },
            {
                {"air-conditioner", "เครื่องปรับอากาศ"},
                {"aquarium", "ตู้ปลา"}
            }
    };

    private void insertDataToTable(SQLiteDatabase db){
        for(int i = 0; i < dataGroup.length; i++){
            insertToWordsGroupTable(db, dataGroup[i][0], dataGroup[i][1]);
            for(int j = 0; j < dataItems[i].length; j++){
                insertToWordsItemsTable(db, dataItems[i][j][0], dataItems[i][j][1], i + 1);
            }
        }
    }

    private void insertToWordsGroupTable(SQLiteDatabase db, String groupEn, String groupTh){
        db.execSQL("INSERT INTO " + TABLE_WORDS_GROUP
                + " VALUES (null, '" + groupEn + "', '" + groupTh + "');");
    }

    private void insertToWordsItemsTable(SQLiteDatabase db, String itemEn, String itemTh, int groupId){
        db.execSQL("INSERT INTO " + TABLE_WORDS_ITEMS
                + " VALUES (null, '" + itemEn + "', '" + itemTh + "', " + groupId + ");");
    }
}