博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android开源中国客户端学习 动弹发送模块 (表情, 话题等)<10>
阅读量:6478 次
发布时间:2019-06-23

本文共 7105 字,大约阅读时间需要 23 分钟。

hot3.png

衔接上文, 动弹的发送(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属性使用

 

然后是解决键盘弹出和表情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

你可能感兴趣的文章
Windows 10 /win10 上使用GIT慢的问题,或者命令行反应慢的问题
查看>>
Windows平台分布式架构实践 - 负载均衡
查看>>
iOS自定制tabbar与系统的tabbar冲突,造成第一次点击各个item图片更换选中,第二次选中部分item图片不改变...
查看>>
SVN服务器使用(二)
查看>>
反射获取内部类以及调用内部类方法
查看>>
App里面如何正确显示用户头像
查看>>
U-BOOT之一:BootLoader 的概念与功能
查看>>
我的路上
查看>>
Velocity处理多余空白和多余空白行问题
查看>>
DB2与oracle有什么区别
查看>>
创建一个多级文件目录
查看>>
Picasa生成图片幻灯片页面图文教程
查看>>
svn status 显示 ~xx
查看>>
常用HiveQL总结
查看>>
[转]使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(三)-- Logger
查看>>
POJ 3311 Hie with the Pie(状压DP + Floyd)
查看>>
Security updates and resources
查看>>
DNS为什么通常都会设置为14.114.114.114
查看>>
Sqoop架构(四)
查看>>
golang copy函数
查看>>