导航菜单
首页 >  考试后发的qq说说怎么写  > 安卓仿QQ空间实现(含图片的动态编辑、发表、点赞、评论)

安卓仿QQ空间实现(含图片的动态编辑、发表、点赞、评论)

目录之前做项目的时候需要用到仿空间动态的功能,在此做一下记录,简单介绍一下listview自定义适配器以及各相关功能实现方法。一、效果图二、功能需求三、 功能实现(主要代码)四、最后2023更新

之前做项目的时候需要用到仿空间动态的功能,在此做一下记录,简单介绍一下listview自定义适配器以及各相关功能实现方法。 一、效果图

在这里插入图片描述 这里添加了两条初始动态,其他都是现编现发的。头像这里后面使用了圆形图片控件。 在这里插入图片描述 动态评论以及点赞功能实现⬆

在这里插入图片描述 动态编辑与发表功能⬆(这个照片是我摸黑拍的,显示并没有问题,并且因为时间比较长降低了gif的图片质量)

二、功能需求

1、仿空间动态界面

2、评论与点赞。

3、发表动态(图片+文字)。

三、 功能实现(主要代码)

1、首先定义一个实体类Dynamic,作为ListView的适配类型。

public class Dynamic {private int iv_head,imagev1;private String tv_name;private String tv_time;private String tv_content;private String ll_comment;private String ivfilepath1;private String ivfilepath2;private String ivfilepath3;public String getTv_dolike() {return tv_dolike;}public void setTv_dolike(String tv_dolike) {this.tv_dolike = tv_dolike;}private String tv_dolike;public void setTv_time(String tv_time) {this.tv_time = tv_time;}public int getImagev1() {return imagev1;}public Dynamic(int iv_head, String tv_name, String tv_content, String ivfilepath1, String ivfilepath2, String ivfilepath3, String tv_time, int imagev1) {this.iv_head = iv_head;this.ivfilepath1=ivfilepath1;this.ivfilepath2=ivfilepath2;this.ivfilepath3=ivfilepath3;this.imagev1=imagev1;this.tv_name = tv_name;this.tv_time = tv_time;this.tv_content = tv_content;}public int getIv_head() {return iv_head;}public String getIvfilepath1() {return ivfilepath1;}public String getIvfilepath2() {return ivfilepath2;}public String getIvfilepath3() {return ivfilepath3;}public String getTv_name() {return tv_name;}public String getTv_time() {return tv_time;}public String getTv_content() {return tv_content;}public String getLl_comment() {return ll_comment;}}

2、自定义适配器DynamicAdapter,我这里使用的适配器继承自ArrayAdapter,适配器作为后端数据与前端界面交互的桥梁是十分重要的,也是实现定制ListView的关键。

//设置点赞事件,点赞图标变化viewHolder.iv_like.setOnClickListener (new OnClickListener () {@Overridepublic void onClick(View view) {if (!islike) {viewHolder.tv_dolike.setText (username+"觉得很赞");viewHolder.iv_like.setImageResource (R.mipmap.like);Toast.makeText (getContext (), "点赞成功", Toast.LENGTH_SHORT).show ();islike = true;} else {viewHolder.tv_dolike.setText ("");viewHolder.iv_like.setImageResource (R.mipmap.nolike);Toast.makeText (getContext (), "取消点赞", Toast.LENGTH_SHORT).show ();islike = false;}}});//给每一条动态设置内容viewHolder.iv_head.setImageResource (dynamic.getIv_head ());viewHolder.tv_name.setText (dynamic.getTv_name ());viewHolder.tv_content.setText (dynamic.getTv_content ());viewHolder.tv_time.setText (dynamic.getTv_time ());Bitmap bitmap1 = BitmapFactory.decodeFile (dynamic.getIvfilepath1 ());viewHolder.iv_content1.setImageBitmap (bitmap1);Bitmap bitmap2 = BitmapFactory.decodeFile (dynamic.getIvfilepath2 ());viewHolder.iv_content2.setImageBitmap (bitmap2);Bitmap bitmap3 = BitmapFactory.decodeFile (dynamic.getIvfilepath3 ());viewHolder.iv_content3.setImageBitmap (bitmap3);if(dynamic.getImagev1 ()!=0){viewHolder.iv_content1.setImageResource (dynamic.getImagev1 ());}//点击评论图标获取edittext焦点viewHolder.Iv_comment.setOnClickListener (new OnClickListener () {@Overridepublic void onClick(View view) {Log.e ("onClick: ", "获取焦点");if (viewHolder.et_comment.isFocused ()) {} else {viewHolder.et_comment.requestFocus ();viewHolder.et_comment.setFocusableInTouchMode (true);InputMethodManager inputManager =(InputMethodManager) viewHolder.et_comment.getContext ().getSystemService (Context.INPUT_METHOD_SERVICE);inputManager.showSoftInput (viewHolder.et_comment, 0);}}});//评论监听viewHolder.et_comment.setOnTouchListener (new View.OnTouchListener () {@Overridepublic boolean onTouch(View view, MotionEvent motionEvent) {Log.e ("onTouch: ", "发表");Drawable drawable = viewHolder.et_comment.getCompoundDrawables ()[2];//排除非按压图标事件if (motionEvent.getAction () != MotionEvent.ACTION_UP) {return false;}if (motionEvent.getX () > viewHolder.et_comment.getWidth () - drawable.getIntrinsicWidth () - viewHolder.et_comment.getPaddingRight ()) {//取出评论String commentStr = viewHolder.et_comment.getText ().toString ().trim ();if (TextUtils.isEmpty (commentStr)) {Toast.makeText (getContext (), "评论内容不能为空", Toast.LENGTH_SHORT).show ();} else {addView (commentStr, viewHolder.ll_comment);viewHolder.et_comment.setText ("");Toast.makeText (getContext (), "发表成功", Toast.LENGTH_SHORT).show ();}}return false;}});return view;}//动态添加textview实现评论private void addView(String string, LinearLayout linearLayout) {Log.e ("addView: ", "添加评论");TextView textView = new TextView (getContext ());textView.setText (username+": "+string);textView.setTextSize (15);linearLayout.addView (textView);LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams ();layoutParams.setMargins (0, 0, 0, 20);textView.setLayoutParams (layoutParams);}

①ListView效率优化

每次Listview的子项滑动到屏幕内时会自动调用getView()方法,重复加载布局及获得控件实例会导致ListView的运行效率降低,这里用到了convertView参数将之前加载好的布局缓存,并且自定义了内部ViewHodler类用来缓存控件实例,进行ListView运行效率的优化。

②动态评论功能的实现

首先实例化一个TextView对象,设置好textView的内容与样式,然后添加进布局容器,通过LayoutParams设置textView的布局参数。

③适配器的构造函数 用于在Activity中实例化自定义适配器对象,并且这里构造函数中我取得了listview每个子项目的布局文件,对它进行操作。

3、下面是Activity代码,这里有两个界面,空间动态主界面MainActivity和编辑动态界面WriteActivity。 ① WriteActivity

//发表动态buttonPublish.setOnClickListener (new View.OnClickListener () {@Overridepublic void onClick(View view) {//取得数据String stringArticle = editTextArticle.getText ().toString ().trim ();Date date=new Date ();SimpleDateFormat simpleDateFormat=new SimpleDateFormat ("MM-dd HH:mm");stringCurrenttime=simpleDateFormat.format (date);//创建传递数据的intent对象Intent intent1 = new Intent ();//存放数据intent1.putExtra ("editArticle", stringArticle);intent1.putExtra ("photoPath1",imagename1);intent1.putExtra ("photoPath2",imagename2);intent1.putExtra ("photoPath3",imagename3);intent1.putExtra ("stringCurrenttime",stringCurrenttime);setResult (RESULT_OK, intent1);finish ();}});//初始化发表按钮状态buttonPublish.setPressed (true);buttonPublish.setClickable (false);//设置取消按钮buttonCancle.setOnClickListener (new View.OnClickListener () {@Overridepublic void onClick(View view) {buttonCancle.setVisibility (View.INVISIBLE);finish ();}}); //文本监听editTextArticle.addTextChangedListener (new TextWatcher () {@Overridepublic void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {Log.e ("beforeTextChanged: ", "初试结果");}@Overridepublic void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {Log.e ("onTextChanged: ", "进行结果");}@Overridepublic void afterTextChanged(Editable editable) {Log.e ("afterTextChanged: ", "最终结果");if (editable.toString ().equals ("")&&imageView2.getDrawable ()==null) {buttonPublish.setPressed (true);buttonPublish.setClickable (false);} else {buttonPublish.setPressed (false);buttonPublish.setClickable (true);}}});}//点击拍摄@Overridepublic void onClick(View view) {Intent intentPhoto = new Intent (MediaStore.ACTION_IMAGE_CAPTURE);switch (view.getId ()) {case R.id.Iv_image1:if (isclickable1) {Log.e ("onClick: ", "拍照");startActivityForResult (intentPhoto, 100);} else {}break;case R.id.Iv_image2:if (isclickable2) {startActivityForResult (intentPhoto, 99);} else {}break;case R.id.Iv_image3:if (isclickable3) {startActivityForResult (intentPhoto, 98);} else {}break;}}//取出照片并显示protected void onActivityResult(int a, int b, Intent c) {super.onActivityResult (a, b, c);ImageView imageViewPhoto1, imageViewPhoto2, imageViewPhoto3;imageViewPhoto1 = findViewById (R.id.Iv_image1);imageViewPhoto2 = findViewById (R.id.Iv_image2);imageViewPhoto3 = findViewById (R.id.Iv_image3);if (b == Activity.RESULT_OK) {if (a == 100) {//取出图片Bundle bd = c.getExtras ();bitmap = (Bitmap) bd.get ("data");//获取当前时间得到路径Date date=new Date ();SimpleDateFormat simpleDateFormat=new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");stringDate1=simpleDateFormat.format (date);imagename1="/"+stringDate1+".jpg";Bitmap copyBitmap=createBitmap(bitmap,imagename1);//显示拍摄照片imageViewPhoto1.setScaleType (ImageView.ScaleType.CENTER_CROP);imageViewPhoto1.setImageBitmap (copyBitmap);//显示拍摄按钮imageViewPhoto2.setVisibility (View.VISIBLE);imageViewPhoto2.setImageResource (R.drawable.photoscale);buttonPublish.setClickable (true);buttonPublish.setPressed (false);isclickable1 = false;}if (a == 99) {Bundle bd = c.getExtras ();bitmap = (Bitmap) bd.get ("data");//获取当前时间得到路径Date date=new Date ();SimpleDateFormat simpleDateFormat=new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");stringDate2=simpleDateFormat.format (date); imagename2="/"+stringDate2+".jpg";Bitmap copyBitmap=createBitmap(bitmap,imagename2);//显示拍摄照片imageViewPhoto2.setScaleType (ImageView.ScaleType.CENTER_CROP);imageViewPhoto2.setImageBitmap (copyBitmap);//显示拍摄按钮imageViewPhoto3.setVisibility (View.VISIBLE);imageViewPhoto3.setImageResource (R.drawable.photoscale);isclickable2 = false;}if (a == 98) {Bundle bd = c.getExtras ();bitmap = (Bitmap) bd.get ("data");//获取当前时间得到路径Date date=new Date ();SimpleDateFormat simpleDateFormat=new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");stringDate3=simpleDateFormat.format (date);imagename3="/"+stringDate3+".jpg";Bitmap copyBitmap=createBitmap(bitmap,imagename3);//显示拍摄照片imageViewPhoto3.setScaleType (ImageView.ScaleType.CENTER_CROP);imageViewPhoto3.setImageBitmap (copyBitmap);isclickable3 = false;}}else {Toast.makeText (this, "没有拍摄照片", Toast.LENGTH_SHORT).show ();}}private Bitmap createBitmap(Bitmap bitmap,String photoname){//剪裁图片int W=bitmap.getWidth ();int H=bitmap.getHeight ();Bitmap newBitmap;if (W>H){newBitmap=bitmap.createBitmap (bitmap,(W-H)/2,0,H,H);}else {newBitmap=bitmap.createBitmap (bitmap,0,(H-W)/2,W,W);}//将照片缓存至本地File fileimage;try {fileimage=new File (getCacheDir ()+photoname);if(!fileimage.exists ()){fileimage.getParentFile ().mkdirs ();fileimage.createNewFile ();}FileOutputStream fos=new FileOutputStream (fileimage);newBitmap.compress (Bitmap.CompressFormat.JPEG,100,fos);fos.flush ();fos.close ();} catch (IOException e) {e.printStackTrace ();}return newBitmap;}

这里利用了系统时间以得到不同的照片命名并存储至本地。此外这里有关文件的操作后续要深入了解一下。

②MainActivity

//新增动态显示数据@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data){super.onActivityResult (requestCode,resultCode,data);switch(requestCode){case 1:if (resultCode==RESULT_OK){String stringArticle=data.getStringExtra ("editArticle");**//得到图片路径String imagepath1=get**CacheDir ()+data.getStringExtra ("photoPath1");String imagepath2=getCacheDir ()+data.getStringExtra ("photoPath2");String imagepath3=getCacheDir ()+data.getStringExtra ("photoPath3");// 获得发表时间String stringCurrenttime=data.getStringExtra ("stringCurrenttime"); Dynamic C=new Dynamic (R.drawable.myhead,"admin",stringArticle,imagepath1,imagepath2,imagepath3,stringCurrenttime,0);dynamicList.add(0,C);listView.setAdapter (adapter); Toast.makeText (getApplicationContext (),"发表成功",Toast.LENGTH_SHORT).show ();}break;}

这里要注意的是,listView中的数据刷新后要重新setAdapter,否则界面动态数据无法刷新。

四、最后

我写这些博客主要是为了加深自己的理解,也供后续回顾,有什么建议与想法大家都可以在下方评论或者私信我,互相交流共同进步。

2023更新

源码现已上传至csdn,点击下载***

相关推荐: