Android UI組件----自定義ListView實現動態刷新

【聲明】html

歡迎轉載,但請保留文章原始出處→_→java

生命壹號:http://www.cnblogs.com/smyhvae/android

文章來源:http://www.cnblogs.com/smyhvae/p/3910541.html安全

 

【正文】微信

1、具體步驟:app

(1)在activiy_main.xml中加一個ListView控件;再添加一個item的模板activity_main_item.xml,加一個底部加載的視圖activity_main_load.xml;ide

(2)初始化item中的數據;學習

(3)自定義適配器BaseAdapter;優化

(4)ListiView綁定監聽器OnScrollListener,並實現該監聽器的兩個方法:this

    • public void onScrollStateChanged(AbsListView view, int scrollState)
    • public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount)

      注:若是屏幕滑到最下面了,而且scrollState的狀態爲:滾動完畢以後ListView處於中止狀態(手離開屏幕),此時能夠加載新數據了

(5)經過額外的線程,來模擬加載新數據;

(6)新數據加載完成後,經過handle通知主線程,將這個新數據顯示在UI界面上(由於涉及到線程安全問題),此時要調用notifyDataSetChanged()方法來刷新。

       注:handler爲線程之間通訊的橋樑

 

2、代碼實現: 

完整版代碼以下:

activiy_main.xml代碼以下:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     tools:context=".MainActivity" >
 6     <ListView
 7         android:id="@+id/listView1"
 8         android:layout_width="match_parent"
 9         android:layout_height="match_parent" >
10     </ListView>
11 </LinearLayout>

注:爲優化起見,第9行的代碼必定要寫成"match_parent",而不是「wrap_content」(解釋略)

 

activity_main_item.xml代碼以下:(做爲一個item的模板)

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6     <TextView
 7     android:id="@+id/textView1_title"
 8     android:layout_width="match_parent"
 9     android:layout_height="wrap_content"
10     android:text="Large Text"
11     android:textAppearance="?android:attr/textAppearanceLarge" />
12     <TextView
13         android:id="@+id/textView2_content"
14         android:layout_width="match_parent"
15         android:layout_height="wrap_content"
16         android:text="TextView" />
17 </LinearLayout>

 

activity_main_load.xml代碼以下:(做爲加載時底部的顯示)

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="wrap_content"
 5     android:orientation="horizontal"
 6     android:gravity="center" >
 7 
 8     <ProgressBar
 9         android:id="@+id/progressBar1"
10         android:layout_width="25dp"
11         android:layout_height="25dp" />
12 
13     <TextView
14         android:id="@+id/textView1"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content"
17         android:text="正在加載···" />
18 
19 </LinearLayout>

 

MainActivity.java代碼以下:

  1 package com.smyhvae.smyh005listview5;
  2 
  3 import java.util.Vector;
  4 
  5 import android.app.Activity;
  6 import android.os.Bundle;
  7 import android.os.Handler;
  8 import android.os.Message;
  9 import android.view.Menu;
 10 import android.view.View;
 11 import android.view.ViewGroup;
 12 import android.widget.AbsListView;
 13 import android.widget.AbsListView.OnScrollListener;
 14 import android.widget.BaseAdapter;
 15 import android.widget.ListView;
 16 import android.widget.TextView;
 17 
 18 public class MainActivity extends Activity {
 19 
 20     private ListView listView;
 21     Vector<News> news = new Vector<News>();
 22     //private ArrayList<News> news = new ArrayList<News>();上面一行與這一行,二選一
 23     MyAdapter myAdapter;
 24     
 25     @Override
 26     protected void onCreate(Bundle savedInstanceState) {
 27         super.onCreate(savedInstanceState);
 28         setContentView(R.layout.activity_main);
 29         listView = (ListView)findViewById(R.id.listView1);
 30         
 31         listView.setOnScrollListener(new ListViewListener());  //綁定監聽器
 32         
 33         //設置底部視圖
 34         View footer = getLayoutInflater().inflate(R.layout.activity_main_load, null);
 35         listView.addFooterView(footer);        
 36         
 37 //        initData();
 38         new LoadDataThread().start();//加載數據的工做線程
 39             
 40         myAdapter = new MyAdapter();
 41         listView.setAdapter(myAdapter);
 42     }
 43 
 44    //定義一個數據的類
 45     class News {
 46         String title;
 47         String content;
 48     }
 49     
 50     int index = 1;//數據的記數器(索引)
 51     //初始化數據
 52     void initData(){        
 53         System.out.println("initData");
 54         for (int i = 0; i < 15; i++) {
 55             News n = new News();  //這句話必定要放在循環的裏面,不然每一個item顯示的內容都是同樣的
 56             n.title = "title-"+index;
 57             n.content = "content"+index;
 58             index++;
 59             news.add(n);  //這一步很關鍵,我就是少了這一步,致使運行時,界面爲空
 60         }
 61     }
 62     
 63     
 64     
 65     //自定義適配器
 66     class MyAdapter extends BaseAdapter{
 67 
 68         @Override
 69         public int getCount() {
 70             // TODO Auto-generated method stub
 71             return news.size();
 72         }
 73         public Object getItem(int position) {
 74             return news.get(position);
 75         }
 76 
 77         @Override
 78         public long getItemId(int position) {
 79             return position;
 80         }
 81 
 82         @Override
 83         public View getView(int position, View convertView, ViewGroup parent) {
 84             ViewHolder viewHolder = new ViewHolder();
 85             //經過下面的條件判斷語句,來循環利用。若是convertView = null ,表示屏幕上沒有能夠被重複利用的對象。
 86             if(convertView==null){
 87                 //建立View
 88                 convertView = getLayoutInflater().inflate(R.layout.activity_main_item, null);
 89                 viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.textView1_title);
 90                 viewHolder.tvContent = (TextView) convertView.findViewById(R.id.textView2_content);
 91                 convertView.setTag(viewHolder);
 92             }else{
 93                 viewHolder = (ViewHolder)convertView.getTag();
 94             }
 95             //從Vector中取出數據填充到ListView列表項中
 96             News n = news.get(position);
 97             viewHolder.tvTitle.setText(n.title);
 98             viewHolder.tvContent.setText(n.content);
 99             return convertView;
100         }
101         
102     }
103 
104     static class ViewHolder{
105         TextView tvTitle;
106         TextView tvContent;
107     }    
108 
109     
110 
111     
112     //實現ListView的監聽器的接口
113     int visibleLastIndex = 0; //最後一個顯示的索引    
114     public class ListViewListener implements OnScrollListener{        
115         @Override
116         public void onScrollStateChanged(AbsListView view, int scrollState) {
117             //若是屏幕滑到最下面了,而且scrollState的狀態爲:滾動完畢以後ListView處於中止狀態(手離開屏幕),
118             if(visibleLastIndex==myAdapter.getCount() && scrollState==OnScrollListener.SCROLL_STATE_IDLE){
119                 new LoadDataThread().start();//若是知足上面的條件,此時,能夠加載新數據了
120             }
121         }
122 
123         @Override
124         public void onScroll(AbsListView view, int firstVisibleItem,
125             int visibleItemCount, int totalItemCount) {
126             visibleLastIndex = firstVisibleItem+visibleItemCount-1;
127             
128         }
129         
130     }
131     
132     //額外開啓一個線程,模擬加載數據
133     class LoadDataThread extends Thread{
134         @Override
135         public void run() {
136             initData();
137             try {
138                 Thread.sleep(2000);//休眠兩秒
139             } catch (InterruptedException e) {
140                 // TODO Auto-generated catch block
141                 e.printStackTrace();
142             }
143             
144             //新數據加載完成後,經過handle通知主線程,將這個新數據顯示在UI界面上(由於涉及到線程安全問題)
145             handler.sendEmptyMessage(1); 146         }
147     }      
148     
149     //handler爲線程之間通訊的橋樑    
150     private Handler handler = new Handler(){
151         public void handleMessage(Message msg) {
152             switch(msg.what){
153             case 1:  //根據上面的提示,當Message爲1,表示數據處理完了,能夠通知主線程了
154                  myAdapter.notifyDataSetChanged();        //這個方法一旦調用,UI界面就刷新了
155                 break;
156                 
157             default :
158                 break;
159             }
160         }
161         
162     };
163     
164     
165     @Override
166     public boolean onCreateOptionsMenu(Menu menu) {
167         // Inflate the menu; this adds items to the action bar if it is present.
168         getMenuInflater().inflate(R.menu.main, menu);
169         return true;
170     }
171 
172 
173     
174 }

運行後,顯示結果以下:

下圖依次爲:剛運行時、滑動到底部時、刷新以後的效果

 

3、總結:

  • 監聽事件處理的接口:OnScrollListener
  • Adapter的刷新方法:notifyDataSetChanged()

 

【工程文件】

密碼:bqsy
 

個人公衆號

想學習代碼以外的軟技能?不妨關注個人微信公衆號:生命團隊(id:vitateam)。

掃一掃,你將發現另外一個全新的世界,而這將是一場美麗的意外:

相關文章
相關標籤/搜索