下载源码:http://download.csdn.net/detail/zhaizu/9790030

本文简单模仿微信朋友圈的点赞和评论弹出框,布局等细节请忽略,着重实现弹出框、发评论,及弹出位置的控制。

#1. 微信弹出框
微信朋友圈的点赞和评论功能,有2个组成部分:

  1. 点击左下角的“更多”按钮,弹出对话框;
  2. 点击评论,弹出输入框,添加评论并在页面中实时显示;

微信朋友圈点赞和评论功能

#2. 实际效果
本文将建一个 ListView,在其 Item 中简单模仿微信的布局,然后着重实现弹出窗,并能发评论,忽略具体布局细节。具体效果如下:

丑爆了,我知道了,⊙﹏⊙||

#3. 知识点清单

  • ListView
    自定义 Adapter,重写 getView()方法;

  • PopupWindow
    弹出框使用PopupWindow实现,这是点赞和评论的载体,具体要涉及 PopupWindow 点击非窗口位置和再次点击消失以及显示位置的问题(根据相应更多按钮的位置确定 PopupWindow 的显示位置,关于 PopupWindow 的显示位置,可以参考我的另一篇文章 Android PopupWindow 的显示位置);

  • LayoutInflater
    使用LayoutInflater 动态加载PopupWindow 的布局,关于 LayoutInflater 的更多知识,参见我的另一篇博客 Android LayoutInflater ;

  • Activity 和 Item 的双向通信
    通过自定义 OnCommentListener() 来实现 MainActivity(具体来说是屏幕底部评论框中的输入的内容)和 ItemView(动态的获得上述输入的评论内容并展示在该ItemView 中) 的通信,更多知识参见我的另一篇博客《 燕过留声:由 Activity 和 Fragment 的通信方法想到的》;

  • 自定义控件
    ListView 中的每个 Item 是一个自定义的 ItemView,记得要重写构造方法,否则会抛出 android.view.InflateException 异常;

  • 如果想实现微信评论那样用户名和内容回复文字字体颜色不同,而且点击评论用户名触发页面跳转等功能,请参见 《布局优化技巧笔记》 之 ClickableSpan 章节;

#4. 美工素材
由于 .apk 本质上是个压缩包,我们可以通过解压得到该 .apk 文件的图片素材和布局文件,更多获得素材的方法参见我的另一篇博文 如何获得Android素材图片。通过这种方式得到颜色、更多按钮的样式等素材,仅供学习之用,请勿做侵犯版权之事。尊重知识版权既是大势所趋,也是终将使每个开发者受益的事。

文件夹r里存放图片 找到更多按钮

#5. 关键代码
开发环境:Android Studio 1.4.1 for Mac + ADT 21 + JDK 1.8.0。

MainAcitivity.java

package main.zhaizu.com.popupwindowdemo;import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;import main.zhaizu.com.popupwindowdemo.model.Comment;
import main.zhaizu.com.popupwindowdemo.model.Item;
import main.zhaizu.com.popupwindowdemo.ui.ItemView;public class MainActivity extends AppCompatActivity {private ListView mListView;private View mCommentView;private MyAdapter myAdapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mListView = (ListView) findViewById(R.id.listview);myAdapter = new MyAdapter(this, getData());mListView.setAdapter(myAdapter);mCommentView = findViewById(R.id.comment_view);}// build dataprivate ArrayList<Item> getData() {int ITEM_COUNT = 20;ArrayList<Item> data = new ArrayList<>();data.add(new Item(R.drawable.xiaona, "薄荷栗", "我学过跆拳道,都给我跪下唱征服", "昨天"));data.add(new Item(R.drawable.xueyan, "欣然", "走遍天涯海角,唯有我家风景最好,啊哈哈", "昨天"));data.add(new Item(R.drawable.leishao, "陈磊_CL", "老子以后要当行长的,都来找我借钱吧,now", "昨天"));data.add(new Item(R.drawable.yuhong, "永恒依然", "房子车子都到碗里来", "昨天"));data.add(new Item(R.drawable.lanshan, "蓝珊", "你们这群傻×,我笑而不语", "昨天"));return data;}// custom adapterprivate class MyAdapter extends BaseAdapter implements ItemView.OnCommentListener {private Context context;private ArrayList<Item> mData;private Map<Integer, ItemView> mCachedViews = new HashMap<>();public MyAdapter(Context context, ArrayList<Item> mData) {this.context = context;this.mData = mData;}@Overridepublic int getCount() {return mData.size();}@Overridepublic Object getItem(int position) {return mData.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view;if (convertView != null) {view = convertView;} else {LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);view = inflater.inflate(R.layout.listview_item, null, false);}if (view instanceof ItemView) {Item data = (Item) getItem(position);((ItemView) view).setData(data);((ItemView) view).setPosition(position);((ItemView) view).setCommentListener(this);cacheView(position, (ItemView) view);}return view;}@Overridepublic void onComment(int position) {showCommentView(position);}private void cacheView(int position, ItemView view) {Iterator<Map.Entry<Integer, ItemView>> entries = mCachedViews.entrySet().iterator();while (entries.hasNext()) {Map.Entry<Integer, ItemView> entry = entries.next();if (entry.getValue() == view && entry.getKey() != position) {mCachedViews.remove(entry.getKey());break;}}mCachedViews.put(position, view);}private void showCommentView(final int position) {mCommentView.setVisibility(View.VISIBLE);mCommentView.findViewById(R.id.submit).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {EditText et = (EditText) mCommentView.findViewById(R.id.edit);String s = et.getText().toString();if (!TextUtils.isEmpty(s)) {// update modelComment comment = new Comment(s);mData.get(position).getComments().add(comment);// update view maybeItemView itemView = mCachedViews.get(position);if (itemView != null && position == itemView.getPosition()) {itemView.addComment();}et.setText("");mCommentView.setVisibility(View.GONE);}}});}}
}

ItemView.java

package main.zhaizu.com.popupwindowdemo.ui;import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;import main.zhaizu.com.popupwindowdemo.R;
import main.zhaizu.com.popupwindowdemo.model.Comment;
import main.zhaizu.com.popupwindowdemo.model.Item;/*** Created by cmm on 15/10/31.*/
public class ItemView extends LinearLayout implements View.OnClickListener {private int mPosition;private Item mData;private ImageView mPortraitView;private TextView mUserNameView;private TextView mContentView;private TextView mCreatedAtView;private LinearLayout mCommentLayout;private View mMoreView;private PopupWindow mMorePopupWindow;private int mShowMorePopupWindowWidth;private int mShowMorePopupWindowHeight;private OnCommentListener mCommentListener;public ItemView(Context context) {super(context);}public ItemView(Context context, AttributeSet attrs) {super(context, attrs);}public interface OnCommentListener {void onComment(int position);}@Overrideprotected void onFinishInflate() {super.onFinishInflate();mPortraitView = (ImageView) findViewById(R.id.portrait);mUserNameView = (TextView) findViewById(R.id.nick_name);mContentView = (TextView) findViewById(R.id.content);mCreatedAtView = (TextView) findViewById(R.id.created_at);mCommentLayout = (LinearLayout) findViewById(R.id.comment_layout);mMoreView = findViewById(R.id.more_btn);}public void setPosition(int mPosition) {this.mPosition = mPosition;}public void setCommentListener(OnCommentListener l) {this.mCommentListener = l;}public void setData(Item data) {mData = data;mPortraitView.setImageResource(data.getPortraitId());mUserNameView.setText(data.getNickName());mContentView.setText(data.getContent());updateComment();mMoreView.setOnClickListener(this);}/*** 弹出点赞和评论框** @param moreBtnView*/private void showMore(View moreBtnView) {if (mMorePopupWindow == null) {LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);View content = li.inflate(R.layout.layout_more, null, false);mMorePopupWindow = new PopupWindow(content, ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);mMorePopupWindow.setBackgroundDrawable(new BitmapDrawable());mMorePopupWindow.setOutsideTouchable(true);mMorePopupWindow.setTouchable(true);content.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);mShowMorePopupWindowWidth = content.getMeasuredWidth();mShowMorePopupWindowHeight = content.getMeasuredHeight();View parent = mMorePopupWindow.getContentView();TextView like = (TextView) parent.findViewById(R.id.like);TextView comment = (TextView) parent.findViewById(R.id.comment);// 点赞的监听器comment.setOnClickListener(this);}if (mMorePopupWindow.isShowing()) {mMorePopupWindow.dismiss();} else {int heightMoreBtnView = moreBtnView.getHeight();mMorePopupWindow.showAsDropDown(moreBtnView, -mShowMorePopupWindowWidth,-(mShowMorePopupWindowHeight + heightMoreBtnView) / 2);}}private void updateComment() {if (mData.hasComment()) {mCommentLayout.removeAllViews();mCommentLayout.setVisibility(View.VISIBLE);for (Comment c : mData.getComments()) {TextView t = new TextView(getContext());t.setLayoutParams(new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)));t.setBackgroundColor(getResources().getColor(R.color.colorCommentLayoutBg));t.setTextSize(16);t.setPadding(5, 2, 0, 3);t.setLineSpacing(3, (float) 1.5);t.setText(c.getComment());mCommentLayout.addView(t);}} else {mCommentLayout.setVisibility(View.GONE);}}@Overridepublic void onClick(View v) {int id = v.getId();if (id == R.id.more_btn) {showMore(v);} else if (id == R.id.comment) {if (mCommentListener != null) {mCommentListener.onComment(mPosition);if (mMorePopupWindow != null && mMorePopupWindow.isShowing()) {mMorePopupWindow.dismiss();}}}}public int getPosition() {return mPosition;}public void addComment() {updateComment();}
}

#6. 感谢
本文中 listview 的布局改编自 http://download.csdn.net/download/weiyirong/6709151,感谢该作者的分享。

本文持续更新,转载请注明出处:http://blog.csdn.net/zhaizu/article/details/48103351

Android 仿微信点赞和评论弹出框相关推荐

  1. android 微信点赞功能,Android 仿微信点赞和评论弹出框

    wjntekaqskfhwktpgpvzhp 1. 微信弹出框 微信朋友圈的点赞和评论功能,有2个组成部分: 左下角的"更多"按钮: 点击该按钮后弹出的对话框: 微信朋友圈点赞和评 ...

  2. android微信点赞ui,Android中使用PopupWindow 仿微信点赞和评论弹出

    微信朋友圈的点赞和评论功能,有2个组成部分:左下角的"更多"按钮:点击该按钮后弹出的对话框: PopupWindow,弹出框使用PopupWindow实现,这是点赞和评论的载体,具 ...

  3. Android自定义弹窗模仿微信,Android 仿微信朋友圈点赞和评论弹出框功能

    本文简单模仿微信朋友圈的点赞和评论弹出框,布局等细节请忽略,着重实现弹出框.发评论,及弹出位置的控制. 1. 微信弹出框 微信朋友圈的点赞和评论功能,有2个组成部分: 点击左下角的"更多&q ...

  4. Android仿IOS封装通用的弹出框Dialog和底部弹出列表选择框 仿美团顶部条件筛选框 附自定义ViewGroup

    弹出框 背景 提示与询问弹出框 实现 使用 列表选择框 实现 使用 顶部条件筛选框 实现 自定义ViewGroup 使用 总结 背景 鉴于Android提供的默认弹出框很一般,IOS的弹出框样式还不错 ...

  5. Android仿淘宝口令复制弹出框功能

    1.我要做什么 应用场景: 我的朋友使用微信给我发一个淘宝链接的口令,我复制口令,进入我的淘宝,弹框,显示口令的详情,点击详情,进入商品页面. 存在的问题: 但这存在一个问题,我的淘宝并不总是关闭状态 ...

  6. Kotlin 仿微信长按列表弹出菜单(动画)

    一.测试 实现: 二.项目: 仿微信长按列表弹出菜单代码,MainActivity.kt class MainActivity : AppCompatActivity(), AdapterView.O ...

  7. android 仿微信朋友圈 评论,2020年android 仿微信朋友圈 评论

    2020年android 仿微信朋友圈 评论 1.如果有人问我:那些艰难的岁月你是怎么熬过来的?我想我只有一句话回答:我有一种强大的精神力量支撑着我,这种力量名字叫"想死又不敢" ...

  8. android h5弹窗,Android嵌套html5页面中alert 弹出框问题

    最近项目中遇到一个头疼的问题,那就是在安卓里嵌套html5的时候发现alert弹出框出现了问题 那就是弹出的时候会出现串 来自http://xxxxx 网页的提示 然后下面出来具体的弹出信息,还有更奇 ...

  9. 微信小程序vantweapp-Dialog弹出框提交表单,并还原确定按钮样式

    vantweapp中Dialog弹出框使用组件调用,怎么将form表单的提交按钮与Dialog弹出框相结合呢 解决方案: wxml代码 <van-dialoguse-slottitle=&quo ...

最新文章

  1. Java中@Override的作用
  2. C语言中的位操作(4)--判断整数是否为2的幂
  3. 安全现状:从通杀到专杀
  4. 大牛书单 | 读懂5G,改变社会
  5. openeim再被刺也忍着痛继续吃
  6. vue和java bean_Java:JavaBean和BeanUtils
  7. linux配置ARP内核参数,详细讲解linux内核参数arp_announce和arp_ignore
  8. 树状数组 Binary Indexed Tree/Fenwick Tree
  9. 怎么看笔记本电脑的配置参数_想给笔记本电脑硬件配置升级,我应该怎么升?...
  10. 火星人谚语系列之八:少读书,多思考
  11. springBoot事物
  12. 火狐浏览器的hoxx附件还能用吗_Haspit
  13. 一些不为人知的秘密[迅雷和快播]
  14. mysql随机生成 姓名+电话
  15. 想要升级Big Sur 了?良心建议看看这个
  16. 使用给定的整数n,编写一个程序生成一个包含(i, i*i)的字典,该字典包含1到n之间的整数(两者都包含)。假设向程序输入:5则输出为:{1:1, 2:4, 3:9, 4:16, 5:25}
  17. MNF最小噪声分离变换(转)
  18. 最强大脑记忆曲线(12)-- 录入数据修改
  19. excel表格换行快捷键_常州办公excel表格常用技巧, 办公软件常用快捷键【金坛吧】...
  20. /?、//、/'……等等是一个字符

热门文章

  1. 大一上学期计算机试卷,大一计算机基础试卷
  2. SEO常用外链资源站整理分享
  3. 【求职】瓜子二手车 C++方向面经
  4. Linux--RAID磁盘阵列学习使用(详细学习)
  5. html5 video 视频标签详解
  6. 一种在Qlik Sense 中计算两个年月所覆盖时间跨度的方法以及场景应用
  7. MP4格式及在MP4文件中提取H264的SPS、PPS及码流
  8. kindle电子书分享网 - 技术栈
  9. iptables介绍和使用
  10. 鸣放礼炮问题 C语言