[Android学习系列15]下拉刷新列表实现动态加载
实现方案:
使用google官方的SwipeRefreshLayout
参考:
http://blog.csdn.net/easyer2012/article/details/22857807
http://stormzhang.github.io/android/2014/03/29/android-swiperefreshlayout/
http://www.eoeandroid.com/thread-330439-1-1.html
http://www.oschina.net/translate/swipe-to-refresh-added-to-android-support-v4-component
使用开源控件PullToRefreshListView
参考:
http://my.oschina.net/sfshine/blog/140716
http://blog.csdn.net/harvic880925/article/details/17680305
https://github.com/chrisbanes/Android-PullToRefresh
使用ActionBar-PullToRefresh开源控件
参考:
http://www.tutecentral.com/android-pull-to-refresh/
http://www.youtube.com/watch?v=JfJM1jQsZRM
小代码练习:
用 SwipeRefreshLayout + android-async-http + gson 实现网络加载数据
package com.example.testwipe; public class Book { int bookid; String bookname; String bookinfo; Book(int id, String name, String info) { this.bookid = id; this.bookname = name; this.bookinfo = info; } } ----------------------------------------------------------------------------------- <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingBottom="10dp" > <TextView android:id="@+id/booktitle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#6FB3E0" android:paddingTop="5dp" android:paddingBottom="5dp" android:textColor="#fff" android:gravity="center" /> <TextView android:id="@+id/bookinfo" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#fff" android:paddingTop="5dp" android:paddingBottom="5dp" android:textColor="#0000EE" android:gravity="center" android:layout_below="@id/booktitle" /> </LinearLayout> ------------------------------------------------------------------------------- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" tools:context=".MainActivity" > <ListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="fill_parent" > </ListView> <!-- <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent" > </android.support.v4.widget.SwipeRefreshLayout> --> </LinearLayout> --------------------------------------------------------------------------------- package com.example.testwipe; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { public List<Book> listBooks; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listview = (ListView)findViewById(R.id.listview); listBooks = new ArrayList<Book>(); listBooks.add( new Book(1, "呵呵", "介绍") ); listBooks.add( new Book(2, "呵呵", "介绍") ); listBooks.add( new Book(3, "呵呵", "介绍") ); listview.setAdapter( new MyListAdapter(getApplicationContext()) ); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } class MyListAdapter extends BaseAdapter { Context context; ArrayList<View> listViews; public MyListAdapter( Context context ) { this.context = context; LayoutInflater inflater = LayoutInflater.from(context); //把book列表的每一个数据渲染进view,然后放进一个list里, 供getView返回 listViews = new ArrayList<View>(); for( Book book : listBooks ) { View view = inflater.inflate(R.layout.list_one_item, null); TextView tv1 = (TextView)view.findViewById(R.id.booktitle); TextView tv2 = (TextView)view.findViewById(R.id.bookinfo); tv1.setText( String.valueOf(book.bookid) + " " + book.bookname ); tv2.setText( book.bookinfo ); listViews.add(view); } } @Override public int getCount() { return listBooks.size(); } @Override public Object getItem(int arg0) { return arg0; } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(int position, View convertView, ViewGroup parent) { return listViews.get(position); } } }
好吧,没有骗到你,上面的代码只是一个很普通的listview
现在在libs文件夹 导入 gson 和 android-async-http 的包
然后,不一一说明代码了,一大堆代码贴出来自己看啊
1 package com.example.testwipe; 2 3 public class Book { 4 5 int bookid; 6 7 8 String bookname; 9 String bookinfo; 10 11 public Book() { 12 13 } 14 15 16 public int getBookid() { 17 return bookid; 18 } 19 20 public void setBookid(int bookid) { 21 this.bookid = bookid; 22 } 23 24 public String getBookname() { 25 return bookname; 26 } 27 28 public void setBookname(String bookname) { 29 this.bookname = bookname; 30 } 31 32 public String getBookinfo() { 33 return bookinfo; 34 } 35 36 public void setBookinfo(String bookinfo) { 37 this.bookinfo = bookinfo; 38 } 39 }
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 tools:context=".MainActivity" > 6 7 <android.support.v4.widget.SwipeRefreshLayout 8 android:id="@+id/swipe_refresh" 9 android:layout_width="match_parent" 10 android:layout_height="match_parent" > 11 12 <ListView 13 android:id="@+id/listview" 14 android:layout_width="fill_parent" 15 android:layout_height="fill_parent" 16 > 17 </ListView> 18 19 20 </android.support.v4.widget.SwipeRefreshLayout> 21 22 23 24 </LinearLayout>
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="wrap_content" 5 android:orientation="vertical" 6 android:paddingBottom="10dp" 7 > 8 9 <TextView 10 android:id="@+id/booktitle" 11 android:layout_width="fill_parent" 12 android:layout_height="wrap_content" 13 android:background="#6FB3E0" 14 android:paddingTop="5dp" 15 android:paddingBottom="5dp" 16 android:textColor="#fff" 17 android:gravity="center" 18 19 /> 20 21 <TextView 22 android:id="@+id/bookinfo" 23 android:layout_width="fill_parent" 24 android:layout_height="wrap_content" 25 android:background="#fff" 26 android:paddingTop="5dp" 27 android:paddingBottom="5dp" 28 android:textColor="#0000EE" 29 android:gravity="center" 30 android:layout_below="@id/booktitle" 31 /> 32 33 34 </LinearLayout>
package com.example.testwipe; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; import com.google.gson.Gson; import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.RequestParams; public class MainActivity extends Activity { public ArrayList<Book> listBooks; private SwipeRefreshLayout swipeLayout; public MyListAdapter myListAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获得主界面的listview ListView listview = (ListView)findViewById(R.id.listview); listBooks = new ArrayList<Book>(); //listBooks.add( new Book(1, "呵呵", "介绍") ); //listBooks.add( new Book(2, "呵呵", "介绍") ); //listBooks.add( new Book(3, "呵呵", "介绍") ); //绑定适配器 myListAdapter = new MyListAdapter( getApplicationContext() , listBooks ); listview.setAdapter( myListAdapter ); //建立一个swipeLayout swipeLayout = (SwipeRefreshLayout) this.findViewById(R.id.swipe_refresh); // 顶部刷新的样式 swipeLayout.setColorScheme(android.R.color.holo_red_light, android.R.color.holo_green_light,android.R.color.holo_blue_bright, android.R.color.holo_orange_light); swipeLayout.setOnRefreshListener( new MyOnrefreshListener() ); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } //监听器 下拉拖动列表时触发 class MyOnrefreshListener implements OnRefreshListener { @Override public void onRefresh() { //用async http 发个请求 AsyncHttpClient client = new AsyncHttpClient(); RequestParams params = new RequestParams(); // 绑定参数 params.put("key1", "1"); //这里参数随便写 因为我发请求的那个网址不解析参数的,只是做个例子 params.put("key2", "2"); client.get("http://taobibi.kuphp.net/index1.php?", params, new AsyncHttpResponseHandler(){ @Override @Deprecated public void onSuccess(String content) { //因为返回了多个json 所以先把string 转成array String [] stringArray = content.split("\r\n"); Gson gson = new Gson(); Book book; for( String s : stringArray ) { //用Gson 把一个json字符串 解析成 对应的类的实例 book = gson.fromJson(s, Book.class); //把实例放进listBooks里 (更新数据源) listBooks.add(book); Log.v( "mytag", book.bookinfo ); } //通知 界面的适配器 重新更新数据 myListAdapter.notifyDataSetChanged(); //更新完毕,停止swipeLayout的刷新动画 swipeLayout.setRefreshing(false); //Log.v("mytag", String.valueOf( listBooks.size() ) ); } }); } } class MyListAdapter extends BaseAdapter { Context context; ArrayList<View> listViews; ArrayList<Book> listBooks; LayoutInflater inflater; public MyListAdapter( Context context, ArrayList<Book> list ) { this.context = context; inflater = LayoutInflater.from(context); this.listBooks = list; } @Override public int getCount() { return listBooks.size(); } @Override public Object getItem(int arg0) { return arg0; } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(int position, View convertView, ViewGroup parent) { //Log.v("mytag", String.valueOf( listBooks.size() ) ); // listBooks.size() - position - 1 是个关键 // 保证最新的数据显示在界面的上方,所以要逆序生成view Book book = listBooks.get( listBooks.size() - position - 1 ); View view = inflater.inflate(R.layout.list_one_item, null); TextView tv1 = (TextView)view.findViewById(R.id.booktitle); TextView tv2 = (TextView)view.findViewById(R.id.bookinfo); tv1.setText( String.valueOf(book.bookid) + " " + book.bookname ); tv2.setText( book.bookinfo ); return view; } } }
用PullToRefreshListView 还有点小问题没有解决
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <!-- The PullToRefreshListView replaces a standard ListView widget. --> <com.handmark.pulltorefresh.library.PullToRefreshListView android:id="@+id/pull_refresh_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="#00000000" android:divider="#19000000" android:dividerHeight="4dp" android:fadingEdge="none" android:fastScrollEnabled="false" android:footerDividersEnabled="false" android:headerDividersEnabled="false" android:smoothScrollbar="true" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/textview1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
package com.example.testpulltorefresh; import java.util.ArrayList; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; import com.handmark.pulltorefresh.library.PullToRefreshBase; import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; import com.handmark.pulltorefresh.library.PullToRefreshBase.State; import com.handmark.pulltorefresh.library.PullToRefreshListView; public class MainActivity extends Activity { public PullToRefreshListView pullToRefreshListView; public ArrayList<String> listStrings; public MyAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listStrings = new ArrayList<String>(); listStrings.add("asdasdasd"); listStrings.add("asdasdasd"); listStrings.add("asdasdasd"); myAdapter = new MyAdapter(); //初始化pullToRefreshListView pullToRefreshListView = (PullToRefreshListView)findViewById(R.id.pull_refresh_list); //让pullToRefreshListView上下两端都可以刷新 pullToRefreshListView.setMode(Mode.BOTH); //为pullToRefreshListView绑定适配器 pullToRefreshListView.setAdapter( myAdapter ); pullToRefreshListView.setOnRefreshListener( new OnRefreshListener<ListView>(){ @Override public void onRefresh(PullToRefreshBase<ListView> refreshView) { String label = DateUtils.formatDateTime(getApplicationContext(), System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL); refreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label); //每一次刷新 增加三个string listStrings.add("asdasdasd"); listStrings.add("asdasdasd"); listStrings.add("asdasdasd"); //通知适配器更新 myAdapter.notifyDataSetChanged(); pullToRefreshListView.onRefreshComplete(); } }); } class MyAdapter extends BaseAdapter { @Override public int getCount() { return listStrings.size(); } @Override public Object getItem(int arg0) { return arg0; } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(int arg0, View arg1, ViewGroup arg2) { LayoutInflater inflator = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflator.inflate(R.layout.list_one_item, null); TextView textView = (TextView)view.findViewById(R.id.textview1); textView.setText( listStrings.get(arg0) ); return view; } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }