2010-05-19 29 views
0

Long Story Short:我的活動更新方法是通過ArrayAdapter更新和滾動ListView,但內部TimerTask的方法用於輪詢消息(顯示在ListView中)更新ListView,但不滾動它。爲什麼?爲什麼我的按鈕可以觸發UI滾動,並且我的TimerTask在活動內部不能?

長篇:

我有這個佈局的聊天活動:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:background="#fff" 
    > 
    <ListView android:id="@+id/messageList" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:stackFromBottom="true" 
     android:transcriptMode="alwaysScroll" 
     android:layout_weight="1" 
     android:fadeScrollbars="true" 
    /> 
    <LinearLayout 
     android:orientation="horizontal" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:gravity="center" 
     > 
     <EditText android:id="@+id/message" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
     /> 
     <Button android:id="@+id/button_send" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Send" 
      android:onClick="sendMessage" 
     /> 
    </LinearLayout> 
</LinearLayout> 

內部的ListView(ID爲給messageManager)由膨脹下面的XML和它替換字符串的ArrayAdapter填充。

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:clickable="false" 
    android:background="#fff" 
    android:paddingLeft="2dp" 
    android:paddingRight="2dp" 
    > 
    <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/date" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:textSize="16sp" 
    android:textColor="#00F" 
    android:typeface="monospace" 
    android:text="2010-10-12 12:12:03" 
    android:gravity="left" 
/> 
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/sender" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:textSize="16sp" 
    android:textColor="#f84" 
    android:text="spidey" 
    android:gravity="right" 
    android:textStyle="bold" 
/> 
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/body" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:textSize="14sp" 
    android:padding="1dp" 
    android:gravity="left" 
    android:layout_below="@id/date" 
    android:text="Mensagem muito legal 123 quatro cinco seis." 
    android:textColor="#000" 
/> 
</RelativeLayout> 

問題是:在主佈局中,我有一個用於聊天消息的EditText和一個用於發送消息的Button。我宣佈在活動範圍內的適配器:

public class ChatManager extends Activity{ 

private EditText et; 
private ListView lv; 
private Timestamp lastDate = null; 
private long campaignId; 
private ChatAdapter ca; 
private List<ChatMessage> vetMsg = new ArrayList<ChatMessage>(); 
private Timer chatPollingTimer; 
private static final int CHAT_POLLING_PERIOD = 10000; 
... 
} 

所以,裏面的sendMessage(視圖V),在notifyDataSetChanged()滾動的ListView acordingly,這樣我就可以自動看到最新的聊天消息:

public void sendMessage(View v) { 
    String msg = et.getText().toString(); 

    if(msg.length() == 0){ 
    return; 
    } 

    et.setText(""); 

    String xml = ServerCom.sendAndGetChatMessages(campaignId, lastDate, msg); 
    Vector<ChatMessage> vetNew = Chat.parse(new InputSource(new StringReader(xml))); 
    //Pegando a última data 
    if(!vetNew.isEmpty()){ 
    lastDate = vetNew.lastElement().getDateSent(); 
    //Atualizando a tela 
    vetMsg.addAll(vetNew); 
    ca.notifyDataSetChanged(); 
    } 
    } 

但我的TimerTask,我不能。 ListView已更新,但它不會自動滾動。我究竟做錯了什麼?

private class chatPollingTask extends TimerTask { 
    @Override 
    public void run() { 
    String xml; 

    if(lastDate != null){ 
    //Chama o Updater 
    xml = ServerCom.getChatMessages(campaignId, lastDate); 
    }else{ 
    //Chama o init denovo 
    xml = ServerCom.getChatMessages(campaignId); 
    } 

    Vector<ChatMessage> vetNew = Chat.parse(new InputSource(new StringReader(xml))); 
    if(!(vetNew.isEmpty())){ 
    //TODO: descobrir porque o chat não está rolando quando chegam novas mensagens 
    //Descobrir também como forçar o rolamento, enquanto o bug não for corrigido. 
    Log.d("CHAT", "New message(s) acquired!"); 
    lastDate = vetNew.lastElement().getDateSent(); 
    vetMsg.addAll(vetNew); 
    ca.notifyDataSetChanged(); 
    } 

    } 
} 

如何強制滾動到底部?我試過使用scrollTo使用lv.getBottom() - lv.getHeight(),但沒有奏效。這是Android SDK中的錯誤嗎?

對不起,大量的代碼,但我想這種方式的問題變得非常清楚。

回答

0

您需要在UI線程上調用數據集(notifyDataSetChanged())的更改。 TimerTask在不同的線程上被調用。有許多方法可以完成此操作,請參閱this blog post以獲取一系列方法。

關於scrollTo,在滾動列表之後不用於滾動。它滾動整個視圖元素..不完全是你所期望的。而是使用ListView.setSelection方法之一。

+0

我已經嘗試在我的活動中創建一個方法,然後在此處發佈問題只是爲了嘗試解決此「主UI線程外的問題」問題,但它也不起作用。 – Spidey 2010-05-20 17:24:45

+0

setSelection(vetMsgs.size() - 1)也不起作用。 – Spidey 2010-05-20 17:53:38

+0

其實,現在我想到了它,我不知道爲什麼notifyDatasetChanged應該導致列表滾動到底部。看起來你應該在調用notifyDatasetChanged後立即調用ListView.setSelection(vetNew.size()-1)。 – 2010-05-20 17:56:25

相關問題