2012-04-14 41 views
3

我想增加列表視圖滾動到結尾時列表視圖將動態顯示的項目數。 在我的情況下,我的列表視圖最初會顯示10個項目。那麼當我們滾動到最後一個項目時,它必須開始顯示10個項目等等。 我該怎麼做?動態增加列表視圖中元素的數量

這裏是我的自定義陣列適配器

package com.android.listview; 

import java.util.ArrayList; 

import com.android.listview.R; 
import com.android.listview.Product; 

import android.widget.ArrayAdapter; 

import android.content.Context; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.AbsListView; 
import android.widget.AbsListView.OnScrollListener; 
import android.widget.ImageView; 
import android.widget.TextView; 
import android.widget.Toast; 
import com.android.listview.ListViewActivity; 

public class CustomArrayAdapter extends ArrayAdapter<Product> implements 
     OnScrollListener { 

    private final Context context; 
    private final ArrayList<Product> values; 

    static class ViewHolder { 
     public TextView text; 
     public ImageView image; 
    } 

    public CustomArrayAdapter(Context arg0, int arg1, int arg2, 
      ArrayList<Product> arg3) { 
     super(arg0, arg1, arg2, arg3); 
     this.context = arg0; 
     this.values = arg3; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     LayoutInflater inflater = (LayoutInflater) context 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

     int product_id = 0; 
     View rowView = inflater.inflate(R.layout.feed_items, parent, false); 
     try { 

      ImageView wic_logo = (ImageView) rowView.findViewById(R.id.logo); 
      TextView label = (TextView) rowView.findViewById(R.id.label); 

      Product p = values.get(position); 
      product_id = p.productId; 
      String date = new java.text.SimpleDateFormat("dd/MM/yy") 
        .format(new java.util.Date(p.timeStamp)); 
      label.setText(p.productName + "\n" + p.reportedPrice + " MRP: " 
        + p.mrp + "\n" + "Discount: " + p.discount + "% " 
        + p.area + " " + p.city + "\n" + "Shared by " + p.userName 
        + " " + "on" + " " + date); 

      wic_logo.setImageResource(R.drawable.wic_logo_small); 
      Log.d("date", "" + date); 

      Log.d("Custom Array Adapter", "at" + position); 
     } catch (Exception e) { 
      Log.d("Custom Array Adapter", "catch"); 
     } 

     return rowView; 
    } 

    public void onScroll(AbsListView arg0, int firstVisibleItem, 
      int visibleItemCount, int totalItemCount) { 
     Log.d("entered onScroll", " " + firstVisibleItem + visibleItemCount 
       + totalItemCount); 
     if (((firstVisibleItem + visibleItemCount) >= totalItemCount - 1)) { 
      Log.d("entered if", " " + firstVisibleItem + visibleItemCount 
        + totalItemCount); 
      // if we're at the bottom of the listview, load more data 
      addData(totalItemCount, values.get(totalItemCount).productId); 
     } 
    } 

    private void addData(int totalItemCount, int productId) { 

     Toast.makeText(getContext(), "last item", Toast.LENGTH_SHORT).show(); 
    } 

    public void onScrollStateChanged(AbsListView arg0, int arg1) { 

    } 
} 

,這裏是我的活動

package com.android.listview; 

import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.ArrayList; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.ResponseHandler; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.BasicResponseHandler; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 

import com.android.listview.CustomArrayAdapter; 

import android.app.Activity; 
import android.os.Bundle; 
import android.util.Log; 
import android.widget.AbsListView; 
import android.widget.AbsListView.OnScrollListener; 
import android.widget.Button; 
import android.widget.ListView; 

public class ListViewActivity extends Activity { 

    static Product[] feed_products_list; 
    private JSONArray JArray; 
    private InputStream is; 
    private StringBuilder sb; 
    private String result; 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     Button feed_button = (Button) findViewById(R.id.feedButton_feed); 
     feed_button.setBackgroundResource(R.color.grey); 
     ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); 
     try { 
      HttpClient httpclient = new DefaultHttpClient(); 
      HttpPost httppost = new HttpPost("http://10.0.2.2/wic2/mobile/feed"); 
      httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
      ResponseHandler<String> responseHandler = new BasicResponseHandler(); 
      HttpResponse response = httpclient.execute(httppost); 
      HttpEntity entity = response.getEntity(); 
      is = entity.getContent(); 

      try { 
       BufferedReader reader = new BufferedReader(
         new InputStreamReader(is, "iso-8859-1"), 8); 
       sb = new StringBuilder(); 
       sb.append(reader.readLine() + "\n"); 
       String line = "0"; 
       while ((line = reader.readLine()) != null) { 
        sb.append(line + "\n"); 
       } 
       is.close(); 
       result = sb.toString(); 
       Log.d("result", result); 
      } catch (Exception e) { 
       Log.e("error", "Error in http connection" + e.toString()); 
      } 

      Log.e("response", "response is:" + response.toString()); 
     } catch (Exception e) { 
      Log.e("error", "Error in http connection" + e.toString()); 
     } 

     ListView tv = (ListView) findViewById(R.id.feedListView); 
     try { 
      Log.d("JArray", "entered try"); 
      JArray = new JSONArray(result); 
      int length = JArray.length(); 
      feed_products_list = new Product[length+1]; 
      Log.d("JArray", "try last line"); 
     } catch (JSONException e) { 
      Log.d("JArray", "in catch"); 
      e.printStackTrace(); 
     } 

     JSONObject jsonObj; 

     for (int i = 0; i < JArray.length(); i++) { 
      try { 
       Log.d("jsonObj", "entered try"); 
       jsonObj = JArray.getJSONObject(i); 
      } catch (Exception e) { 
       Log.d("jsonObj", "in catch"); 
       continue; 
      } 

      try { 
       Log.d("feed_products_list", "entered try"); 
       feed_products_list[i] = new Product(jsonObj.getInt("id"), 
         jsonObj.getString("image"), 
         jsonObj.getString("product_name"), 
         jsonObj.getString("reported_price_formated"), 
         jsonObj.getString("store_area"), 
         jsonObj.getString("store_city"), 
         jsonObj.getString("mrp"), 
         jsonObj.getString("user_name"), 
         jsonObj.getLong("reported_timestamp"), 
         jsonObj.getInt("discount")); 
       Log.d("feed_products_list", feed_products_list[i].productName); 
      } catch (JSONException e) { 
       Log.d("feed_products_list in catch", 
         feed_products_list[i].productName); 
       e.printStackTrace(); 
      } 
     } 

     tv.setAdapter(new CustomArrayAdapter(this, R.layout.feed_items, 
       R.id.label, feed_products_list)); 


    } 
} 

還有一個問題是,我有項目的數量來初始化我的數組feed_products_list [長度]在JArray。所以我可以我每次滾動到最後一個項目,時間不會改變數組大小重新填充整個列表再次

回答

3

首先,您的代碼存在一些問題。在您的Activity中,將變量values更改爲ArrayList<Product>,因爲您無法在創建後操縱數組的長度。接下來,將JArray重命名爲jArray;如果第一個字母是一個大寫,表示你正在處理一個類而不是一個變量。

此外,您沒有使用ViewHolder模式,這大大提高了性能。退房this link on vogella.com about ListView;更具體地說,查看章節3.1和3.2

CustomArrayAdapter中,執行OnScrollListener並添加所需的方法。然後,在onScroll(...)中,確定是否要添加數據(例如用戶到達列表底部)。最後,加載新項目,將其添加到您的數據集values.add(product)values.addAll(products),其中產品是ListProduct s,並在每次致電values.add(...)values.addAll(...)後,從您的CustomArrayAdapter中調用notifyDataSetChanged

例如,你可以改變你的代碼如下:

在你活動

  • 刪除線

    int length = JArray.length(); 
    feed_products_list = new Product[length+1]; 
    
  • 取下 '靜態'您的feed_products_list並將其更改爲ArrayList:

    private ArrayList<Product> feed_products_list = new ArrayList<Product>(); 
    
  • 而不是feed_products_list[i] = new Product(jsonObj.getInt("id"), .... yadiya ...,請調用feed_products_list.add(新產品(jsonObj.getInt(「id」),... yadiya ...`)。

在你適配器

  • 使類implement OnScrollListeneronScroll() - 方法設置爲類似以下內容:

    public void onScroll(AbsListView view, int firstVisibleItem, 
             int visibleItemCount, final int totalItemCount) { 
        if(((firstVisibleItem + visibleItemCount) >= totalItemCount)) { 
    
         // if we're at the bottom of the listview, load more data 
         addData(totalItemCount); 
        } 
    } 
    
  • 創建方法addData(long offset)

    private void addData(long offset) { 
    
        // download your data, pass the offset so you know where to start 
        // and when you convert your json into `Product`s 
        Product product = new Product(JSONObject.getInt("id"), ... yadiya ...); 
        this.add(product); 
        this.notifyDataSetChanged(); 
    
        // make sure to call notifyDataSetChanged() on your UI-Thread. 
    } 
    
+0

這裏的偏移量是最後一個項目的位置int他從我們要添加額外項目的位置列出? – Housefly 2012-04-14 09:23:13

+1

是的,你可以用它來告訴你的服務器哪些項目已經被下載。其他方式是發佈當前的日期時間或最後一次提取的項目的日期時間 - 這取決於您的需求。 – Reinier 2012-04-14 09:24:34

+0

它在哪裏指定onScroll方法被調用,當我滾動我正在使用的列表視圖.....就在onScroll中的if塊之前,我添加了一個日誌,並且從未出現在我的日誌貓中,當我滾動列表時 – Housefly 2012-04-25 07:17:42

1

你應該附上scroll listenerlistview

ListView lv = (ListView)findViewById(R.id.list_view); 
lv.setOnScrollListener(new OnScrollListener() { 
    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem, 
     int visibleItemCount, int totalItemCount) { 
     //Check if the last view is visible 
     if (view.getLastVisiblePosition()+1 == 10) { 
      //load more content 
     } 
    } 
}); 

更新

所以最初在您的feed_products_list中,您將有10個項目,當用戶向下滾動時,將10個項目添加到列表中並將CustomArrayAdapter重置爲listView。繼續這樣做,直到你擁有列表中的所有項目。

+0

謝謝。但也請幫助我如何動態增加我的數組大小,其中包含列表項。最初它是10滾動它必須我20 30 40 n等 – Housefly 2012-04-14 08:49:04

+0

使用ArrayLists ... – Ronnie 2012-04-14 09:03:39

+0

是的,使用ArrayList而不是陣列會更好地工作 – Mayank 2012-04-14 09:05:40

0

你不需要這樣做。 Android列表視圖可以輕鬆處理數千個條目 - 只要您仔細編寫適配器並重新使用視圖即可。所以在你的getView()方法中,你必須檢查是否提供了converView,並且是正確的,然後用新的值填充它。 (Andriod的是如此聰明,它提供回收這是正確的現在爲n加時賽可見列表條目) - 這會給你即時的性能提升

做這樣的:

View rowView = convertView; 
if(rowView == null) { 
    // do what you are doing now to inflate view 
} 
// do what you are doing now to set up view 

return rowView; 

增加列表的大小會如果您不想立即加載所有存儲的條目,則不需要加載來自 的所有條目 - 在這種情況下,您必須註冊滾動監聽器並通過加載缺失條目對其做出反應,然後發出信號,表明列表數據已更改。你不必使用數組作爲後備存儲 - 列表將是完美匹配的這個目的

+0

請你提供一個鏈接,詳細闡述了你在第1段 – Housefly 2012-04-14 08:54:19

+0

@ Archie.bpgc正在從websource下載內容;從開始加載更多數據可能會對用戶體驗造成負面影響,因爲初始加載需要更長的時間,尤其是連接不好或數據收集的規模較大時。 – Reinier 2012-04-14 09:17:14

+0

我在我的遊戲中做了幾乎相同的事情。最初,我在後臺加載所有高分數據,所以noew用戶在開始時並沒有獲得所有高分(並且通常新用戶在他們玩幾場遊戲之前對他們不感興趣) - 所以高分被加載到backgorund中。在此之後,我只從最後一次已知的高分入口(小)開始進行更改。我的數據生活在一個不相關的對象中,而列表適配器只是在需要時纔將它們列出。 – 2012-04-14 09:23:37

2

對於動態增加大小,最好使用ArrayList.For滾動可以使用@Mayank的想法。

0

使用ArrayList而不是數組 這樣

public class CustomArrayAdapter extends ArrayAdapter<Object> { 

    private final Context context; 
    private final ArrayList<Product> values; 

,並在您getView()

  Product p = values.get(position); 

你能提供您轉接器內的方法來添加元素到ArrayList和notifyDataSetChange()它看起來像這樣

public void addElement(Product p){ 
values.add(p); 
notifiyDataSetChange(); 
} 

使用OnScrollListener加載更多的數據 例如:

listView.setOnScrollListener(new OnScrollListener() { 
    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem, 
     int visibleItemCount, int totalItemCount) { 

     if (totalItemCount - visibleItemCount <= firstVisibeItem + 5) { 
      //load more content 

      ..... 
      adpater.addElement(p); 

     } 


    } 
    }); 
0

我想你想要像Lazy loading

它被稱爲延遲加載。我相信你沒有試過這樣的搜索。我已經給你GridView的例子。這是列表視圖的其他鏈接Other Link