android 新浪微博客户端的表情功能的实现

这是一篇好文章,我转来收藏,技术的最高境界是分享。

 

最近在搞android 新浪微博客户端,有一些心得分享
弄android客户端表情功能可以用以下思路
1.首页把新浪的表情下载到本地一文件夹种,表情图片的命名要用新浪微博表情原来的命名
比如 新浪的害羞表情是shame.gif 那么你在本地也得命名为shame.gif,命名相同主要是为了能够匹配表情对应的code.
2.把本地的表情都放进android的资源文件里----drawable下面
3.访问新浪的表情接口(新浪返回的数据类型有json和xml两种,本人用xml),把返回的信息,利用xml解析器解析出来的信息储存在一个Emotion.java的bean里,这样就可以根据Emotion.java的code找到一一对应的资源表情图片了
4.实现一个可以让用户选择的表情界面,本人用GridView实现
5.实现点击GridView的每一个item,处理根据item的index查找对应的表情code,然后再把code利用正则把code转换为相对应的表情图片,最后表情插入EditText进行发送。

 

下面是具体的实现过程

1.把新浪表情图片下载到本地的实现如下:(这个可以建一个java工程进行下载)

public void getFriendList() throws Exception {
BlogReleaseServiceImpl service = new BlogReleaseServiceImpl();
List<Emotions> list = service.getEmotion();
for (Emotions emotions : list) {
String path = emotions.getUrl();
String filename = path.substring(path.lastIndexOf("/") + 1,path.length());
URL url =  new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5 * 1000);
if(conn.getResponseCode() == 200){
InputStream is = conn.getInputStream();
byte[] data = readStream(is);
File file = new File("f: \\sina_images\\" + filename);
FileOutputStream fs = new FileOutputStream(file);
fs.write(data);
fs.close();
}else{
System.out.println("请求失败");
}
}
}
public byte[] readStream(InputStream is) throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len = 0;
while((len = is.read(buffer)) != -1){
os.write(buffer,0,len);
}
is.close();
return os.toByteArray();
}

2:把本地的表情都放进android的资源文件里----drawable下面(这个就不用多说了,直接选取所有文件复制就行了)

3:

3.1访问新浪的表情接口,把返回的信息如下:

       <emotion>
<phrase>[嘻嘻]</phrase>
<type>face</type>
<url>http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/c2/tooth.gif
</url>
<is_hot>false</is_hot>
<is_common>true</is_common>
<order_number>0</order_number>
<category></category>
</emotion>


3.2 储存在一个Emotion.java里。Emotion.java代码如下:

package com.uim.microblog.model;
import java.io.Serializable;
public class Emotions implements Serializable {
/**
* 
*/
private static final long serialVersionUID = 1L;
private String phrase;//表情使用的替代文字
private String type;
private String url;//表情图片存放的位置
private String isHot;//是否为热门表情
private String isCommon;//是否属于通用
private String orderNumber;//该表情在系统中的排序号码
private String category;//表情分类
private String imageName;//表情名称
public String getImageName() {
return imageName;
}
public void setImageName(String imageName) {
this.imageName = imageName;
}
public String getPhrase() {
return phrase;
}
public void setPhrase(String phrase) {
this.phrase = phrase;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getIsHot() {
return isHot;
}
public void setIsHot(String isHot) {
this.isHot = isHot;
}
public String getIsCommon() {
return isCommon;
}
public void setIsCommon(String isCommon) {
this.isCommon = isCommon;
}
public String getOrderNumber() {
return orderNumber;
}
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}

 

3.2 储存在一个Emotion.java里。Emotion.java代码如下:

 

package com.uim.microblog.net.handler;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.uim.microblog.model.Emotions;
import com.uim.microblog.model.ResponseResult;
public class BlogEmotionsHandler extends DefaultHandler {
private List<Emotions> list;
private Emotions emotions;
private ResponseResult responseresult;
private String tag = null;//正在解析的元素
public List<Emotions> getEmotionsList(){
return list;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (tag != null) {
String textArea = new String(ch,start,length);
/**开始解析表情数据*/
if ("phrase".equals(tag)) {
emotions.setPhrase(textArea);
} else if ("type".equals(tag)) {
emotions.setType(textArea);
} else if ("url".equals(tag)) {
try {
emotions.setUrl(textArea);
String imageName = textArea.substring(textArea.lastIndexOf("/") + 1,textArea.length() - 4);
emotions.setImageName(imageName);
} catch (Exception e) {
e.printStackTrace();
}
} else if ("is_hot".equals(tag)) {
emotions.setIsHot(textArea);
} else if ("is_common".equals(tag)) {
emotions.setIsCommon(textArea);
} else if ("order_number".equals(tag)) {
emotions.setOrderNumber(textArea);
} else if ("category".equals(tag)) {
emotions.setCategory(textArea);
} else if ("retn".equals(tag)) {
responseresult.setRetn(textArea);
} else if ("desc".equals(tag)) {
responseresult.setDesc(textArea);
}
}
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
tag = null;
if ("mb".equals(localName)) {
} else if ("emotions".equals(localName)) {
responseresult =null;
} else if ("emotion".equals(localName)) {
list.add(emotions);
emotions = null;
} 
}
@Override
public void startDocument() throws SAXException {
list = new ArrayList<Emotions>();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if ("mb".equals(localName)) {
responseresult = new ResponseResult();
} else if ("emotions".equals(localName)) {
} else if ("emotion".equals(localName)) {
emotions = new Emotions();
} 
tag = localName;
}
}


3.4sax解析

public List<Emotions> getEmotion(){
BlogGetData getdata = new BlogGetData();
String result = getdata.blogEmotionsServlet();
try {
//生成SAX解析对象
parser = SAXParserFactory.newInstance().newSAXParser();
//生成xml读取器
reader = parser.getXMLReader();
BlogEmotionsHandler handler = new BlogEmotionsHandler();
//设置Handler
reader.setContentHandler(handler);
//指定文件,进行解析
reader.parse(new InputSource(new StringReader(result)));
//获取 List<Emotions>
emotionList = handler.getEmotionsList();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return emotionList;
}


4:

4.1实现表情选择器---GridView

 

<GridView
android:id="@+id/blog_sendmsg_gvemotion"
android:layout_width="fill_parent"
android:layout_height="150sp"
android:scrollbars="vertical"
android:numColumns="auto_fit"
android:verticalSpacing="15dp"
android:background="@color/blog_list_back"
android:stretchMode="columnWidth"
android:gravity="center"
android:visibility="gone"
android:columnWidth="40dp">
</GridView>


4.2 GridView的item-----gridview_emotion_item.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/blog_sendmsg_emotion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="50"
android:layout_gravity="center">
</ImageView>
</LinearLayout>

 4.3代码加载表情图片到GridView进行显示

 

public void addexpression(View view){
if (expressionGriView.getVisibility() == View.GONE) {
expressionGriView.setVisibility(View.VISIBLE);
emotionList = BlogHomeActivity.emotions;
ArrayList<HashMap<String, Object>> lstImageItem = new ArrayList<HashMap<String, Object>>();
for(int i=0;i<70;i++)  
{ 
emtions = emotionList.get(i);   
if (emtions != null) {
HashMap<String, Object> map = new HashMap<String, Object>();
Field f;
try {
f = (Field)R.drawable.class.getDeclaredField(emtions.getImageName());
int j = f.getInt(R.drawable.class);	
map.put("ItemImage", j);//添加图像资源的ID  
lstImageItem.add(map);  
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}  
}  
//生成适配器的ImageItem <====> 动态数组的元素,两者一一对应  
SimpleAdapter saImageItems = new SimpleAdapter(this, 
lstImageItem,//数据来源   
R.layout.blog_emotion_list,
//动态数组与ImageItem对应的子项          
new String[] {"ItemImage"},   
//ImageItem的XML文件里面的一个ImageView
new int[] {R.id.blog_sendmsg_emotion});  
expressionGriView.setAdapter(saImageItems);  
} else {
expressionGriView.setVisibility(View.GONE);
}
}


5:实现点击GridView的每一个item,处理根据item的index查找对应的表情code,然后再把code利用正则把code转换为相对应的表情图片,最后表情插入EditText进行发送

5.1:code转换为图片:

 

public SpannableString txtToImg(String content){
SpannableString ss = new SpannableString(content);
int starts = 0;
int end = 0;
if(content.indexOf("[", starts) != -1 && content.indexOf("]", end) != -1){
starts = content.indexOf("[", starts);
end = content.indexOf("]", end);
String phrase = content.substring(starts,end + 1);
String imageName = "";
List<Emotions> list = BlogHomeActivity.emotions;
for (Emotions emotions : list) {
if (emotions.getPhrase().equals(phrase)) {
imageName = emotions.getImageName();
}
}
try {
Field f = (Field)R.drawable.class.getDeclaredField(imageName);
int i= f.getInt(R.drawable.class);
Drawable drawable = BlogSendMsgActivity.this.getResources().getDrawable(i);  
if (drawable != null) {
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 
ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);  
ss.setSpan(span, starts,end + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
}
}
return ss;
}


 

5.2:插入EditText

emtions = emotionList.get(position);//获取表情bean
int cursor = etcontent.getSelectionStart();
etcontent.getText().insert(cursor, txtToImg(emtions.getPhrase()));


 

写完收工,给个效果图:


 

转自:http://jspjson.iteye.com/blog/1109222 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/31188.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

夸克两年SVIP试水

那就这样喽 以后不用了就是&#x1f644; 然后还有另外一个目的就是 影视资源可以直接上传&#xff0c;然后就可能不会那么卡 可是现在很多资源网站都有视频直链加密&#xff0c;你点击了云收藏他有很大几率是不会收藏成功的&#xff08;e.g.这个m3u8链接只有你这个IP才能用&a…

mix2 android 8.0,小米MIX2终于用上安卓8.0,米粉欢呼:MIUI9完美了

原标题&#xff1a;小米MIX2终于用上安卓8.0&#xff0c;米粉欢呼&#xff1a;MIUI9完美了 安卓8.0的系统出来啦&#xff01;部分小米用户已经可以用上了基于安卓8.0系统的MIUI9 7.12.18体验版&#xff0c;据说速度“快到飞起”&#xff01; 安卓8.0版本重点是提升了电池续航能…

Android模仿新浪微博(主页微博,评论界面)

主页微博&#xff1a; 获取当前登录用户及其所关注&#xff08;授权&#xff09;用户的最新微博接口&#xff1a;http://open.weibo.com/wiki/2/statuses/friends_timeline 代码详解&#xff1a; 1.异步get请求数据&#xff0c;由于数据中带图片&#xff0c;故需要多线程管理…

音视频技术开发周刊 | 291

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 谷歌将 AI 芯片团队并入云计算部门 追赶微软和亚马逊 OpenAI推出的ChatGPT获得一定成功&#xff0c;微软是OpenAI的重要投资者&#xff0c;它将ChatGPT植入必应搜索&#…

生成式AI年度观察 | 技术及产品快速迭代,生成内容质量及安全性仍需提升

原文链接&#xff1a; https://mp.weixin.qq.com/s/ED9mo5pxuDdyZmrFe-u7qw 一、2022年生成式AI发展观察 1.扩散模型和ChatGPT能力出众&#xff0c;多种生成模态涌现 扩散模型Diffusion&#xff08;以下简称“扩散模型”&#xff09;和神经网络模型CLIP结合&#xff0c;文生图实…

可信AI年度观察 | 生成式AI技术及产品快速迭代,生成内容质量及安全性仍需提升

自2021年起&#xff0c;生成式人工智能&#xff08;以下简称“生成式AI”&#xff09;连续两年入选Gartner《Hype Cycle for Artificial Intelligence》&#xff0c;被认为是未来重要的AI技术趋势。2022年以来&#xff0c;生成式AI产品不断涌现&#xff0c;生成内容模态多样&am…

孙燕姿谈“AI孙燕姿”:她的反应让人意外,深入体验揭示其背后的真相与潜力!

目录 前言AI歌手简介AI歌手的技术原理孙燕姿对“AI孙燕姿”的看法结论个人感受一、你听过AI歌手的音乐呈现吗&#xff1f;作为听众你的感受如何&#xff1f;二、你认为这种新型演艺模式能否获得广泛的市场认可&#xff1f;原因是什么&#xff1f;三、你认为AI歌手会取代流行歌手…

吞噬还是撬动?开发者如何应对大模型风暴?

责编 | 禾木木 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; ChatGPT 的出现几乎改变了 AI 的风向&#xff0c;各方大佬都丝毫不吝惜溢美之词&#xff0c;比尔盖茨说这种人工智能技术出现的重大意义&#xff0c;不亚于互联网和个人电脑的诞生&#xff1b;英伟达…

《花雕学AI》ChatGPT跟人类的思考方式有什么不同?

一、ChatGPT是一个基于GPT-3.5的对话语言模型&#xff0c;它可以根据用户的输入生成多轮对话&#xff0c;也可以生成文本、代码、音乐等内容。ChatGPT的思考方式是利用大量的数据和强大的算力来学习语言的联合概率分布&#xff0c;从而能够根据上下文和目标生成合理和有趣的回复…

跟着ChatGPT学PsychoPy编程1:绘制一个随按键而变化的进度条

让GPT帮忙绘制一个随按键而发生的进度条&#xff08;说的越详细越好&#xff09;&#xff1a; from psychopy import visual, event, core # 创建窗口 win visual.Window(size(800, 600), fullscrTrue) #True表示全屏 # 创建矩形框 rect visual.Rect(win, width0.1, height0.…

抖音服务器带宽有多大,才能供上亿人同时刷?

字节跳动有多少台服务器&#xff1f;字节跳动大型的数据中心出口带宽是多少&#xff1f; 最近看到一个有意思的提问&#xff1a;抖音服务器带宽有多大&#xff0c;为什么能够供那么多人同时刷&#xff1f;今天来给大家科普一下。 图片来自 Pexels 抖音&#xff0c;百度&#xf…

月报总结|Moonbeam 5月份大事一览

本月&#xff0c;Moonbeam迎来了Uniswap V3的部署&#xff0c;经过一年的社区讨论&#xff0c;UniSwap V3终于以5000万个同意票通过&#xff0c;将在未来一个月内部署于Moonbeam&#xff0c;为Web3用户提供更广泛公链生态的多链体验&#xff0c;加速应用之间跨链交互&#xff0…

月报总结|Moonbeam 4月份大事一览

本月&#xff0c;Moonbeam生态扶持进入下一里程碑&#xff01;探索更多优质的早期Web3项目&#xff0c;Moonbeam Accelerator Program已公布进入最终加速孵化阶段的10家初创公司&#xff0c;这些幸运项目将在未来3个月接受顶级孵化公司和专业投资机构的培训&#xff0c;于下半年…

惊人的算力成本背后,自动驾驶公司如何加速研发创新

【摘要】AI算法模型的开发&#xff0c;测试和训练是自动驾驶公司最重要的工作之一&#xff0c;它们都需要大量GPU算力来支撑。然而&#xff0c;“一人一卡”的简单独占式GPU分配方式会导致GPU分配率高但实际利用率低&#xff0c;造成大量算力的浪费。基于远程GPU的GPU池化技术能…

Flutter 中使用 OpenAI GPT-3 进行语义化处理

Flutter 中使用 OpenAI GPT-3 进行语义化处理 视频 https://www.bilibili.com/video/BV1AA411X7o3/ 前言 最近 openai 的 ChatGPT 火了&#xff0c;然后我也想着用它来做点什么&#xff0c;于是就写了个 调用 openai api 语言执行工具&#xff0c;跑个测试&#xff0c;以后再有…

谷歌云|机密 GKE 节点可在计算优化的 C2D 虚拟机上使用

机密 GKE 节点可用于计算优化的 C2D 虚拟机。 许多公司已采用 Google Kubernetes Engine (GKE) 作为其应用程序基础架构中的关键组件。在某些情况下&#xff0c;使用容器和 Kubernetes 的优势可以超越传统架构&#xff0c;但迁移到云端并在云端运行应用程序通常需要战略规划以降…

【打卡-Coggle竞赛学习2023年3月】对话意图识别

学习链接&#xff1a; https://coggle.club/blog/30days-of-ml-202303 ## Part1 内容介绍 本月竞赛学习将以对话意图识别展开&#xff0c;意图识别是指分析用户的核心需求&#xff0c;错误的识别几乎可以确定找不到能满足用户需求的内容&#xff0c;导致产生非常差的用户体验…

魔法咒语

魔法咒语 题目描述 Chandra 是一个魔法天才。从一岁时接受火之教会洗礼之后&#xff0c; Chandra 就显示出对火元素无与伦比的亲和力&#xff0c;轻而易举地学会种种晦涩难解的法术。这也多亏 Chandra 有着常人难以企及的语言天赋&#xff0c;让她能轻松流利地说出咒语中那些极…

网络舆情监测系统TOOM

在当今社会网络信息纷繁错杂&#xff0c;一条小小的舆情信息很可能引发异常舆情风暴&#xff0c;导致严重的舆情危机&#xff0c;而网络舆情监测系统能&#xff0c;更好地全面监测网络信息&#xff0c;未雨绸缪&#xff0c;精准把控&#xff0c;及时发现及时处理&#xff0c;为…

讯飞星火大模型V1.5发布 刘庆峰:我们要追赶OpenAI

雷递网 乐天 6月9日 讯飞星火认知大模型V1.5今日正式发布。讯飞称&#xff0c;时隔一月&#xff0c;星火大模型不仅各项能力获得持续提升&#xff0c;且在综合能力上实现三大升级&#xff1a;开放式知识问答取得突破&#xff0c;多轮对话、逻辑和数学能力再升级。星火APP同步发…