之前做项目的时候需要用到仿空间动态的功能,在此做一下记录,简单介绍一下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 () {
@Override
public 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 () {
@Override
public 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 () {
@Override
public 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 () {
@Override
public 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 () {
@Override
public void onClick(View view) {
buttonCancle.setVisibility (View.INVISIBLE);
finish ();
}
});
//文本监听
editTextArticle.addTextChangedListener (new TextWatcher () {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
Log.e ("beforeTextChanged: ", "初试结果");
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
Log.e ("onTextChanged: ", "进行结果");
}
@Override
public 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);
}
}
});
}
//点击拍摄
@Override
public 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
//新增动态显示数据
@Override
protected 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,否则界面动态数据无法刷新。
四、最后
我写这些博客主要是为了加深自己的理解,也供后续回顾,有什么建议与想法大家都可以在下方评论或者私信我,互相交流共同进步。