Android开源中国客户端学习 动弹发送模块 (表情, 话题等)<10>

衔接上文, 动弹的发送(TweetPub.java)其实还有许多功能值得我们学习,动弹界面其实也是一个发微博界面,功能点如下:

1.表情的实现

2.键盘的消隐机制

3.选择图片并处理上传的两张方式 包括拍照和从相册


那么现在就来分析一下具体的实现:

1.表情的实现

这里表情的实现其实很简单,就是一个GridView,那么怎么在edittext中显示表情呢?其实有些基础的大家也应该知道,使用的是SpinnableString和 ImageSpan 代码如下:


//初始化表情控件
    private void initGridView() {
    	mGVFaceAdapter = new GridViewFaceAdapter(this);
    	mGridView = (GridView)findViewById(R.id.tweet_pub_faces);
    	mGridView.setAdapter(mGVFaceAdapter);
    	mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				//插入的表情
				SpannableString ss = new SpannableString(view.getTag().toString());
				Drawable d = getResources().getDrawable((int)mGVFaceAdapter.getItemId(position));
				d.setBounds(0, 0, 35, 35);//设置表情图片的显示大小
				ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BOTTOM);
				ss.setSpan(span, 0, view.getTag().toString().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);				 
				//在光标所在处插入表情
				mContent.getText().insert(mContent.getSelectionStart(), ss);				
			}    		
    	});
    }
表情数据的装载全部在GridViewFaceAdapter里面进行,请自行查看源码,至于表情的显示隐藏,只不过是gridview的显示隐藏而已.



2.键盘的消隐机制.

在做编辑界面的时候,键盘的消隐关于很 影响用户的体验,但是如果添加了一下底部的富编辑按钮, 按照android原有的逻辑,会发现很多时候不想让键盘弹出时候键盘弹出了,比如在表情打开的时候键盘弹出,这样用户体验机会非常差,又比如,键盘弹出的时候吧底部工具类遮住,用户就不能再键盘打开的时候点击选择表情了.这样的体验也是非常差. 故此我们应该出来键盘表情的消隐机制,提高用户的体验.

那么我们就一步一步来看:

首先是键盘 出现后 其他UI空间跟随调整,也就是键盘也可以把底部工具类推上去.其实实现比较简单

在android中添加属性

   android:windowSoftInputMode="stateVisible|adjustResize"

第一个属性是进入这个activity就获得焦点 弹出键盘

第二个属性就是键盘弹出 UI空间随之调整了

这里不详细介绍 请参考

 android:windowSoftInputMode属性使用

 http://www.blogjava.net/zhip/archive/2011/02/14/344258.html


然后是解决键盘弹出和表情panel弹出的冲突:

用户点击编辑器,弹出键盘

//编辑器点击事件
    	mContent.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				//显示软键盘
				showIMM();
			}
		});
shoIMM函数在这里
private void showIMM() {
    	mFace.setTag(1);
    	showOrHideIMM();
    }
第一句话是个表情的panel添加一个tag (tag是一个object类型 ,可以理解为个view的附加信息)

现在需要显示的是输入法,mFace.getTag!=null于是会显示输入法隐藏表情panel

private void showOrHideIMM() {
    	if(mFace.getTag() == null){
			//隐藏软键盘
			imm.hideSoftInputFromWindow(mContent.getWindowToken(), 0);
			//显示表情
			showFace();				
		}else{
			//显示软键盘
			imm.showSoftInput(mContent, 0);
			//隐藏表情
			hideFace();
		}
    }
imm在activity启动的时候定义的
//软键盘管理类
		imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);

在showFace和hideFace的时候,处理设置panel的可见与否还会设置是face的tag 以标示face的可见状态

private void showFace() {
		mFace.setImageResource(R.drawable.widget_bar_keyboard);
		mFace.setTag(1);
		mGridView.setVisibility(View.VISIBLE);
    }
    private void hideFace() {
    	mFace.setImageResource(R.drawable.widget_bar_face);
		mFace.setTag(null);
		mGridView.setVisibility(View.GONE);
    }


用户点击表情图标也会触发showOrHideIMM函数,

这时候如果在显示表情就显示输入法,如果在显示输入法就显示表情

流程图如下

3.选择图片并处理上传的两张方式 包括拍照和从相册

选择图片分为两种,相机和相册 在函数 imageChooseItem中:

相册选图的实现:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
						intent.addCategory(Intent.CATEGORY_OPENABLE); 
						intent.setType("image/*"); 
						startActivityForResult(Intent.createChooser(intent, "选择图片"),ImageUtils.REQUEST_CODE_GETIMAGE_BYSDCARD);


相机拍照的实现:

首先是启动相机 作者对一些异常都做了判断:\

//拍照
					else if( item == 1 )
					{	
						String savePath = "";
						//判断是否挂载了SD卡
						String storageState = Environment.getExternalStorageState();		
						if(storageState.equals(Environment.MEDIA_MOUNTED)){
							savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSChina/Camera/";//存放照片的文件夹
							File savedir = new File(savePath);
							if (!savedir.exists()) {
								savedir.mkdirs();
							}
						}
						
						//没有挂载SD卡,无法保存文件
						if(StringUtils.isEmpty(savePath)){
							UIHelper.ToastMessage(TweetPub.this, "无法保存照片,请检查SD卡是否挂载");
							return;
						}

						String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
						String fileName = "osc_" + timeStamp + ".jpg";//照片命名
						File out = new File(savePath, fileName);
						Uri uri = Uri.fromFile(out);
						
						theLarge = savePath + fileName;//该照片的绝对路径
						
						Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
						intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
						startActivityForResult(intent, ImageUtils.REQUEST_CODE_GETIMAGE_BYCAMERA);
					}


在一个新的线程 对得到的图片 如果是从相册得到的 会检查一下可以从相册数据库中拿到缩略图吗,如果拿不到就是用imageUtil 裁剪为缩略图:

if(requestCode == ImageUtils.REQUEST_CODE_GETIMAGE_BYSDCARD) 
		        {         	
		        	if(data == null)  return;
		        	
		        	Uri thisUri = data.getData();
		        	String thePath = ImageUtils.getAbsolutePathFromNoStandardUri(thisUri);
		        	
		        	//如果是标准Uri
		        	if(StringUtils.isEmpty(thePath))
		        	{
		        		theLarge = ImageUtils.getAbsoluteImagePath(TweetPub.this,thisUri);
		        	}
		        	else
		        	{
		        		theLarge = thePath;
		        	}
		        	
		        	String attFormat = FileUtils.getFileFormat(theLarge);
		        	if(!"photo".equals(MediaUtils.getContentType(attFormat)))
		        	{
		        		Toast.makeText(TweetPub.this, getString(R.string.choose_image), Toast.LENGTH_SHORT).show();
		        		return;
		        	}
		        	
		        	//获取图片缩略图 只有Android2.1以上版本支持
		    		if(AppContext.isMethodsCompat(android.os.Build.VERSION_CODES.ECLAIR_MR1)){
		    			String imgName = FileUtils.getFileName(theLarge);
		    			bitmap = ImageUtils.loadImgThumbnail(TweetPub.this, imgName, MediaStore.Images.Thumbnails.MICRO_KIND);
		    		}
		        	
		        	if(bitmap == null && !StringUtils.isEmpty(theLarge))
		        	{
		        		bitmap = ImageUtils.loadImgThumbnail(theLarge, 100, 100);
		        	}
		        }

如果是来自相机的图片,就直接生成缩略图


//拍摄图片
		        else if(requestCode == ImageUtils.REQUEST_CODE_GETIMAGE_BYCAMERA)
		        {	
		        	if(bitmap == null && !StringUtils.isEmpty(theLarge))
		        	{
		        		bitmap = ImageUtils.loadImgThumbnail(theLarge, 100, 100);
		        	}
		        }


最后就把拿到的图片压缩成800 宽度的进行 等完成了就通知UI把拿到的图片显示到编辑界面上:用户就可以发送了~

if(bitmap!=null)
				{
					//存放照片的文件夹
					String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/OSChina/Camera/";
					File savedir = new File(savePath);
					if (!savedir.exists()) {
						savedir.mkdirs();
					}
					
					String largeFileName = FileUtils.getFileName(theLarge);
					String largeFilePath = savePath + largeFileName;
					//判断是否已存在缩略图
					if(largeFileName.startsWith("thumb_") && new File(largeFilePath).exists()) 
					{
						theThumbnail = largeFilePath;
						imgFile = new File(theThumbnail);
					} 
					else 
					{
						//生成上传的800宽度图片
						String thumbFileName = "thumb_" + largeFileName;
						theThumbnail = savePath + thumbFileName;
						if(new File(theThumbnail).exists())
						{
							imgFile = new File(theThumbnail);
						}
						else
						{
							try {
								//压缩上传的图片
								ImageUtils.createImageThumbnail(TweetPub.this, theLarge, theThumbnail, 800, 80);
								imgFile = new File(theThumbnail);
							} catch (IOException e) {
								e.printStackTrace();
							}	
						}						
					}					
					//保存动弹临时图片
					((AppContext)getApplication()).setProperty(tempTweetImageKey, theThumbnail);
					
					Message msg = new Message();
					msg.what = 1;
					msg.obj = bitmap;
					handler.sendMessage(msg);
				}				
			};

转载于:https://my.oschina.net/sfshine/blog/147701

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值