仿微信、QQ聊天界麵私信對話效果
https://blog.csdn.net/junhuahouse/article/details/39076821
我們大家可能都看到過在自己使用社交Android軟件的時候,會發現聊天頁麵的效果;有人說是氣泡效果,也很像,是吧?那我們該怎麼去實現那種效果呢??
這個就是效果:有人物頭像、聊天的當時時間、聊天內容、發送信息等;其實呢,她的思路很簡單,我也弄了幾個小時!恩,那我們就簡單詳細的聊聊吧!先看源代碼:項目入口MainActivity.java:
- public class MainActivity extends Activity {
- private LinkedList<PeopleStudentBean> sList = null;
- private LinkedList<PeopleTeacherBean> tList = null;
- private LinkedList<Bean> beans = null;
- /** 聊天message 格式 */
- private ListView listView;
- /** 信息編輯框 */
- private EditText edt;
- /** 信息發送按鈕 */
- private Button btnEnter;
- private CustomAdapter adapter;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- sList = new LinkedList<PeopleStudentBean>();
- tList = new LinkedList<PeopleTeacherBean>();
- beans = new LinkedList<Bean>();
- String[] msg = new String[] { "你好!", "你也在金象工作嗎?", "我在天安門掃大街呢,這裏可舒服了!",
- "原來你也細化這個工作啊,我這裏還招人呢,你來不?來的話,我一句話的事兒!", "嗬嗬,你好!", "是的,你在哪裏呢?",
- "吼吼,這麼便宜的事兒?!,我怎麼沒有遇到呢。", "恩,好啊 好啊。那等著我。。。" };
- // 0 是教師; 1 是學生
- for (int i = 0; i < 4; i++) {
- sList.add(new PeopleStudentBean(msg[i], R.drawable.you,"", 1));
- tList.add(new PeopleTeacherBean(msg[i + 4], R.drawable.me,"", 0));
- }
- // 歸放到 同一個 類集合Bean中
- for (int j = 0; j < sList.size(); j++) {
- beans.add(sList.get(j));
- beans.add(tList.get(j));
- }
- setContentView(R.layout.activity_main);
- initViewsMethod();
- onHandleMethod();
- }
- /** 處理listView 的 item方法 */
- private void initViewsMethod(){
- listView = (ListView) findViewById(R.id.lvMessages);
- edt = (EditText) findViewById(R.id.edt);
- btnEnter = (Button) findViewById(R.id.enter);
- listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
- // TODO Auto-generated method stub
- menu.setHeaderTitle("提示:");
- menu.setHeaderIcon(android.R.drawable.stat_notify_error);
- menu.add(0, 0, 1, "刪除");
- menu.add(1, 1, 0, "取消");
- }
- });
- }
- /** 處理發送信息的方法 */
- public void onHandleMethod(){
- adapter = new CustomAdapter(this, beans);
- listView.setAdapter(adapter);
- btnEnter.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- String txt = edt.getText().toString();
- if(null == txt)
- Toast.makeText(getApplicationContext(), "發送內容不能為空 !", Toast.LENGTH_SHORT).show();
- adapter.addItemNotifiChange(new Bean(txt, R.drawable.me, new Date()+"", 0));
- edt.setText("");
- listView.setSelection(beans.size()-1);
- }
- });
- }
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- // TODO Auto-generated method stub
- switch (item.getItemId()) {
- case 0:
- Toast.makeText(getApplicationContext(), "刪除成功", Toast.LENGTH_SHORT).show();
- AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
- Bean bean = (Bean) adapter.getItem(info.position);
- beans.remove(bean);
- adapter.notifyDataSetChanged();
- break;
- }
- return super.onContextItemSelected(item);
- }
public class MainActivity extends Activity { private LinkedList<PeopleStudentBean> sList = null; private LinkedList<PeopleTeacherBean> tList = null; private LinkedList<Bean> beans = null; /** 聊天message 格式 */ private ListView listView; /** 信息編輯框 */ private EditText edt; /** 信息發送按鈕 */ private Button btnEnter; private CustomAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sList = new LinkedList<PeopleStudentBean>(); tList = new LinkedList<PeopleTeacherBean>(); beans = new LinkedList<Bean>(); String[] msg = new String[] { "你好!", "你也在金象工作嗎?", "我在天安門掃大街呢,這裏可舒服了!", "原來你也細化這個工作啊,我這裏還招人呢,你來不?來的話,我一句話的事兒!", "嗬嗬,你好!", "是的,你在哪裏呢?", "吼吼,這麼便宜的事兒?!,我怎麼沒有遇到呢。", "恩,好啊 好啊。那等著我。。。" }; // 0 是教師; 1 是學生 for (int i = 0; i < 4; i++) { sList.add(new PeopleStudentBean(msg[i], R.drawable.you,"", 1)); tList.add(new PeopleTeacherBean(msg[i + 4], R.drawable.me,"", 0)); } // 歸放到 同一個 類集合Bean中 for (int j = 0; j < sList.size(); j++) { beans.add(sList.get(j)); beans.add(tList.get(j)); } setContentView(R.layout.activity_main); initViewsMethod(); onHandleMethod(); } /** 處理listView 的 item方法 */ private void initViewsMethod(){ listView = (ListView) findViewById(R.id.lvMessages); edt = (EditText) findViewById(R.id.edt); btnEnter = (Button) findViewById(R.id.enter); listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // TODO Auto-generated method stub menu.setHeaderTitle("提示:"); menu.setHeaderIcon(android.R.drawable.stat_notify_error); menu.add(0, 0, 1, "刪除"); menu.add(1, 1, 0, "取消"); } }); } /** 處理發送信息的方法 */ public void onHandleMethod(){ adapter = new CustomAdapter(this, beans); listView.setAdapter(adapter); btnEnter.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub String txt = edt.getText().toString(); if(null == txt) Toast.makeText(getApplicationContext(), "發送內容不能為空 !", Toast.LENGTH_SHORT).show(); adapter.addItemNotifiChange(new Bean(txt, R.drawable.me, new Date()+"", 0)); edt.setText(""); listView.setSelection(beans.size()-1); } }); } @Override public boolean onContextItemSelected(MenuItem item) { // TODO Auto-generated method stub switch (item.getItemId()) { case 0: Toast.makeText(getApplicationContext(), "刪除成功", Toast.LENGTH_SHORT).show(); AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); Bean bean = (Bean) adapter.getItem(info.position); beans.remove(bean); adapter.notifyDataSetChanged(); break; } return super.onContextItemSelected(item); }
填充效果內容對應的自定義適配器CustomAdapter.java:
- public class CustomAdapter extends BaseAdapter {
- private LinkedList<Bean> beans = null;
- private LayoutInflater li;
- private final int ITEM_TYPES = 2, TYPE_0 = 0, TYPE_1 = 1;
- public CustomAdapter(Context context, LinkedList<Bean> beans) {
- // TODO Auto-generated constructor stub
- this.beans = beans;
- li = LayoutInflater.from(context);
- }
- @Override
- public int getCount() {
- // TODO Auto-generated method stub
- return beans.size();
- }
- @Override
- public Object getItem(int position) {
- // TODO Auto-generated method stub
- return beans.get(position);
- }
- @Override
- public long getItemId(int position) {
- // TODO Auto-generated method stub
- return position;
- }
- @Override
- public int getViewTypeCount() {
- // TODO Auto-generated method stub
- return ITEM_TYPES;
- }
- @Override
- public int getItemViewType(int position) {
- // TODO Auto-generated method stub
- int tp = beans.get(position).getId();
- if (TYPE_0 == tp)
- return TYPE_0;
- else if (TYPE_1 == tp)
- return TYPE_1;
- return TYPE_0;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- // TODO Auto-generated method stub
- PeopleView s = null;
- Bean bean = beans.get(position);
- int type = getItemViewType(position);
- if (null == convertView) {
- s = new PeopleView();
- switch (type) {
- case TYPE_0:
- convertView = li.inflate(R.layout.listview_item_teacher, null);
- break;
- case TYPE_1:
- convertView = li.inflate(R.layout.listview_item_student, null);
- break;
- }
- s.time = (TextView) convertView.findViewById(R.id.Time);
- s.message = (TextView) convertView.findViewById(R.id.Msg);
- s.portrait = (ImageView) convertView.findViewById(R.id.Img);
- convertView.setTag(s);
- } else
- s = (PeopleView) convertView.getTag();
- s.time.setText(DateFomats.getCurrentTime(new Date().getTime()));
- s.message.setText(bean.gettMessage());
- s.portrait.setImageResource(R.drawable.you);
- return convertView;
- }
- class PeopleView {
- TextView time;
- TextView message;
- ImageView portrait;
- }
- /** 添加發表私信內容,更新列表 */
- public void addItemNotifiChange(Bean bean) {
- beans.add(bean);
- notifyDataSetChanged();
- }
- }
public class CustomAdapter extends BaseAdapter { private LinkedList<Bean> beans = null; private LayoutInflater li; private final int ITEM_TYPES = 2, TYPE_0 = 0, TYPE_1 = 1; public CustomAdapter(Context context, LinkedList<Bean> beans) { // TODO Auto-generated constructor stub this.beans = beans; li = LayoutInflater.from(context); } @Override public int getCount() { // TODO Auto-generated method stub return beans.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return beans.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public int getViewTypeCount() { // TODO Auto-generated method stub return ITEM_TYPES; } @Override public int getItemViewType(int position) { // TODO Auto-generated method stub int tp = beans.get(position).getId(); if (TYPE_0 == tp) return TYPE_0; else if (TYPE_1 == tp) return TYPE_1; return TYPE_0; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub PeopleView s = null; Bean bean = beans.get(position); int type = getItemViewType(position); if (null == convertView) { s = new PeopleView(); switch (type) { case TYPE_0: convertView = li.inflate(R.layout.listview_item_teacher, null); break; case TYPE_1: convertView = li.inflate(R.layout.listview_item_student, null); break; } s.time = (TextView) convertView.findViewById(R.id.Time); s.message = (TextView) convertView.findViewById(R.id.Msg); s.portrait = (ImageView) convertView.findViewById(R.id.Img); convertView.setTag(s); } else s = (PeopleView) convertView.getTag(); s.time.setText(DateFomats.getCurrentTime(new Date().getTime())); s.message.setText(bean.gettMessage()); s.portrait.setImageResource(R.drawable.you); return convertView; } class PeopleView { TextView time; TextView message; ImageView portrait; } /** 添加發表私信內容,更新列表 */ public void addItemNotifiChange(Bean bean) { beans.add(bean); notifyDataSetChanged(); } }
我想大家從代碼中也已經看出端倪了;她的實現思路是使用ListView,在ListView中對其item布局展示做出變動。也就是說,這個Listview中item要用到兩種布局,然後通過用戶的 Id 進行判斷 ,不同 id 對應不同的聊天布局。然後按照時間的順序展示在界麵上(當然這個是後台提供的,你不需要進行什麼作為,這裏隻是自己添加排布的);為了實現的高效率,在創建item布局時候控件的兩類布局的id使用同一套。這是關鍵的一點,這樣的話在進行Layout布局初始化的時候可以使ListView得到優化。還要注意,要在適配器中重寫方法:
- getViewTypeCount()
getViewTypeCount()
和重寫方法:
- getItemViewType(int position)
getItemViewType(int position)
上麵第一個方法表返回值多少,對應的該ListView就會有有多少種的item布局類型,即在加載適配的時候每加載一次對話信息會走getView(int position ,View convertView ,ViewGroup parent);方法多少遍。如果按照原來的普通ListView適配器填充的話,現在的這個有兩種item布局展示,為展示其對話效果在每走兩次getView()方法 就相當於普通的ListView適配方法走一次,這樣才能展示出我們想要的不同布局item的展示效果。第二個方法通過參數position對用戶的id進行處理判斷,並返回我們自定義布局類型或者說用戶
id 所對應的類型數值值(這個是我們自己設置的),然後在getView()方法中通過方法獲取不同布局類型對應的我們所設置的數值來進行判斷此時我們應該展示那種itme布局,並來初始化該布局;
另外,ListView對應的item;如果想長按刪除要實現其監聽
- listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener()
listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener()
和監聽必須實現的方法;以及重寫回調的方法,對被點擊的item做出處理
- @Override
- blic boolean onContextItemSelected(MenuItem item)
@Override public boolean onContextItemSelected(MenuItem item)
順便提一下:
- menu.add(0, 0, 1, "刪除");
menu.add(0, 0, 1, "刪除");
第一個int類型的group ID參數,代表的是組概念,你可以將幾個菜單項歸為一組,以便更好的以組的方式管理你的菜單按鈕。 第二個int類型的item ID參數,代表的是項目編號。這個參數非常重要,一個item ID對應一個menu中的選項。在後麵使用菜單的時候,就靠這個item ID來判斷你使用的是哪個選項。 第三個int類型的order ID參數,代表的是菜單項的顯示順序。默認是0,表示菜單的顯示順序就是按照add的顯示順序來顯示。 第四個String類型的title參數,表示選項中顯示的文字。
最後更新:2017-04-03 05:40:14