Day 4 : Swipe Refresh Layout

Day 4 : Swipe Refresh Layout Cover Image

สวัสดีครับ บทความนี้เป็นบทความที่ 4 แล้วนะครับ ที่ผมจะมาเขียน ในซีรีย์ Learn 30 Android Libraries in 30 days สำหรับบทความตอนก่อน อ่านได้จากด้านล่างครับ

สำหรับบทความทั้งหมด อ่านได้จากด้านล่างครับ

ส่วนวันนี้นำเสนอ Library ตัวที่สี่ ชื่อว่า SwipeRefreshLayout ครับ ตัวนี้เป็น Library

SwipeRefreshLayout คืออะไร?

SwipeRefreshLayout เป็น View ชนิดหนึ่ง ที่เอาไว้ให้ User สามารถที่จะ refresh เนื้อหาโดยการใช้การ swipe ได้ การใช้งาน SwipeRefreshLayout ก็คล้ายๆกับการใช้งานพวก ScrollView คือจะเป็นคล้ายๆ ตัว Container คอยหุ้มพวก View อื่นๆ อีกทีนึง โดยส่วนตัวไม่แน่ใจว่า ตัว SwipeRefreshLayout กับตัว Actionbar Pull To Refresh มันคือตัวเดียวกันหรือไม่ เหมือนกับว่าทาง Android เพิ่งจะนำมาใส่เป็น default รึเปล่า? อันนี้ใครพอทราบ รบกวนช่วยบอกด้วยนะครับ

Getting Started

เนื่องจากไม่ต้องติดตั้งอะไรเพิ่มเติม เพราะว่าตัว SwipeRefreshLayout มันอยู่ใน Support Library v4 อยู่แล้ว ถ้าหากใครไม่ได้โหลด Support Library ก็ไปโหลดมาซะ

การใช้งาน ก็ง่ายๆครับ สร้างไฟล์เลเอา์ท์ xml โดยใช้ SwipeRefreshLayout เป็น container คอยหุ้ม View อื่่นๆ แบบนี้

<android.support.v4.widget.SwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipe_refresh_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.v4.widget.SwipeRefreshLayout>

ต่อมาที่คลาส SwipeToRefreshActivity.java ผมทำการประกาศ ListView, ArrayAdapter และ SwipeRefreshLayout แบบนี้

package com.devahoy.learn30androidlibraries.day4;

import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBarActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.devahoy.learn30androidlibraries.R;

import java.util.ArrayList;
import java.util.Random;

public class SwipeToRefreshActivity extends ActionBarActivity {

    private SwipeRefreshLayout mSwipeRefresh;
    private ListView mListView;
    private ArrayAdapter<String> mSimpleAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.day4_activity_swipe_to_refresh);

        mSwipeRefresh = (SwipeRefreshLayout)
                findViewById(R.id.swipe_refresh_layout);
        mListView = (ListView) findViewById(R.id.list_view);

    }
}

การใช้งาน SwipeRefreshLayout

การใช้งาน SwipeRefreshLayout เมื่อเรา declare มันที่ไฟล์ layout และก็ทำการเชื่อมมันเข้ากับคลาสในโค๊ดแล้ว ขั้นตอนต่อมา ถ้าจะให้ตัว SwipeRefreshLayout ทำงาน ก็ต้องใช้เมธอด setOnRefreshListener() ให้มันครับ คล้ายๆกับการ setListernr ให้กับพวก Button หรือว่า ListView แบบนี้

mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {

    }
});

โดยหาก user มีการ swipe หน้าจอ ตัว SwipeRefreshLayout จะทำงานที่เมธอด onRefresh() ฉะนั้น Logic ทุกๆอย่าง ก็ต้องทำในเมธอดนี้ เช่น เมื่อมีการ refresh ให้ไปดาวน์โหลดข้อมูลมาใหม่ จากนั้นก็ refresh ListView และโชว์ข้อมูลอันใหม่

ทดสอบลองรันดู แล้วลอง swipe ดู ปรากฎว่าทำงานได้ แต่ตัว Progress เป็นสีเทาๆ ดำๆ

No Set Color Schema

แต่ว่า ListView อุตส่ามีแล้ว แต่ไม่ได้โชว์ข้อมูลอะไรเลย ก็สร้างข้อมูลให้ ListView ซะหน่อย สร้างเมธอดและตัวแปร ขึ้นมาแบบนี้ (ทำการ random และเพิ่มข้อมูลเข้าไป)

private void initSampleData() {
    for (int i = 0; i < 5; i++) {
        int index = random.nextInt(lorems.length);
        mData.add(lorems[index]);
    }
}
private String[] lorems = new String[] {
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
        "Vivamus fringilla adipiscing neque, a lacinia metus pretium et",
        "Donec quam justo, vehicula ut mauris vel, luctus cursus libero",
        "Pellentesque ac fermentum augue, id congue tortor.",
        "Proin mattis ac nibh vitae volutpat. Pellentesque commodo eros quis enim tempus",
        "Fusce sagittis orci sit amet magna tempus, ut dignissim urna malesuada",
        "Quisque sit amet libero volutpat velit euismod sollicitudin.",
        "Interdum et malesuada fames ac ante ipsum primis in faucibus",
        "Cras sagittis rutrum ipsum, eget elementum arcu bibendum vitae",
        "Sed laoreet dignissim purus, ac vehicula eros lobortis id. Curabitur i",
        "egestas non arcu. Quisque placerat vulputate magna",
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
        "Praesent lacinia pellentesque sapien",
};

จากนั้นที่เมธอด onCreate() ก็จัดการสร้าง ArrayAdapter พร้อมทั้งให้ setAdapter ให้ ListView แบบนี้

public class SwipeToRefreshActivity extends ActionBarActivity {

    private SwipeRefreshLayout mSwipeRefresh;
    private ListView mListView;
    private ArrayAdapter<String> mSimpleAdapter;

    private ArrayList<String> mData = new ArrayList<String>();
    private Random random = new Random();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...

        initSampleData();

        mSimpleAdapter = new ArrayAdapter(this,
                android.R.layout.simple_list_item_1, android.R.id.text1, mData);

        mListView.setAdapter(mSimpleAdapter);
    }
}

ส่วน listener ของ SwipeRefreshLayout ก็เพิ่มนี้ลงไป เพื่อให้ ListView ทำการ random ข้อมูลใหม่ เมื่อมีการ refresh

mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
        mSimpleAdapter.clear();

        initSampleData();

        mSimpleAdapter.notifyDataSetChanged();

        mSwipeRefresh.setRefreshing(false);
    }
});

mSimpleAdapter.clear() คือสั่งให้ ลบข้อมูลใน ListView ท้ิงก่อน จากนั้นก็ทำการ initSampleData ใหม่อีกครั้ง แล้วก็สั่ง notifyDataSetChanged() เพื่อทำการ refresh ค่าที่เปลี่ยนแปลงใน Adapter จากนั้น ก็สั่งให้ SwipeRefreshLayout หยุดการ refresh ด้วยคำสั่ง #setRefreshing(false)

สุดท้าย หากเราไม่ชอบ ไอ้ตัว Progress สีดำๆ เทาๆ เราก็สามารถเปลี่ยนมันได้ ด้วยเมธอด setColorSchemeColors โดยรับ paramter เป็นสี 4 ค่า คิดว่าน่าจะเรียงลำดับก่อนหลัง แบบนี้

mSwipeRefresh.setColorSchemeColors(Color.parseColor("#4183D7"),
                Color.parseColor("#F62459"),
                Color.parseColor("#03C9A9"),
                Color.parseColor("#F4D03F"));

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

mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {

        new Handler().postDelayed(new Runnable() {
            @Override public void run() {

                mSimpleAdapter.clear();

                initSampleData();

                mSimpleAdapter.notifyDataSetChanged();

                mSwipeRefresh.setRefreshing(false);
            }
        }, 5000);
    }
});

ด้านบนเป็นการใช้ Handler และ Runnable เข้ามาช่วยคือเมื่อ SwipeRefreshLayout ทำการ refresh แล้ว ก็จะรอ 5 วินาที ถึงจะทำการ initSampleData ทำให้เราสามารถเห็น progress bar ได้ทุกสี

Result

Chai

Chai Phonbopit : Developer แห่งหนึ่ง • ผู้ชายธรรมดาๆ ที่ชื่นชอบ Node.js, JavaScript และ Open Source มีงานอดิเรกเป็น Acoustic Guitar และ Football

บทความล่าสุด