Android自定义弹窗模仿微信,Android 仿微信朋友圈点赞和评论弹出框功能
本文简单模仿微信朋友圈的点赞和评论弹出框,布局等细节请忽略,着重实现弹出框、发评论,及弹出位置的控制。
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;
@Override
protected 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 data
private ArrayList getData() {
int ITEM_COUNT = 20;
ArrayList 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 adapter
private class MyAdapter extends BaseAdapter implements ItemView.OnCommentListener {
private Context context;
private ArrayList mData;
private Map mCachedViews = new HashMap<>();
public MyAdapter(Context context, ArrayList mData) {
this.context = context;
this.mData = mData;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public 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;
}
@Override
public void onComment(int position) {
showCommentView(position);
}
private void cacheView(int position, ItemView view) {
Iterator> entries = mCachedViews.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry 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() {
@Override
public void onClick(View v) {
EditText et = (EditText) mCommentView.findViewById(R.id.edit);
String s = et.getText().toString();
if (!TextUtils.isEmpty(s)) {
// update model
Comment comment = new Comment(s);
mData.get(position).getComments().add(comment);
// update view maybe
ItemView 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);
}
@Override
protected 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);
}
}
@Override
public 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();
}
}
以上所述是小编给大家介绍的Android 仿微信朋友圈点赞和评论弹出框功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
Android自定义弹窗模仿微信,Android 仿微信朋友圈点赞和评论弹出框功能相关推荐
- Android 仿微信点赞和评论弹出框
下载源码:http://download.csdn.net/detail/zhaizu/9790030 本文简单模仿微信朋友圈的点赞和评论弹出框,布局等细节请忽略,着重实现弹出框.发评论,及弹出位置的 ...
- android 微信点赞功能,Android 仿微信点赞和评论弹出框
wjntekaqskfhwktpgpvzhp 1. 微信弹出框 微信朋友圈的点赞和评论功能,有2个组成部分: 左下角的"更多"按钮: 点击该按钮后弹出的对话框: 微信朋友圈点赞和评 ...
- android微信点赞ui,Android中使用PopupWindow 仿微信点赞和评论弹出
微信朋友圈的点赞和评论功能,有2个组成部分:左下角的"更多"按钮:点击该按钮后弹出的对话框: PopupWindow,弹出框使用PopupWindow实现,这是点赞和评论的载体,具 ...
- android 微信评论功能,Android仿微信朋友圈点赞和评论功能
最近在做朋友圈的项目,所以写一个Android仿朋友圈点赞和评论功能Demo,代码就是简单实现了一下功能,没有做优化,凑合看. 图文排列是用的RecyclerView实现的,弹窗效果是用的自定义的Po ...
- 仿微信朋友圈点赞和评论功能
仿微信朋友圈点赞和评论功能 最近在做朋友圈的项目,所以写一个Demo,代码就是简单实现了一下功能,没有做优化,凑合看 图文排列是用的RecyclerView实现的,弹窗效果是用的自定义的PopupWi ...
- 微信朋友圈消息列表html,微信,怎么查看朋友圈以前的评论消息?
原标题:微信,怎么查看朋友圈以前的评论消息? 怎么在微信里面找到好友之前和我们之间互动留下的评论?也就是说微信朋友圈回复的消息列表在哪呢? 经常玩微信的朋友就知道通常如果好友评论或者赞了自已的动态及你 ...
- java调用个人微信API接口收发朋友圈,删除评论朋友圈
java调用个人微信API接口收发朋友圈,删除评论朋友圈 /** * 发送朋友圈任务 * @author wechatno:tangjinjinwx * @param ctx * @param vo ...
- yii php 弹窗,Yii框架弹出框功能示例
本文实例讲述了Yii框架弹出框功能.分享给大家供大家参考,具体如下: <?php $this->beginWidget('zii.widgets.jui.CJuiDialog', arra ...
- Android自定义弹窗模仿微信,Android仿微信右上角点击加号弹出PopupWindow
本文实例为大家分享了Android仿微信右上角点击加号弹出展示的具体代码,供大家参考,具体内容如下 一.要弹出的布局,随便设计 android:layout_width="match_par ...
最新文章
- why-and-howto-calculate-your-events-per-second
- 面试官:能说下 SpringBoot 启动原理吗?
- BugkuCTF-Misc:Linux2
- 2022年最值得学习的 5 种编程语言,你有在学习吗?
- tp3.2 视图中U函数传变量值
- java redis 删除整个hash_redis中hash表内容删除的方法代码
- 反爬虫破解——裁判文书网
- 同是匿名社交,国内外“秘密”大不同
- c#:判断一个数组元素中否有重复元素
- 《英语语法新思维初级教程——走近语法》阅读笔记(持续更新中)
- DNS服务器可能不可用
- 多线程调用ch.ethz.ssh2.Connection执行shell任务时有的执行丢失情况解决
- [AWS] dynamodb-local本地数据库安装以及dynamoose模块连接dynamodb-local
- RK3588S Android12 旋转系统图像
- 试题 算法训练 黑色星期五
- 燕京理工学院计算机答辩难吗,燕京理工学院:一腔热血答与辩,满腹经纶方成功...
- python3 笔记9 字典
- php 支付宝电脑支付宝,PHP语言学习之php 做支付宝电脑网站和app支付
- MFC 调用系统ping工具检测网络
- Word 2007 2010 书法字帖 停止保护
热门文章
- android通知栏的点击事件,Android监听消息通知栏点击事件
- 『杭电1869』六度分离
- 大数据专业找工作分析
- Vue-常用加密(MD5,DES,SHA256,BASE64,SHA1,RSA)
- JAVA领域10位大神
- Postgresql skip locked跳过行锁消除行锁冲突等待
- 在WIN2012R2和WIN2016服务器打开网站慢的解决方法
- 如何识别一个网站是正规合法的网站
- 转载_Linux下Bluetooth编程
- [SPRD CAMERA] 5 HAL Camera open流程二