热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

黑马智能短信管理第2天

1.checkBox的显示和隐藏<span>***存储在编辑状态下,选中的listView的条目*

1.checkBox的显示和隐藏

/**
	 * 存储在编辑状态下,选中的listView的条目 
	 */
	private HashSet selectItemSet;

			/*
			 * 设置 checkBox
			 */
			//如果是编辑状态,显示checkBox,
			if(isEditState){
				vh.checkbox.setVisibility(View.VISIBLE);
				// 该条目对应的会话ID
				int threadId = cursor.getInt(INDEX_THREAD_ID);
				
				//判断集合当中,是否有该条目对应的会话ID,如果有,表示是选中状态,如果没有,是没选中状态。
				if(selectItemSet.contains(threadId)){
					vh.checkbox.setEnabled(true);
				}else{
					vh.checkbox.setEnabled(false);
				}
				
			}else{
				//否则,隐藏
				vh.checkbox.setVisibility(View.GONE);
			}
@Override
	/**
	 * 响应listview的条目点击事件
	 */
	public void onItemClick(AdapterView parent, View view, int position,
			long id) {
		
		//通过adapter 获得cursor
		Cursor cursor = adapter.getCursor();
		//将cursor移动到对应的位置
		cursor.moveToPosition(position);
		//取得该位置对应的会话ID
		int threadId = cursor.getInt(INDEX_THREAD_ID);
		
		if (isEditState) {
			// 判断 集合中是否有该会话ID,如果有,就删除,如果没有,就添加
			if (selectItemSet.contains(threadId)) {
				selectItemSet.remove(threadId);
			} else {
				selectItemSet.add(threadId);
			}
			//刷新listview
			adapter.notifyDataSetChanged();
			//刷新按钮状态
			flushState();
		}

2.点击删除按钮删除短信



/**
	 * 显示确认删除的对话框 
	 */
	private void showConfirmDeleteDialog() {
		AlertDialog.Builder adb = new AlertDialog.Builder(this);
		adb.setTitle("清除短信");
		adb.setMessage("确认删除这些回忆吗?");
		adb.setNegativeButton("确认", new DialogInterface.OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// 1.开子线程,删除短信,
				new Thread(new DeleteMsgRunnable()).start();
				
				// 2.显示删除短信的进度对话框
				showDeleteProgressDialog();
			}
		});
		
		adb.setPositiveButton("取消", null);
		adb.show();
		
	}


删除短信在子线程中执行

class DeleteMsgRunnable implements Runnable{

		@Override
		public void run() {
			// 遍历 selectItemSet 集合,根据会话ID,删除短信 
			
			for(Integer threadId : selectItemSet ){ // 用增强for循环 遍历 set集合 
				
				SystemClock.sleep(1000); // 会为显示效果正好,在此休眠一秒,
				
				if(isCancelDeleteMsg){
					break; // 跳出 for 循环 取消删除
				}
				
				Tools.deleteMsgByThreadId(ctx,threadId);
				
				proDlg.incrementProgressBy(1);//让  proDlg 的水平进度条,增加刻度 
			}
			// 清空集合
			selectItemSet.clear();// 清空集合
			//关闭进度框
			proDlg.dismiss();
			// 将 isCancelDeleteMsg 复原
			isCancelDeleteMsg = false;
//			flushState();// 在子线程中不能更新UI
		}





private ProgressDialog proDlg;
	/**
	 * 显示删除短信的进度对话框
	 */
	protected void showDeleteProgressDialog() {
		proDlg =new ProgressDialog(this);
		proDlg.setTitle("正在删除短信");
		//设置 进度框 为水平显示的样式,
		proDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		// 设置进度条的最大值 = 集合的大小。
		proDlg.setMax(selectItemSet.size());
		
		//当点击取消删除时,设置isCancelDeleteMsg
		proDlg.setButton("取消", new DialogInterface.OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				isCancelDeleteMsg = true;
			}
		});
		// 给进度框添加,关闭时的回调 ,监听,监听的代码,会在UI线程中执行
		proDlg.setOnDismissListener(new DialogInterface.OnDismissListener() {
			
			@Override
			public void onDismiss(DialogInterface dialog) {
				
				isEditState = false; 
				
				flushState();// 刷新页面状态
				System.out.println(selectItemSet);
				adapter.notifyDataSetChanged();// 刷新listview
				System.out.println("222::"+selectItemSet);
			}
		});
		
		proDlg.show();
		
	}


3.进入会话详情页面  

	
			String address = cursor.getString(INDEX_ADDRESS);
			
			Intent intent = new Intent(this,ConversationDetail.class);
			
			intent.putExtra("address", address);// 将当前条目对应的联系人电话号码,传递给会话详情页面
			
			startActivity(intent);

4.会话详情页面 根据电话号码设置 页面数据和布局



public class ConversationDetail extends Activity implements OnClickListener{

	/**
	 *联系人的电话号码 
	 */
	private String address;
	private Context ctx;
	
	private ListView listView;
	
	private EditText inputMsg;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		ctx = this;
		
		address = getIntent().getStringExtra("address");
		if(address == null){
			throw new RuntimeException("联系人是空,我不知道显示哪个会话记录");
		}
		
		setContentView(R.layout.activity_conversation_detail);
		
		init();
		
		listView = (ListView) findViewById(R.id.lv_conversation_detail);
		adapter = new MyListAdapter(this, null);
		listView.setAdapter(adapter);
		//设置listView条目之间的分隔线为null ,即,不要分隔线
		listView.setDivider(null);
		
		prepareData();
	}

	private void prepareData() {
		
		MyQueryHandler myQueryHandler = new MyQueryHandler(getContentResolver());
		myQueryHandler.setOnCursorChangedListener(new MyQueryHandler.IOnCursorChangedListener() {
			
			@Override
			/**
			 *  当adapter 获得 cursor 的时候,回调此方法 
			 */
			public void onCursorChanged(int token, Object COOKIE, Cursor cursor) {
				// 让listview 显示最后一行
				listView.setSelection(adapter.getCount()-1);
			}
		});
		myQueryHandler.startQuery(99, adapter, MyConstants.URI_SMS, projection, " address="+address, null, " date ");
	}

	/**
	 * 显示会话详情,所需要的列
	 */
	private String[] projection={
			"_id","body","date","type"
	};
	
	/**
	 * 短信内容所在列的索引值  为 1
	 */
	private final int INDEX_BODY = 1;
	private final int INDEX_DATE = 2;
	private final int INDEX_TYPE = 3;
	
	private void init() {
		TextView title = (TextView) findViewById(R.id.tv_title_conversation_detail);
		
		String name = Tools.findNameByNumber(ctx, address);
		if(name !=null){ // 有此联系人
			title.setText(name);
		}else{ // 无此联系人
			title.setText(address);
		}
		
		findViewById(R.id.btn_back).setOnClickListener(this);
		findViewById(R.id.btn_ok).setOnClickListener(this);
		
		inputMsg = (EditText) findViewById(R.id.et_input_msg_conversation_detail);
	}

	@Override
	/**
	 * 响应按钮的点击事件
	 */
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_back: // 后退按钮
			
			finish();
			
			break;
		case R.id.btn_ok: // 确定按钮
			
			//先判断输入的是否有内容,
			//如果有内容的话,就将内容以短信的形式发送出去,
			String msg = inputMsg.getText().toString();
			if(TextUtils.isEmpty(msg.trim())){
				Toast.makeText(ctx, "请输入短信内容", 0).show();
				return ;
			}
			// 发送短信
			Tools.sendMessage(ctx,msg,address);
			//清空输入框
			inputMsg.setText("");
			// 隐藏输入法键盘
			InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
			// 隐藏输入法的 API 
			imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
			
			break;

		}
	}
	
	private MyListAdapter adapter;
	
	private class MyListAdapter extends CursorAdapter{

		public MyListAdapter(Context context, Cursor c) {
			super(context, c);
		}

		
		@Override
		/**
		 * 当内容发生改变的时候,回调此方法
		 */
		protected void onContentChanged() {
			// super 里面,做了重新查询的动作
			super.onContentChanged();
			// 让listView 显示最后一行
			listView.setSelection(getCount()-1);
			
		}
		
		@Override
		public View newView(Context context, Cursor cursor, ViewGroup parent) {
			View view =View.inflate(ctx, R.layout.list_item_conversation_detail, null);
			
			ViewHolder vh = new ViewHolder();
			vh.tlReceive = (TableLayout) view.findViewById(R.id.tl_receive);
			vh.msgReceive = (TextView) view.findViewById(R.id.tv_msg_receive);
			vh.dateReceive = (TextView) view.findViewById(R.id.tv_date_receive);
			
			vh.tlSend = (TableLayout) view.findViewById(R.id.tl_send);
			vh.msgSend = (TextView) view.findViewById(R.id.tv_msg_send);
			vh.dateSend = (TextView) view.findViewById(R.id.tv_date_send);
			view.setTag(vh);
			
			return view;
		}

		@Override
		public void bindView(View view, Context context, Cursor cursor) {
			ViewHolder vh = (ViewHolder) view.getTag();
			// 给listView条目设置内容
			
			int type = cursor.getInt(INDEX_TYPE);// 获得短信类型
			Log.d("tencent", type+"");
			
			String text = cursor.getString(INDEX_BODY);//获得短信内容
			
			long when = cursor.getLong(INDEX_DATE);// 获得日期
			String dateStr = DateFormat.getDateFormat(ctx).format(when);
			
			
			if(type == MyConstants.TYPE_RECEIVE){ // 接收到的短信
				vh.tlReceive.setVisibility(View.VISIBLE);
				vh.tlSend.setVisibility(View.GONE);
				//设置短信内容
				vh.msgReceive.setText(text);
				//设置日期
				vh.dateReceive.setText(dateStr);
				
			}else{
				vh.tlReceive.setVisibility(View.GONE);
				vh.tlSend.setVisibility(View.VISIBLE);
				
				//设置短信内容
				vh.msgSend.setText(text);
				
				vh.dateSend.setText(dateStr);
			}
		}
	}
	
	private class ViewHolder {
		
		public TableLayout tlReceive;
		public TextView msgReceive;
		public TextView dateReceive;
		
		public TableLayout tlSend;
		public TextView msgSend;
		public TextView dateSend;
		
	}
	
}

5.发送消息 ,AutoCompleteTextView匹配数据 及选择系统联系人


public class NewMessageUI extends Activity implements OnClickListener {

	private AutoCompleteTextView actv;
	private ImageView selectContact;

	private EditText inputMsg;
	private ACTVadapter adapter;

	private String[] projection = { "_id", "data1", "display_name" };
	private final int INDEX_NUMBER = 1;//电话号码
	private final int INDEX_NAME = 2;//名字
	

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_new_message);

		actv = (AutoCompleteTextView) findViewById(R.id.actv);
		selectCOntact= (ImageView) findViewById(R.id.iv_select_contact);
		inputMsg = (EditText) findViewById(R.id.et_input_msg);

		selectContact.setOnClickListener(this);// 选择联系人
		findViewById(R.id.btn_send_msg).setOnClickListener(this);// 发送消息

		adapter = new ACTVadapter(this, null);
		actv.setAdapter(adapter);

		// 这个方法是cursoradapter中的---当actv 中的内容发生改变时,回调此方法
		adapter.setFilterQueryProvider(new FilterQueryProvider() {
			@Override
			public Cursor runQuery(CharSequence constraint) {
				// constraint 默认是当输入2个及以上的文字则返回,否则返回null
				// android:completiOnThreshold="1"xml中配置则会变为1
				// System.out.println(constraint);
				Cursor cursor = getContentResolver().query(MyConstants.CONTENT_URI,
						projection, "data1 like '%" + constraint + "%'", null,
						null);
				// Tools.printCursor(cursor);
				return cursor;
			}
		});
	}

	class ACTVadapter extends CursorAdapter {

		private TextView name;
		private TextView number;

		public ACTVadapter(Context context, Cursor c) {
			super(context, c);
		}

		@Override
		public View newView(Context context, Cursor cursor, ViewGroup parent) {
			View view = View.inflate(context, R.layout.list_item_actv, null);

			return view;
		}

		@Override
		public void bindView(View view, Context context, Cursor cursor) {
			name = (TextView) view.findViewById(R.id.tv_name_actv);
			number = (TextView) view.findViewById(R.id.tv_number_actv);
			name.setText(cursor.getString(INDEX_NUMBER));
			number.setText(cursor.getString(INDEX_NAME));
		}
		//该方法将返回的数据转换成电话号码返回给autoCompleteTextView
		@Override
		public CharSequence convertToString(Cursor cursor) {
			String number = cursor.getString(INDEX_NUMBER);
			return number;
		}

	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_send_msg:// 发送短信的按钮
			String address = actv.getText().toString();
			if (TextUtils.isEmpty(address.trim())) {
				Toast.makeText(this, "请输入收件人号码", Toast.LENGTH_SHORT).show();
				return;
			}
			String msg = inputMsg.getText().toString();
			if (TextUtils.isEmpty(msg.trim())) {
				Toast.makeText(this, "请输入短信内容", Toast.LENGTH_SHORT).show();
				return;
			}

			// 开始发送短信
			Tools.sendMessage(this, msg, address.trim());
			// 清空输入框
			inputMsg.setText("");

			break;
		case R.id.iv_select_contact:// 点击选择联系人的图片

			Intent intent = new Intent();
			intent.setAction("android.intent.action.PICK");
			intent.setData(Uri.parse("content://com.android.contacts/contacts"));
			startActivityForResult(intent, 99);

			break;
		default:
			break;
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// System.out.println("stringExtra::"+stringExtra);//null
		if (requestCode == 99) {
			String stringExtra = data.getStringExtra("phone");
			System.out.println("stringExtra::" + stringExtra);

			Uri uri = data.getData();
			//1.根据系统的uri查询_id的列(系统uri没有电话号码)
			Cursor cursor = getContentResolver().query(uri,
					new String[] { "_id" }, null, null, null);
			// Tools.printCursor(cursor);
			while(cursor.moveToNext()){
				// 返回的cursor默认指向-1行 ,
				int cOntactId= cursor.getInt(0); // 仅查询一列,所以列的索引值 输入 0
				//2.通过_id去查询Phone.Content.uri中的电话号码
				Cursor cursor2 = getContentResolver().query(Phone.CONTENT_URI,
						new String[] { "data1" }, " contact_id = " + contactId,
						null, null);
				while(cursor2.moveToNext()){
					// 返回的cursor默认指向-1行 ,
					String number = cursor2.getString(0);
					actv.setText(number + "");
				}
			}
			
		}
	}
}







推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Java图形化计算器设计与实现
    本文介绍了使用Java编程语言设计和实现图形化计算器的方法。通过使用swing包和awt包中的组件,作者创建了一个具有按钮监听器和自定义界面尺寸和布局的计算器。文章还分享了在图形化界面设计中的一些心得体会。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • 本文介绍了在Android开发中使用软引用和弱引用的应用。如果一个对象只具有软引用,那么只有在内存不够的情况下才会被回收,可以用来实现内存敏感的高速缓存;而如果一个对象只具有弱引用,不管内存是否足够,都会被垃圾回收器回收。软引用和弱引用还可以与引用队列联合使用,当被引用的对象被回收时,会将引用加入到关联的引用队列中。软引用和弱引用的根本区别在于生命周期的长短,弱引用的对象可能随时被回收,而软引用的对象只有在内存不够时才会被回收。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • C#多线程解决界面卡死问题的完美解决方案
    当界面需要在程序运行中不断更新数据时,使用多线程可以解决界面卡死的问题。一个主线程创建界面,使用一个子线程执行程序并更新主界面,可以避免卡死现象。本文分享了一个例子,供大家参考。 ... [详细]
  • 使用freemaker生成Java代码的步骤及示例代码
    本文介绍了使用freemaker这个jar包生成Java代码的步骤,通过提前编辑好的模板,可以避免写重复代码。首先需要在springboot的pom.xml文件中加入freemaker的依赖包。然后编写模板,定义要生成的Java类的属性和方法。最后编写生成代码的类,通过加载模板文件和数据模型,生成Java代码文件。本文提供了示例代码,并展示了文件目录结构。 ... [详细]
author-avatar
西瓜246
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有