閱讀249 返回首頁    go 阿裏雲 go 技術社區[雲棲]


仿微信、QQ聊天界麵私信對話效果

https://blog.csdn.net/junhuahouse/article/details/39076821

我們大家可能都看到過在自己使用社交Android軟件的時候,會發現聊天頁麵的效果;有人說是氣泡效果,也很像,是吧?那我們該怎麼去實現那種效果呢??

點擊這裏進入她的姊妹篇

點擊這裏下載源碼

這個就是效果:有人物頭像、聊天的當時時間、聊天內容、發送信息等;其實呢,她的思路很簡單,我也弄了幾個小時!恩,那我們就簡單詳細的聊聊吧!先看源代碼:項目入口MainActivity.java:

  1. public class MainActivity extends Activity {  
  2.   
  3.     private LinkedList<PeopleStudentBean> sList = null;  
  4.     private LinkedList<PeopleTeacherBean> tList = null;  
  5.     private LinkedList<Bean> beans = null;  
  6.   
  7.   
  8.     /** 聊天message 格式 */  
  9.     private ListView listView;  
  10.     /** 信息編輯框 */  
  11.     private EditText edt;  
  12.     /** 信息發送按鈕 */  
  13.     private Button btnEnter;  
  14.   
  15.     private CustomAdapter adapter;  
  16.   
  17.     @Override  
  18.     protected void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         sList = new LinkedList<PeopleStudentBean>();  
  21.         tList = new LinkedList<PeopleTeacherBean>();  
  22.         beans = new LinkedList<Bean>();  
  23.         String[] msg = new String[] { "你好!""你也在金象工作嗎?""我在天安門掃大街呢,這裏可舒服了!",  
  24.                 "原來你也細化這個工作啊,我這裏還招人呢,你來不?來的話,我一句話的事兒!""嗬嗬,你好!""是的,你在哪裏呢?",  
  25.                 "吼吼,這麼便宜的事兒?!,我怎麼沒有遇到呢。""恩,好啊 好啊。那等著我。。。" };  
  26.   
  27.         // 0 是教師; 1 是學生   
  28.         for (int i = 0; i < 4; i++) {  
  29.             sList.add(new PeopleStudentBean(msg[i], R.drawable.you,""1));  
  30.             tList.add(new PeopleTeacherBean(msg[i + 4], R.drawable.me,""0));  
  31.         }  
  32.   
  33.         // 歸放到 同一個 類集合Bean中   
  34.         for (int j = 0; j < sList.size(); j++) {  
  35.   
  36.             beans.add(sList.get(j));  
  37.             beans.add(tList.get(j));  
  38.         }  
  39.   
  40.         setContentView(R.layout.activity_main);  
  41.         initViewsMethod();  
  42.         onHandleMethod();  
  43.     }  
  44.       
  45.     /** 處理listView 的 item方法  */  
  46.     private void initViewsMethod(){  
  47.         listView = (ListView) findViewById(R.id.lvMessages);  
  48.         edt = (EditText) findViewById(R.id.edt);  
  49.         btnEnter = (Button) findViewById(R.id.enter);  
  50.   
  51.         listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {  
  52.               
  53.             @Override  
  54.             public void onCreateContextMenu(ContextMenu menu, View v,  
  55.                     ContextMenuInfo menuInfo) {  
  56.                 // TODO Auto-generated method stub   
  57.                   
  58.                 menu.setHeaderTitle("提示:");  
  59.                 menu.setHeaderIcon(android.R.drawable.stat_notify_error);  
  60.                 menu.add(001"刪除");  
  61.                 menu.add(110"取消");  
  62.                   
  63.             }  
  64.         });  
  65.           
  66.     }  
  67.       
  68.       
  69.     /** 處理發送信息的方法  */  
  70.     public void onHandleMethod(){  
  71.         adapter = new CustomAdapter(this, beans);  
  72.         listView.setAdapter(adapter);  
  73.         btnEnter.setOnClickListener(new OnClickListener() {  
  74.               
  75.             @Override  
  76.             public void onClick(View v) {  
  77.                 // TODO Auto-generated method stub   
  78.                 String txt = edt.getText().toString();  
  79.                 if(null == txt)  
  80.                     Toast.makeText(getApplicationContext(), "發送內容不能為空 !", Toast.LENGTH_SHORT).show();  
  81.                 adapter.addItemNotifiChange(new Bean(txt, R.drawable.me, new Date()+""0));  
  82.                 edt.setText("");  
  83.                 listView.setSelection(beans.size()-1);  
  84.             }  
  85.         });  
  86.     }  
  87.   
  88.     @Override  
  89.     public boolean onContextItemSelected(MenuItem item) {  
  90.         // TODO Auto-generated method stub   
  91.         switch (item.getItemId()) {  
  92.         case 0:  
  93.             Toast.makeText(getApplicationContext(), "刪除成功", Toast.LENGTH_SHORT).show();  
  94.             AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();  
  95.             Bean bean = (Bean) adapter.getItem(info.position);  
  96.             beans.remove(bean);  
  97.             adapter.notifyDataSetChanged();  
  98.             break;  
  99.         }  
  100.         return super.onContextItemSelected(item);  
  101.   
  102.     }  
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:

  1. public class CustomAdapter extends BaseAdapter {  
  2.   
  3.     private LinkedList<Bean> beans = null;  
  4.     private LayoutInflater li;  
  5.     private final int ITEM_TYPES = 2, TYPE_0 = 0, TYPE_1 = 1;  
  6.   
  7.     public CustomAdapter(Context context, LinkedList<Bean> beans) {  
  8.         // TODO Auto-generated constructor stub   
  9.         this.beans = beans;  
  10.         li = LayoutInflater.from(context);  
  11.   
  12.     }  
  13.   
  14.     @Override  
  15.     public int getCount() {  
  16.         // TODO Auto-generated method stub   
  17.         return beans.size();  
  18.     }  
  19.   
  20.     @Override  
  21.     public Object getItem(int position) {  
  22.         // TODO Auto-generated method stub   
  23.         return beans.get(position);  
  24.     }  
  25.   
  26.     @Override  
  27.     public long getItemId(int position) {  
  28.         // TODO Auto-generated method stub   
  29.         return position;  
  30.     }  
  31.   
  32.     @Override  
  33.     public int getViewTypeCount() {  
  34.         // TODO Auto-generated method stub   
  35.         return ITEM_TYPES;  
  36.     }  
  37.   
  38.     @Override  
  39.     public int getItemViewType(int position) {  
  40.         // TODO Auto-generated method stub   
  41.         int tp = beans.get(position).getId();  
  42.         if (TYPE_0 == tp)  
  43.             return TYPE_0;  
  44.         else if (TYPE_1 == tp)  
  45.             return TYPE_1;  
  46.         return TYPE_0;  
  47.     }  
  48.   
  49.     @Override  
  50.     public View getView(int position, View convertView, ViewGroup parent) {  
  51.         // TODO Auto-generated method stub   
  52.   
  53.         PeopleView s = null;  
  54.         Bean bean = beans.get(position);  
  55.         int type = getItemViewType(position);  
  56.   
  57.         if (null == convertView) {  
  58.             s = new PeopleView();  
  59.   
  60.             switch (type) {  
  61.             case TYPE_0:  
  62.                 convertView = li.inflate(R.layout.listview_item_teacher, null);  
  63.                 break;  
  64.             case TYPE_1:  
  65.                 convertView = li.inflate(R.layout.listview_item_student, null);  
  66.                 break;  
  67.             }  
  68.   
  69.             s.time = (TextView) convertView.findViewById(R.id.Time);  
  70.             s.message = (TextView) convertView.findViewById(R.id.Msg);  
  71.             s.portrait = (ImageView) convertView.findViewById(R.id.Img);  
  72.             convertView.setTag(s);  
  73.         } else  
  74.             s = (PeopleView) convertView.getTag();  
  75.         s.time.setText(DateFomats.getCurrentTime(new Date().getTime()));  
  76.         s.message.setText(bean.gettMessage());  
  77.         s.portrait.setImageResource(R.drawable.you);  
  78.   
  79.         return convertView;  
  80.   
  81.     }  
  82.   
  83.     class PeopleView {  
  84.         TextView time;  
  85.         TextView message;  
  86.         ImageView portrait;  
  87.     }  
  88.   
  89.     /** 添加發表私信內容,更新列表 */  
  90.     public void addItemNotifiChange(Bean bean) {  
  91.         beans.add(bean);  
  92.         notifyDataSetChanged();  
  93.   
  94.     }  
  95.   
  96. }  
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得到優化。還要注意,要在適配器中重寫方法:

  1. getViewTypeCount()  
getViewTypeCount()

和重寫方法:

  1. 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;如果想長按刪除要實現其監聽

  1. listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener()   
listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() 

和監聽必須實現的方法;以及重寫回調的方法,對被點擊的item做出處理

  1. @Override  
  2. blic boolean onContextItemSelected(MenuItem item)  
  @Override
public boolean onContextItemSelected(MenuItem item)

順便提一下:

  1. menu.add(001"刪除");  
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

  上一篇:go eclipse javaee版本配置tomcat並向tomcat發布工程
  下一篇:go 使用wordpress搭建博客過程中遇到的一些問題