Header Ads

How to use SwipeRefreshLayout the right way

In the latest revision of the android support library came out with an interesting new layout :SwipeRefreshLayout which implements the famous pull-down-to-refresh pattern. In the following i will show you how to implement it with a ListView and avoid some pitfalls.
To use this new layout you will need to have at least the android support library with at least revision 19.1
First we need to import the support library project to our workspace and then add it to your main project as a library.

Then we will start by defining our SwipeToRefresh container
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipe_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
     
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <ListView android:id="@id/android:list"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:drawSelectorOnTop="false"/>
    </LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
and then in our activity or fragment we load the layout and set it up
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
private SwipeRefreshLayout swipeRefreshLayout;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getCountries());
    ListView listView = (ListView) findViewById(R.id.listView);
    listView.setAdapter(adapter);
    // find the layout
    swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
    // the refresh listner. this would be called when the layout is pulled down
    swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
         
        @Override
        public void onRefresh() {
            // get the new data from you data source
            // TODO : request data here
            // our swipeRefreshLayout needs to be notified when the data is returned in order for it to stop the animation
            handler.post(refreshing);
        }
    });
    // sets the colors used in the refresh animation
    swipeRefreshLayout.setColorSchemeResources(R.color.blue_bright, R.color.green_light,
            R.color.orange_light, R.color.red_light);
}
private final Runnable refreshing = new Runnable(){
    public void run(){
        try {
            // TODO : isRefreshing should be attached to your data request status
            if(isRefreshing()){
                // re run the verification after 1 second
                handler.postDelayed(this, 1000);  
            }else{
                // stop the animation after the data is fully loaded
                swipeRefreshLayout.setRefreshing(false);
                // TODO : update your list with the new data
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }  
    }
};
For now if you try to swipe down to refresh your will be able to see the animation and your list would be updated. However, if scroll down in your list and try to go up again the swipe to refresh would be triggered again and you won’t be able to go back to the top of your list.
Obviously, this would be very annoying and the trick would be forcing the layout to refresh only when the very first item of the list is fully visible. To do this we assign anOnScrollListener to our ListView after the initialization of our swipe to refresh layout
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
listView.setOnScrollListener(new OnScrollListener() {
     
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }
     
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        boolean enable = false;
        if(listView != null && listView.getChildCount() > 0){
            // check if the first item of the list is visible
            boolean firstItemVisible = listView.getFirstVisiblePosition() == 0;
            // check if the top of the first item is visible
            boolean topOfFirstItemVisible = listView.getChildAt(0).getTop() == 0;
            // enabling or disabling the refresh layout
            enable = firstItemVisible && topOfFirstItemVisible;
        }
        swipeRefreshLayout.setEnabled(enable);
    }
});
Now you are good to go!
from : https://yassirh.com

No comments:

Powered by Blogger.