Android仿qq聊天记录长按删除功能效果

简介:

最近项目在做IM即时通讯开发,在删除聊天列表的时候跟删除聊天详细信息的时候,产品经理想要跟ios一样,在当前选中行上方弹出一个删除窗口.于是先从网上找demo,找了一个发现是Dialog做的,我感觉没有必要这么麻烦,于是我用Popupwindow实现了一个,有需要的朋友可以参考一下。

1.效果图如下(长按列表弹窗,消息详细信息长按弹窗)



2.对源码进行说明。

一条消息实体类,有消息内容跟是否发送这两个属性。

  1. public class Message {  
  2.     private String content;// 消息内容  
  3.     private boolean sended;// 是否发送  
  4.       
  5.     public Message(){  
  6.     }  
  7.       
  8.     public Message(String content,boolean sended){  
  9.         this.content=content;  
  10.         this.sended=sended;  
  11.     }  
  12.   
  13.     public String getContent() {  
  14.         return content;  
  15.     }  
  16.   
  17.     public void setContent(String content) {  
  18.         this.content = content;  
  19.     }  
  20.   
  21.     public boolean isSended() {  
  22.         return sended;  
  23.     }  
  24.   
  25.     public void setSended(boolean sended) {  
  26.         this.sended = sended;  
  27.     }  
  28. }  

消息详细信息的Activity

1).给每条消息设置长按事件,把点击的下标用tag传进去

2).用popupwindow展示,显示在当前点击的View下方,然后设置xy的偏移度

  1.  * 消息详细界面  
  2.  * @author ansen  
  3.  * @create time 2015-08-04  
  4.  */  
  5. public class MessageDetailActivity extends Activity{  
  6.     private List<Message> messages=new ArrayList<Message>();  
  7.     private ListView listView;  
  8.     private MyAdapter mAdapter;  
  9.       
  10.     private PopupWindow popupWindow;  
  11.     private TextView tvDelete;  
  12.     private EditText etInput;  
  13.     private int longClickPosition;  
  14.       
  15.     @Override  
  16.     protected void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         setContentView(R.layout.activity_private_message_detail_list);  
  19.           
  20.         initData();  
  21.           
  22.         listView=(ListView) findViewById(R.id.list_private_message);  
  23.         listView.setAdapter(mAdapter=new MyAdapter());  
  24.           
  25.         TextView sendMessage=(TextView) findViewById(R.id.tv_send_message);  
  26.         sendMessage.setOnClickListener(clickListener);  
  27.           
  28.         etInput=(EditText) findViewById(R.id.et_input);  
  29.     }  
  30.       
  31.       
  32.     private class MyAdapter extends BaseAdapter{  
  33.         private LayoutInflater inflater;  
  34.         public MyAdapter(){  
  35.             inflater=LayoutInflater.from(MessageDetailActivity.this);  
  36.         }  
  37.   
  38.         @Override  
  39.         public int getCount() {  
  40.             return messages.size();  
  41.         }  
  42.   
  43.         @Override  
  44.         public Object getItem(int position) {  
  45.             return messages.get(position);  
  46.         }  
  47.   
  48.         @Override  
  49.         public long getItemId(int position) {  
  50.             return position;  
  51.         }  
  52.   
  53.         @Override  
  54.         public View getView(int position, View convertView, ViewGroup parent) {  
  55.             ViewHolder holder = null;  
  56.             if(null==convertView){  
  57.                 holder=new ViewHolder();  
  58.                 convertView= inflater.inflate(R.layout.item_private_message_chat,parent,false);  
  59.                 holder.tvMessageTo=(TextView) convertView.findViewById(R.id.tv_message_to);  
  60.                 holder.ivMessageToHeadImage=(ImageView) convertView.findViewById(R.id.iv_message_to_head_image);  
  61.                   
  62.                 holder.tvMessageFrom=(TextView) convertView.findViewById(R.id.tv_message_from);  
  63.                 holder.ivMessageFromHeadImage=(ImageView) convertView.findViewById(R.id.iv_message_from_head_image);  
  64.                 convertView.setTag(holder);  
  65.             }else{  
  66.                 holder=(ViewHolder) convertView.getTag();  
  67.             }  
  68.               
  69.             Message message=messages.get(position);  
  70.             if(message.isSended()){//发送消息  
  71.                 holder.tvMessageTo.setVisibility(View.GONE);  
  72.                 holder.ivMessageToHeadImage.setVisibility(View.GONE);  
  73.                   
  74.                 holder.tvMessageFrom.setVisibility(View.VISIBLE);  
  75.                 holder.tvMessageFrom.setText(message.getContent());  
  76.                 holder.tvMessageFrom.setOnLongClickListener(longClickListener);  
  77.                 holder.tvMessageFrom.setTag(position);  
  78.                   
  79.                 holder.ivMessageFromHeadImage.setVisibility(View.VISIBLE);  
  80.             }else{//接收消息  
  81.                 holder.tvMessageFrom.setVisibility(View.GONE);  
  82.                 holder.ivMessageFromHeadImage.setVisibility(View.GONE);  
  83.                   
  84.                 holder.tvMessageTo.setVisibility(View.VISIBLE);  
  85.                 holder.tvMessageTo.setText(message.getContent());  
  86.                 holder.tvMessageTo.setOnLongClickListener(longClickListener);  
  87.                 holder.tvMessageTo.setTag(position);  
  88.                   
  89.                 holder.ivMessageToHeadImage.setVisibility(View.VISIBLE);  
  90.             }  
  91.             return convertView;  
  92.         }  
  93.           
  94.         private class ViewHolder{  
  95.             private ImageView ivMessageToHeadImage;//接收消息用户头像  
  96.             private TextView tvMessageTo;//接收消息内容  
  97.               
  98.             private ImageView ivMessageFromHeadImage;//发送消息用户头像  
  99.             private TextView tvMessageFrom;//发送消息内容  
  100.         }  
  101.     }  
  102.       
  103.     private OnLongClickListener longClickListener=new OnLongClickListener() {  
  104.         @Override  
  105.         public boolean onLongClick(View v) {  
  106.             longClickPosition=(Integer) v.getTag();  
  107.             showDialog(v);  
  108.             return true;  
  109.         }  
  110.     };  
  111.       
  112.     private void  showDialog(View view){  
  113.         if(null==popupWindow){  
  114.             View popView = LayoutInflater.from(this).inflate(R.layout.layout_long_click_dialog, null);  
  115.             tvDelete=(TextView) popView.findViewById(R.id.tv_delete);  
  116.             tvDelete.setOnClickListener(clickListener);  
  117.             popupWindow = new PopupWindow(popView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
  118.             popupWindow.setAnimationStyle(R.style.PopAnimStyle);  
  119.             popupWindow.setOutsideTouchable(true);  
  120.             popupWindow.setBackgroundDrawable(new BitmapDrawable());  
  121.         }  
  122.         if (popupWindow.isShowing())  
  123.             popupWindow.dismiss();  
  124.           
  125.         //第一次显示控件的时候宽高会为0   
  126.         int deleteHeight=tvDelete.getHeight()==0?145:tvDelete.getHeight();  
  127.         int deleteWidth=tvDelete.getWidth()==0?212:tvDelete.getWidth();  
  128.           
  129.         popupWindow.showAsDropDown(view,(view.getWidth()-deleteWidth)/2,-view.getHeight()-deleteHeight);  
  130.     }  
  131.       
  132.     private OnClickListener clickListener=new OnClickListener() {  
  133.         @Override  
  134.         public void onClick(View v) {  
  135.             switch (v.getId()) {  
  136.             case R.id.tv_delete:  
  137.                 messages.remove(longClickPosition);  
  138.                 mAdapter.notifyDataSetChanged();  
  139.                   
  140.                 popupWindow.dismiss();  
  141.                 break;  
  142.             case R.id.tv_send_message:  
  143.                 String content=etInput.getText().toString().trim();  
  144.                 if(!TextUtils.isEmpty(content)){  
  145.                     Message message=new Message(content, true);  
  146.                     messages.add(message);  
  147.                     mAdapter.notifyDataSetChanged();  
  148.                     listView.setSelection(mAdapter.getCount()-1);  
  149.                 }  
  150.                 break;  
  151.             }  
  152.         }  
  153.     };  
  154.       
  155.     private void initData(){  
  156.         Message message=new Message("范德萨范德"true);  
  157.         Message message7=new Message("范德萨范德fds"true);  
  158.         Message message1=new Message("个人提个人鬼地"false);  
  159.         Message message4=new Message("接收消息"false);  
  160.         Message message2=new Message("吃饭了嘛。。。。吃过了没有啊。。。。。还没有吃啊 范德萨范德萨发水电费的说法都是"true);  
  161.         Message message3=new Message("吃饭了嘛。。。。吃过了没有啊。。。。。还没有吃啊 范德萨范德萨发水电费的说法都是"false);  
  162.         messages.add(message);  
  163.         messages.add(message1);  
  164.         messages.add(message2);  
  165.         messages.add(message3);  
  166.         messages.add(message4);  
  167.         messages.add(message7);  
  168.     }  
  169. }  

消息详细列表布局文件 activity_private_message_detail_list.xml     

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <ListView  
  7.         android:id="@+id/list_private_message"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent"  
  10.         android:layout_above="@+id/ll_bottom"  
  11.         android:divider="@null" >  
  12.     </ListView>  
  13.   
  14.     <include  
  15.         android:id="@+id/ll_bottom"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="wrap_content"  
  18.         android:layout_alignParentBottom="true"  
  19.         layout="@layout/layout_input_comment" />  
  20.   
  21. </RelativeLayout>  


底部输入框布局

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="wrap_content"  
  5.     android:orientation="vertical">  
  6.   
  7.     <RelativeLayout  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:paddingBottom="7dip"  
  11.         android:paddingTop="7dip">  
  12.           
  13.         <ImageView  
  14.             android:id="@+id/iv_message_to_head_image"  
  15.             android:layout_alignParentLeft="true"  
  16.             android:layout_marginLeft="5dp"  
  17.             android:layout_marginRight="5dp"  
  18.             android:layout_width="40dp"  
  19.             android:layout_height="40dp"  
  20.             android:src="@drawable/slide_left_avatar_default"/>  
  21.   
  22.         <TextView  
  23.             android:id="@+id/tv_message_to"  
  24.             android:layout_width="wrap_content"  
  25.             android:layout_height="wrap_content"  
  26.             android:background="@drawable/icon_message_to"  
  27.             android:gravity="center"  
  28.             android:paddingLeft="20dip"  
  29.             android:textColor="@color/register_text_color"  
  30.             android:layout_toRightOf="@+id/iv_message_to_head_image"  
  31.             android:layout_marginRight="55dp"  
  32.             android:textSize="16dip"/>  
  33.   
  34.         <TextView  
  35.             android:id="@+id/tv_message_from"  
  36.             android:layout_width="wrap_content"  
  37.             android:layout_height="wrap_content"  
  38.             android:layout_toLeftOf="@+id/iv_message_from_head_image"  
  39.             android:background="@drawable/icon_message_from"  
  40.             android:gravity="center"  
  41.             android:paddingRight="20dip"  
  42.             android:textColor="@color/white_normal"  
  43.             android:layout_marginLeft="55dp"  
  44.             android:text="我已经吃过了"  
  45.             android:textSize="16dip"/>  
  46.           
  47.         <!--          -->  
  48.         <ImageView  
  49.             android:id="@+id/iv_message_from_head_image"  
  50.             android:layout_alignParentRight="true"  
  51.             android:layout_marginLeft="5dp"  
  52.             android:layout_marginRight="5dp"  
  53.             android:layout_width="40dp"  
  54.             android:layout_height="40dp"  
  55.             android:src="@drawable/slide_left_avatar_default"/>  
  56.     </RelativeLayout>  
  57.   
  58. </LinearLayout>  

每一条消息的布局文件

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="wrap_content"  
  5.     android:orientation="vertical">  
  6.   
  7.     <RelativeLayout  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:paddingBottom="7dip"  
  11.         android:paddingTop="7dip">  
  12.           
  13.         <ImageView  
  14.             android:id="@+id/iv_message_to_head_image"  
  15.             android:layout_alignParentLeft="true"  
  16.             android:layout_marginLeft="5dp"  
  17.             android:layout_marginRight="5dp"  
  18.             android:layout_width="40dp"  
  19.             android:layout_height="40dp"  
  20.             android:src="@drawable/slide_left_avatar_default"/>  
  21.   
  22.         <TextView  
  23.             android:id="@+id/tv_message_to"  
  24.             android:layout_width="wrap_content"  
  25.             android:layout_height="wrap_content"  
  26.             android:background="@drawable/icon_message_to"  
  27.             android:gravity="center"  
  28.             android:paddingLeft="20dip"  
  29.             android:textColor="@color/register_text_color"  
  30.             android:layout_toRightOf="@+id/iv_message_to_head_image"  
  31.             android:layout_marginRight="55dp"  
  32.             android:textSize="16dip"/>  
  33.   
  34.         <TextView  
  35.             android:id="@+id/tv_message_from"  
  36.             android:layout_width="wrap_content"  
  37.             android:layout_height="wrap_content"  
  38.             android:layout_toLeftOf="@+id/iv_message_from_head_image"  
  39.             android:background="@drawable/icon_message_from"  
  40.             android:gravity="center"  
  41.             android:paddingRight="20dip"  
  42.             android:textColor="@color/white_normal"  
  43.             android:layout_marginLeft="55dp"  
  44.             android:text="我已经吃过了"  
  45.             android:textSize="16dip"/>  
  46.           
  47.         <!--          -->  
  48.         <ImageView  
  49.             android:id="@+id/iv_message_from_head_image"  
  50.             android:layout_alignParentRight="true"  
  51.             android:layout_marginLeft="5dp"  
  52.             android:layout_marginRight="5dp"  
  53.             android:layout_width="40dp"  
  54.             android:layout_height="40dp"  
  55.             android:src="@drawable/slide_left_avatar_default"/>  
  56.     </RelativeLayout>  
  57.   
  58. </LinearLayout>  


弹出删除按钮的布局文件

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <TextView  
  7.         android:id="@+id/tv_delete"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:background="@drawable/icon_private_message_delete"  
  11.         android:gravity="center_horizontal"  
  12.         android:padding="5dp"  
  13.         android:text="删除"  
  14.         android:textColor="#ffffffff" />  
  15.   
  16. </FrameLayout>  

点击链接下载源码

目录
相关文章
|
20天前
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
6月前
|
Android开发
Android开发表情emoji功能开发
本文介绍了一种在Android应用中实现emoji表情功能的方法,通过将图片与表情字符对应,实现在`TextView`中的正常显示。示例代码展示了如何使用自定义适配器加载emoji表情,并在编辑框中输入或删除表情。项目包含完整的源码结构,可作为开发参考。视频演示和源码详情见文章内链接。
147 4
Android开发表情emoji功能开发
|
6月前
|
安全 Android开发 iOS开发
Android vs iOS:探索移动操作系统的设计与功能差异###
【10月更文挑战第20天】 本文深入分析了Android和iOS两个主流移动操作系统在设计哲学、用户体验、技术架构等方面的显著差异。通过对比,揭示了这两种系统各自的独特优势与局限性,并探讨了它们如何塑造了我们的数字生活方式。无论你是开发者还是普通用户,理解这些差异都有助于更好地选择和使用你的移动设备。 ###
156 3
|
8月前
|
编解码 测试技术 Android开发
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
本文详细介绍了如何利用CameraX库实现高质量的照片及视频拍摄功能,包括添加依赖、初始化、权限请求、配置预览与捕获等关键步骤。此外,还特别针对不同分辨率和帧率的视频拍摄提供了性能优化策略,确保应用既高效又稳定。
765 1
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
|
7月前
|
Android开发 开发者
Android平台无纸化同屏如何实现实时录像功能
Android平台无纸化同屏,如果需要本地录像的话,实现难度不大,只要复用之前开发的录像模块的就可以,对我们来说,同屏采集这块,只是数据源不同而已,如果是自采集的其他数据,我们一样可以编码录像。
|
1月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
288 76
|
2月前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
85 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
2月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
227 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
2月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
74 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
3月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
185 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程

热门文章

最新文章

下一篇
oss创建bucket