2013-01-25 86 views
0

我正在開發一個有點聊天應用程序,並希望使用ListView來顯示消息。目前我正在嘗試獲取用戶的輸入並將其顯示爲「傳出消息」。我的row佈局如下:TextView(時間戳),TextView(消息),ImageView(消息狀態指示符)。我的問題:文本和時間戳沒有設置,只是一個「虛擬」佈局膨脹。我想我必須以某種方式設置適配器內的文本。有人能告訴我我做錯了什麼嗎?代碼如下。爲聊天應用程序實現自定義ListView

我的適配器:

public class ChatAdapter extends BaseAdapter { 
private Context context; 

private List<String> chat; 

public ChatAdapter(Context context, List<String> listchat) { 
    this.context = context; 
    this.chat = listchat; 
} 

public int getCount() { 
    return chat.size(); 
} 

public Object getItem(int position) { 
    return chat.get(position); 
} 

public long getItemId(int position) { 
    return position; 
} 

public View getView(int position, View convertView, ViewGroup viewGroup) { 

    if (convertView == null) { 
     LayoutInflater inflater = (LayoutInflater) context 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView = inflater.inflate(R.layout.row, null); 
    } 
    TextView tvTS = (TextView) convertView.findViewById(R.id.tvTS); 
    // TODO set timestamp 

    TextView tvMessage = (TextView) convertView 
      .findViewById(R.id.tvMessage); 
    // TODO set the text to the actual message text from etInput 

    ImageView indicator = (ImageView) convertView.findViewById(R.id.imgInd); 

    // TODO set the image Resource according to message state 
    return convertView; 
} 

我的活動:

public class ChatActivity extends ListActivity { 

private EditText input; 
private String tmpMessage; 
ListView lv; 
ChatAdapter adapter; 
List<String> messages; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.lis); 
    Button send = (Button) findViewById(R.id.btnSend); 
    input = (EditText) findViewById(R.id.etInput); 
    lv = getListView(); 

    messages = new ArrayList<String>(); 
    adapter = new ChatAdapter(this, messages); 
    lv.setOnItemClickListener(new OnItemClickListener() { 

     @Override 
     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, 
       long arg3) { 
      // TODO 
     } 
    }); 

    lv.setAdapter(adapter); 

    send.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      sendMessage(); 
     } 
    }); 
} 

public void sendMessage() { 

    tmpMessage = input.getText().toString(); 
    input.setText(""); 
    messages.add(tmpMessage); 
    adapter.notifyDataSetChanged(); 

} 

@SuppressLint("SimpleDateFormat") 
public String generateTimestamp() { 
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); 
    String ts = sdf.format(new Date()); 

    return ts; 
} 

UPDATE

我添加了一個保持器,並使用以下代碼設置文本:

String message = (String) getItem(position); 
     holder.message.setText(message); 

它的作品,但膨脹的佈局現在隨機定位,見下面的截圖。它應該看起來像

測試

test1的

test2的

....

enter image description here

的原因是什麼?

回答

1

你似乎沒有數據被設置爲TextViews/ImageView的。你需要做這在你ChatAdapter的getView()方法,如下所示:

public View getView(int position, View convertView, ViewGroup viewGroup) { 

    if (convertView == null) { 
     LayoutInflater inflater = (LayoutInflater) context 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView = inflater.inflate(R.layout.row, null); 
    } 
    String chatMessage = getItem(position); 
    TextView tvTS = (TextView) convertView.findViewById(R.id.tvTS); 
    // TODO set timestamp 

    TextView tvMessage = (TextView) convertView 
      .findViewById(R.id.tvMessage); 
    //Set the message to the TextView 
    tvMessage.setText(chatMessage); 

    ImageView indicator = (ImageView) convertView.findViewById(R.id.imgInd); 

    // TODO set the image Resource according to message state 
    return convertView; 
} 

考慮使用自定義的對象(而不是字符串列表)來保存信息,時間戳和消息狀態的類型指標被顯示。在這種情況下,你可以這樣做

ChatMessage msgObj = getItem(position); 
... 
tvMessage.setText(msgObj.getMessage()); 
tvTS.setText(msgObj.getTimestamp()); 
if (msgObj.getStatus() == ChatMessage.DELIVERED) 
{ 
    indicator.setBackgroundResource(R.drawable.delivered); 
} 
else if (....) 
1

您必須在您的getView中調用setText方法獲取文本方法,併爲每個需要的視圖設置文本。並設置你的形象。 getView負責爲列表創建單個視圖,因此您必須以每次都會返回就緒視圖的方式實現它。

你現在正在做的只是通過尋找其ID元素,無所事事他們。您只需返回默認的虛浮行。

P.S.還請閱讀有關性能問題的ViewHolder模式。

1

嘗試在getView

public View getView(int position, View convertView, ViewGroup viewGroup) { 

if (convertView == null) { 
    LayoutInflater inflater = (LayoutInflater) context 
      .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    convertView = inflater.inflate(R.layout.row, null); 

TextView tvTS = (TextView) convertView.findViewById(R.id.tvTS);  

TextView tvMessage = (TextView) convertView.findViewById(R.id.tvMessage); 

ImageView indicator = (ImageView) convertView.findViewById(R.id.imgInd); 

} 
tvMessage.setText("......"); 

return convertView; 

}以下更改

Please see this link

+0

問題是我必須在每次調用時都將消息字符串傳遞給getView方法。不知道如何從我的ChatActivity類中做到這一點.. – Droidman

+1

我想你不能將消息傳遞給getview方法。您可以更改適配器。並且在更改適配器調用notifyDataSetChanged() – Swati

+0

之後,您能否通過更改適配器來解釋您的意思? – Droidman

1

你可以使用更好的性能ViewHolder模式清單上

ViewHolder類:

public class ViewHolder{ 
public TextView message; 
public TextView timestamp; 
public ImageView indicator 
} 

然後在適配器getView方法使用以下方式:

public View getView(int position, View convertView, ViewGroup viewGroup) { 

    ViewHolder holder = null; 

      if(convertView == null){ 
       convertView = inflater.inflate(R.layout.<your_layout>, null);   

       holder = new ViewHolder(); 
       holder.message = (TextView) convertView.findViewById(R.id.message); 
holder.timestamp = (TextView) convertView.findViewById(R.id.timestamp); 
holder.indicator = (ImageView) convertView.findViewById(R.id.indicator); 

       convertView.setTag(holder); 
      } else{ 
       holder = (ViewHolder) convertView.getTag(); 

      } 

      holder.message.setText(chat.get(position).<whatever>); 
      holder.timestamp.setText(chat.get(position).<whatever>); 
holder.indicator.<method> 
      return convertView; 
} 

希望有所幫助。

BR, mybecks