Android原生下拉刷新SwipeRefreshLayout实践

本篇文章翻译自Ravi Tamada的Android Swipe Down to Refresh ListView Tutorial

首先来看一下效果图

这里写图片描写叙述

你应该发现很多的android app比如Twitter,Google+都提供了一个下拉刷新数据的功能。仅仅要用户从上往下滑动,新的内容就会载入出来,这篇文章我们将学习怎样开发出相同的功能。

1.Android SwipeRefreshLayout

实现SwipeRefreshLayout很easy。我们将SwipeRefreshLayout作为根布局,将一个子布局包裹在内。本例中我们使用ListView,而且在Activity中中实现SwipeRefreshLayout.OnRefreshListener接口,当用户下拉时,会触发onRefresh()方法。在onRefresh()中我们发起网络请求而且获取最新的数据。

<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="wrap_content">

    <!-- place your view here -->

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

2.JSON URL

URL:http://api.androidhive.info/json/imdb_top_250.php?

offset=0

3.新建一个project

1.打开Android Studio,选择File->New Project project起名为MySwipeRefreshLayout

2.右键MySwipeRefreshLayout,选择New->Module 加入我们的Volley库,起名为Volley

这里写图片描写叙述
将Volley.jar拷贝到Volley的libs目录下
这里写图片描写叙述

打开Volley下的build.gradle。加入例如以下代码

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'
    compile files('libs/volley.jar')
}

3.打开src/res/values/colors.xml。加入例如以下代码

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="movie_serial_bg">
        <item>#24c6d5</item>
        <item>#57dd86</item>
        <item>#ad7dcf</item>
        <item>#ff484d</item>
        <item>#fcba59</item>
        <item>#24c6d5</item>
    </string-array>
</resources>

4.新建一个Application来初始化我们的Volley

public class MyApplication extends Application {

    public static final String TAG = MyApplication.class
            .getSimpleName();

    private RequestQueue mRequestQueue;

    private static MyApplication mInstance;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }

    public static synchronized MyApplication getInstance() {
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }

        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req, String tag) {
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }

    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }

    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

5.打开AndroidManifest.xml加入网络权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.swiperefresh">

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

    <application
        android:name="com.example.zhangqi.myswiperefreshlayout.MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name="com.example.zhangqi.myswiperefreshlayout.MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

6.创建list_row.xml 作为ListView每一个item的布局

<?

xml version="1.0" encoding="utf-8"?

> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/serial" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="25dp" android:layout_margin="5dp" android:layout_alignParentLeft="true" android:textSize="20dp" android:textStyle="bold" /> <TextView android:id="@+id/title" android:layout_toRightOf="@id/serial" android:layout_centerVertical="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" android:paddingLeft="20dp" android:textSize="18dp" /> </RelativeLayout>

7.创建实体类Movie.java

public class Movie {
    public int id;
    public String title;

    public Movie() {
    }

    public Movie(int id, String title) {
        this.title = title;
        this.id = id;
    }
}

8.创建Adapter

public class SwipeListAdapter extends BaseAdapter {
    private Activity activity;
    private LayoutInflater inflater;
    private List<Movie> movieList;
    private String[] bgColors;

    public SwipeListAdapter(Activity activity, List<Movie> movieList) {
        this.activity = activity;
        this.movieList = movieList;
        bgColors = activity.getApplicationContext().getResources().getStringArray(R.array.movie_serial_bg);
    }

    @Override
    public int getCount() {
        return movieList.size();
    }

    @Override
    public Object getItem(int location) {
        return movieList.get(location);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (inflater == null)
            inflater = (LayoutInflater) activity
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null)
            convertView = inflater.inflate(R.layout.list_row, null);

        TextView serial = (TextView) convertView.findViewById(R.id.serial);
        TextView title = (TextView) convertView.findViewById(R.id.title);

        serial.setText(String.valueOf(movieList.get(position).id));
        title.setText(movieList.get(position).title);

        String color = bgColors[position % bgColors.length];
        serial.setBackgroundColor(Color.parseColor(color));

        return convertView;
    }

}

9.如今我们在activity_main.xml的SwipeRefreshLayout下加入一个ListView

<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="wrap_content">

    <ListView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/listView">

    </ListView>

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

10.最后。打开MainActivity.java来完毕最后工作

实现SwipeRefreshLayout.OnRefreshListener而且重写OnRefresh()方法
使用Volley的JsonArrayRequest来获取最新的数据而且更新listview,抽取为一个方法fetchMovies()
当用户下拉刷新时触发OnRefresh(),在这里调用fetchMovies()

public class MainActivity extends ActionBarActivity implements SwipeRefreshLayout.OnRefreshListener {

    private String TAG = MainActivity.class.getSimpleName();

    private String URL_TOP_250 = "http://api.androidhive.info/json/imdb_top_250.php?

offset="; private SwipeRefreshLayout swipeRefreshLayout; private ListView listView; private SwipeListAdapter adapter; private List<Movie> movieList; // initially offset will be 0, later will be updated while parsing the json private int offSet = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView); swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout); movieList = new ArrayList<>(); adapter = new SwipeListAdapter(this, movieList); listView.setAdapter(adapter); swipeRefreshLayout.setOnRefreshListener(this); /** * Showing Swipe Refresh animation on activity create * As animation won't start on onCreate, post runnable is used */ swipeRefreshLayout.post(new Runnable() { @Override public void run() { swipeRefreshLayout.setRefreshing(true); fetchMovies(); } } ); } /** * This method is called when swipe refresh is pulled down */ @Override public void onRefresh() { fetchMovies(); } /** * Fetching movies json by making http call */ private void fetchMovies() { // showing refresh animation before making http call swipeRefreshLayout.setRefreshing(true); // appending offset to url String url = URL_TOP_250 + offSet; // Volley's json array request object JsonArrayRequest req = new JsonArrayRequest(url, new Response.Listener<JSONArray>() { @Override public void onResponse(JSONArray response) { Log.d(TAG, response.toString()); if (response.length() > 0) { // looping through json and adding to movies list for (int i = 0; i < response.length(); i++) { try { JSONObject movieObj = response.getJSONObject(i); int rank = movieObj.getInt("rank"); String title = movieObj.getString("title"); Movie m = new Movie(rank, title); movieList.add(0, m); // updating offset value to highest value if (rank >= offSet) offSet = rank; } catch (JSONException e) { Log.e(TAG, "JSON Parsing error: " + e.getMessage()); } } adapter.notifyDataSetChanged(); } // stopping swipe refresh swipeRefreshLayout.setRefreshing(false); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "Server Error: " + error.getMessage()); Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show(); // stopping swipe refresh swipeRefreshLayout.setRefreshing(false); } }); // Adding request to request queue MyApplication.getInstance().addToRequestQueue(req); } }

大功告成。

原文地址:https://www.cnblogs.com/mthoutai/p/7275622.html