2011-12-14 46 views
2

我試圖動態地將列表項插入到列表視圖中。當列表視圖被創建並顯示在屏幕上時,現在假設我從服務器或某個地方獲得了一個項目,現在我想在同一個列表視圖中添加此項目。怎麼做 ??有沒有什麼方法可以在顯示的列表視圖中動態插入項目,而無需再次創建列表agtain。有什麼方法可以改變列表項的狀態,這意味着我們可以在顯示時進行交互?你的答覆將不勝感激。 Thnx提前!ListView Activity,動態插入列表項

回答

5

任何你想要添加到正在使用你的Adapter,然後調用notifiyDataSetChanged()Adapter

與常規ArrayAdapter這將是數據結構(指List)是這樣的:

MyAdapter adapter = new MyAdapter(this, R.layout.row, myList); 
listView.setAdapter(adapter); 
... 
//make a bunch of changes to data 
list.add(foo); 
listView.getAdapter().notifyDataSetChanged(); 

我也可以提供一個更復雜的示例,其中包含BaseAdapter

編輯

我創建了一個小樣本,因爲這個問題似乎是很常見的。

在我的示例中,我在一個類中做了所有事情,只是爲了讓它更容易在一個地方跟蹤它。

最後,這是一個非常模型 - 視圖 - 控制器類型的情況。你甚至可以從這裏克隆它運行實際的項目:https://github.com/levinotik/Android-Frequently-Asked-Questions

它的本質是這樣的:

/** 
* This Activity answers the frequently asked question 
* of how to change items on the fly in a ListView. 
* 
* In my own project, some of the elements (inner classes, etc) 
* might be extracted into separate classes, but for clarity 
* purposes, I'm doing everything inline. 
* 
* The example here is very, very basic. But if you understand 
* the concept, it can scale to anything. You have complex 
* views bound to complex data wit complex conditions. 
* You could model a facebook user and update the ListView 
* based on changes to that user's data that's represented in 
* your model. 
*/ 
public class DynamicListViewActivity extends Activity { 

    MyCustomAdapter mAdapter; 

    @Override 
    public void onCreate(Bundle state) { 
     super.onCreate(state); 
     ListView listView = new ListView(this); 
     setContentView(listView); 

     /** 
     * Obviously, this will typically some from somewhere else, 
     * as opposed to be creating manually, one by one. 
     */ 

     ArrayList<MyObject> myListOfObjects = new ArrayList<MyObject>(); 

     MyObject object1 = new MyObject("I love Android", "ListViews are cool"); 
     myListOfObjects.add(object1); 
     MyObject object2 = new MyObject("Broccoli is healthy", "Pizza tastes good"); 
     myListOfObjects.add(object2); 
     MyObject object3 = new MyObject("bla bla bla", "random string"); 
     myListOfObjects.add(object3); 

     //Instantiate your custom adapter and hand it your listOfObjects 
     mAdapter = new MyCustomAdapter(this, myListOfObjects); 
     listView.setAdapter(mAdapter); 

     /** 
     * Now you are free to do whatever the hell you want to your ListView. 
     * You can add to the List, change an object in it, whatever. 
     * Just let your Adapter know that that the data has changed so it 
     * can refresh itself and the Views in the ListView. 
     */ 

     /**Here's an example. Set object2's condition to true. 
     If everyting worked right, then the background color 
     of that row will change to blue 
     Obviously you would do this based on some later event. 
     */ 
     object2.setSomeCondition(true); 
     mAdapter.notifyDataSetChanged(); 



    } 


    /** 
    * 
    * An Adapter is bridge between your data 
    * and the views that make up the ListView. 
    * You provide some data and the adapter 
    * helps to place them into the rows 
    * of the ListView. 
    * 
    * Subclassing BaseAdapter gives you the most 
    * flexibility. You'll have to override some 
    * methods to get it working. 
    */ 
    class MyCustomAdapter extends BaseAdapter { 

     private List<MyObject> mObjects; 
     private Context mContext; 

     /** 
     * Create a constructor that takes a List 
     * of some Objects to use as the Adapter's 
     * data 
     */ 
     public MyCustomAdapter(Context context, List<MyObject> objects) { 
      mObjects = objects; 
      mContext = context; 
     } 

     /** 
     * Tell the Adapter how many items are in your data. 
     * Here, we can just return the size of mObjects! 
     */ 
     @Override 
     public int getCount() { 
      return mObjects.size(); 
     } 

     /** 
     * Tell your the Adapter how to get an 
     * item as the specified position in the list. 
     */ 
     @Override 
     public Object getItem(int position) { 
      return mObjects.get(position); 
     } 

     /** 
     * If you want the id of the item 
     * to be something else, do something fancy here. 
     * Rarely any need for that. 
     */ 
     @Override 
     public long getItemId(int position) { 
      return position; 
     } 

     /** 
     * Here's where the real work takes place. 
     * Here you tell the Adapter what View to show 
     * for the rows in the ListView. 
     * 
     * ListViews try to recycle views, so the "convertView" 
     * is provided for you to reuse, but you need to check if 
     * it's null before trying to reuse it. 
     * @param position 
     * @param convertView 
     * @param parent 
     * @return 
     */ 
     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      MyView view; 
      if(convertView == null){ 
       view = new MyView(mContext); 
      } else { 
       view = (MyView) convertView; 
      } 
      /**Here's where we utilize the method we exposed 
      in order to change the view based on the data 
      So right before you return the View for the ListView 
      to use, you just call that method. 
      */ 
      view.configure(mObjects.get(position)); 

      return view; 
     } 
    } 


    /** 
    * Very simple layout to use in the ListView. 
    * Just shows some text in the center of the View 
    */ 
    public class MyView extends RelativeLayout { 

     private TextView someText; 

     public MyView(Context context) { 
      super(context); 

      LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 
      params.addRule(CENTER_IN_PARENT); 
      someText = new TextView(context); 
      someText.setTextSize(20); 
      someText.setTextColor(Color.BLACK); 
      someText.setLayoutParams(params); 
      addView(someText); 
     } 

     /** 
     * Remember, your View is an regular object like any other. 
     * You can add whatever methods you want and expose it to the world! 
     * We have the method take a "MyObject" and do things to the View 
     * based on it. 
     */ 

     public void configure(MyObject object) { 

      someText.setText(object.bar); 
      //Check if the condition is true, if it is, set background of view to Blue. 
      if(object.isSomeCondition()) { 
       this.setBackgroundColor(Color.BLUE); 
      } else { //You probably need this else, because when views are recycled, it may just use Blue even when the condition isn't true. 
       this.setBackgroundColor(Color.WHITE); 
      } 
     } 
    } 

    /** 
    * This can be anything you want. Usually, 
    * it's some object that makes sense according 
    * to your business logic/domain. 
    * 
    * I'm purposely keeping this class as simple 
    * as possible to demonstrate the point. 
    */ 
    class MyObject { 
     private String foo; 
     private String bar; 
     private boolean someCondition; 


     public boolean isSomeCondition() { 
      return someCondition; 
     } 


     MyObject(String foo, String bar) { 
      this.foo = foo; 
      this.bar = bar; 
     } 

     public void setSomeCondition(boolean b) { 
      someCondition = b; 
     } 
    } 

} 

如果您在此處把握的概念,你應該能夠適應(沒有雙關語意)這ArrayAdapters等

+0

可不可以用示例代碼詳細闡述??這對我更有幫助。 – 2011-12-14 05:17:13

+0

好吧。假設有一些列表視圖項目(例如聯繫人列表)存在,現在顯示時我想要更改特定列表項目的文本顏色,假設線上/離線狀態來自服務器端或某些地方。我怎樣才能做到這一點?? – 2011-12-14 06:04:11

0

是,通過一個適配器,您在ListView填充,更新項目需要時,增加新項目等

如果你過網拉取數據,你可以首先使用普通的ArrayAdapter(通常通過繼承和重寫getView()方法來構建您的佈局),然後添加和刪除它提供的列表中的項目。如果將項目添加到列表中,則向下滾動時會顯示在列表的末尾(如果您位於最下面,則立即顯示)。如果您修改一個項目,該列表將立即在屏幕上更新。

如果您在模型對象上使用setter,那麼適配器將不會知道這一點,但您可以撥打notifyDataSetChanged()。如果您想一次對列表進行多處更改而不會導致屏幕閃爍,您可能還需要查看setNotifyOnChange()方法。