之前写过一个发帖界面,但是从来没有认真整理过,现在该写的写完了,好好整理下,不说废话,直接上效果图。(以下所有图片,全部来自百度贴吧客户端“借用”)

这个发帖界面主要实现功能包括,图片的上传,表情的实现。这篇我们先说表情功能的实现。

习惯性,从设计师那里拿到界面,先考虑布局,然后开始编写xml,如下面这个文件main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#FFFFFF"><RelativeLayout android:id="@+id/post_titlebar"android:layout_width="match_parent"android:layout_height="50dp"android:layout_alignParentTop="true"><TextView android:id="@+id/post_cancel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_alignParentLeft="true"android:layout_marginLeft="10dp"android:textSize="16sp"android:textColor="#FF00FF"android:text="取消"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textColor="#000000"android:textSize="18sp"android:text="发表帖子"/><TextView android:id="@+id/post_submit"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_alignParentRight="true"android:layout_marginRight="10dp"android:textSize="16sp"android:textColor="#FF00FF"android:text="发送"/></RelativeLayout><View android:id="@+id/post_topLine"android:layout_below="@id/post_titlebar"android:layout_width="match_parent"android:layout_height="1dp"android:background="#cdcdcd"/><EditText android:id="@+id/post_inputEdit"android:layout_below="@id/post_topLine"android:layout_width="match_parent"android:layout_height="100dp"android:maxLines="5"android:hint="说点什么吧"android:textSize="14sp"android:gravity="left|top"android:cursorVisible="true"android:background="@null"android:layout_marginLeft="10dp"android:layout_marginTop="10dp"android:layout_marginRight="10dp"android:textColor="#959595"/><FrameLayout android:id="@+id/post_imagePart"android:layout_below="@id/post_inputEdit"android:layout_marginTop="10dp"android:layout_marginLeft="10dp"android:layout_width="wrap_content"android:layout_height="wrap_content"><ImageView android:id="@+id/post_addPhoto"android:layout_width="100dp"android:layout_height="100dp"android:scaleType="fitXY"android:src="@drawable/add_photo"android:layout_marginRight="5dp"android:layout_marginTop="5dp"/><ImageView android:id="@+id/post_deletePhoto"android:layout_width="wrap_content"android:layout_height="wrap_content"android:scaleType="centerCrop"android:src="@drawable/delete_photo"android:layout_gravity="top|right"android:visibility="invisible"/></FrameLayout><LinearLayoutandroid:layout_alignParentBottom="true"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><View android:layout_width="match_parent"android:layout_height="1dp"android:background="#cdcdcd"/><ImageView android:id="@+id/post_addEmotion"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/add_emotion"android:layout_marginTop="5dp"android:layout_marginBottom="5dp"android:layout_marginLeft="10dp"android:scaleType="centerCrop"/><View android:layout_width="match_parent"android:layout_height="1dp"android:background="#cdcdcd"/><FrameLayout android:id="@+id/post_emotion_content"android:layout_width="match_parent"android:layout_height="150dp"android:layout_marginTop="5dp"android:visibility="gone"></FrameLayout></LinearLayout>
</RelativeLayout>

xml里面就这些东西,没什么好说的,只是这里我们的打算是,将表情界面当做一个Framgent来写。所以出现了一个id为post_emotion_content的FrameLayout,用来装载表情界面的Fragment。

xml编写完毕之后,接下来考虑我们的Fragment该如何编写,很明显表情界面整个是一个ViewPager,而在ViewPager的每个页面则是一个GridView,这样分析之下,整个界面的结构都出来了,编写代码轻而易举。

先看下emotion_main.xml的代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" ><android.support.v4.view.ViewPagerandroid:id="@+id/emotion_viewPager"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentTop="true"/><LinearLayout android:id="@+id/emotion_dotViewGroup"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_marginBottom="10dp"android:orientation="horizontal"android:layout_centerHorizontal="true"></LinearLayout></RelativeLayout>

这个xml里就只包括我们需要的ViewPager和一个dotViewGroup。从表面意思也可以看出,dotViewGroup就是下方的点,看过 上一篇博客的话,大家应该对ViewPager的布局甚至adapter都非常熟悉了,这里不做具体介绍了。

接下来我们看整个Fragment的内容,为了方便,我们直接将很多类都写成了内部类。具体看下EmotionFragment.java文件,如下:

package com.example.postdemo;import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.Selection;
import android.text.Spannable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;/*** * @author happy_fsyy* */public class EmotionFragment extends Fragment implements OnItemClickListener {/*** 表情界面的布局*/private View emotionMain;/*** 装载表情页面的viewPager*/private ViewPager emotionViewpager;/*** 表情滑动下方的小点布局*/private LinearLayout dotViewGroup;/*** 每个页面其实是一个GridView*/private GridView[] emotionGridViews;/*** 定义页面数量*/private int pageCount;/*** 小点*/private View[] dots;/*** 表情图片*/private int[] emotionImgs;/*** 表情文字*/private String[] emotionText;/*** 当前 被选中页面index*/private int currentIndex;private void initViews(){emotionMain=getActivity().getLayoutInflater().inflate(R.layout.emotion_main, null);emotionViewpager=(ViewPager)emotionMain.findViewById(R.id.emotion_viewPager);dotViewGroup=(LinearLayout)emotionMain.findViewById(R.id.emotion_dotViewGroup);}/*** 初始化viewPager*/private void initViewPager(){emotionImgs=new int[]{R.drawable.image_emoticon1,R.drawable.image_emoticon2,R.drawable.image_emoticon3,R.drawable.image_emoticon4,R.drawable.image_emoticon5,R.drawable.image_emoticon6,R.drawable.image_emoticon7,R.drawable.image_emoticon8,R.drawable.image_emoticon9,R.drawable.image_emoticon10,R.drawable.image_emoticon11,R.drawable.image_emoticon12,R.drawable.image_emoticon13,R.drawable.image_emoticon14,R.drawable.image_emoticon15,R.drawable.image_emoticon16,R.drawable.image_emoticon17,R.drawable.image_emoticon18,R.drawable.image_emoticon19,R.drawable.image_emoticon20,R.drawable.image_emoticon21,R.drawable.image_emoticon22,R.drawable.image_emoticon23,R.drawable.image_emoticon24,R.drawable.image_emoticon25,R.drawable.image_emoticon26,R.drawable.image_emoticon27,R.drawable.image_emoticon28,R.drawable.image_emoticon29,R.drawable.image_emoticon30,R.drawable.image_emoticon31,R.drawable.image_emoticon32,R.drawable.image_emoticon33};//这里的字符串可以任意更换emotionText=getActivity().getResources().getStringArray(R.array.emotion_texts);currentIndex=0;pageCount=emotionImgs.length/15+1;//每个页面15个表情emotionGridViews=new GridView[pageCount];dots=new View[pageCount];int i=0;//初始化每个页面的gridviewfor(i=0;i<pageCount;i++){emotionGridViews[i]=new GridView(getActivity());emotionGridViews[i].setStretchMode(GridView.STRETCH_COLUMN_WIDTH);emotionGridViews[i].setNumColumns(5);emotionGridViews[i].setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));emotionGridViews[i].setGravity(Gravity.CENTER);emotionGridViews[i].setAdapter(new GridViewAdapter(getActivity(), i));emotionGridViews[i].setOnItemClickListener(this);}for(i=0;i<pageCount;i++){dots[i]=new View(getActivity());LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(10, 10);lp.setMargins(10, 0, 10, 0);dots[i].setLayoutParams(lp);if(i!=currentIndex){dots[i].setBackgroundResource(R.drawable.dot_normal);}else{dots[i].setBackgroundResource(R.drawable.dot_focused);}dotViewGroup.addView(dots[i]);}emotionViewpager.setAdapter(new EmotionPagerAdapter());}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);initViews();initViewPager();emotionViewpager.setOnPageChangeListener(new OnPageChangeListener() {@Overridepublic void onPageSelected(int position) {currentIndex=position;for(int i=0;i<pageCount;i++){if(i==currentIndex){dots[i].setBackgroundResource(R.drawable.dot_focused);}else{dots[i].setBackgroundResource(R.drawable.dot_normal);}}}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int arg0) {}});}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return emotionMain;}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {EditText inputEditText=(EditText)getActivity().findViewById(R.id.post_inputEdit);EmotionParser parser=new EmotionParser(getActivity());String content=inputEditText.getText().append(emotionText[currentIndex*15+position]).toString();inputEditText.setText(parser.replace(content));Spannable text=(Spannable)inputEditText.getText();Selection.setSelection(text, text.length());}private class GridViewAdapter extends BaseAdapter{private Context context;//Contextprivate int pageIndex;//页面索引/*** @param context Context* @param pageIndex 第几页*/public GridViewAdapter(Context context,int pageIndex) {this.context=context;this.pageIndex=pageIndex;}@Overridepublic int getCount() {if(pageIndex<pageCount-1){return 15;}else{return emotionImgs.length%15;}}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ImageView view;if(convertView==null){view=new ImageView(context);view.setLayoutParams(new GridView.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));view.setScaleType(ImageView.ScaleType.CENTER_CROP);view.setPadding(8, 8, 8, 8);}else{view=(ImageView)convertView;}view.setImageResource(emotionImgs[pageIndex*15+position]);return view;}}private class EmotionPagerAdapter extends PagerAdapter{@Overridepublic int getCount() {return pageCount;}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0==arg1;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView(emotionGridViews[position]);}@Overridepublic Object instantiateItem(ViewGroup container, int position) {((ViewPager)container).addView(emotionGridViews[position]);return emotionGridViews[position];}}}

根据代码注释看起来应该没有任何问题了,具体的代码下载请看下一篇。

android表情功能开发相关推荐

  1. Android 表情功能的完整处理方案

    概述 1.原理和实现思路 2.表情图片显示 3.表情面板 4.表情的输入框插入和删除 5.表情添加脚本 Android中表情功能,一般都不是用ImageView去设置图片实现的, 表情一般会嵌套在文本 ...

  2. android 翻译功能开发,手把手教你开发Android studio翻译插件

    前言 由于我英语很烂,写代码的时候需要用英文命名,有些单词不知道,就只能切换到浏览器打开网页搜索,再拿到英文单词.这样每次都要切换出去,很麻烦,于是,就想着开发一个Android studio插件,在 ...

  3. android论坛功能开发教程,Android教程 如何免费生成论坛App

    介绍 按照快速集成文档,您可以很容易的把BBSSDK提供的功能集成到您的应用中,然后使用BBSSDK来做开发. 在集成前,您也可以先下载示例Sample的源码工程(包含应用内打开pdfoffice等格 ...

  4. android签到功能开发,Android应用开发之Android简单实现app每月签到功能

    本文将带你了解Android应用开发Android简单实现app每月签到功能,希望本文对大家学Android有所帮助. 本文实例为大家分享了Android实现app每月签到功能的具体代码,供大家参考, ...

  5. Android FTP功能开发基于swiftp

    需求描述 市面很多android文件管理器都有FTP文件管理功能,就是通过同一个WIFI把手机作为服务器,用其他的设备(电脑或手机)可以完成对本手机文件的访问. FTP介绍 ftp (文件传输协议) ...

  6. android签到功能开发,Android简单实现app每月签到功能

    本文实例为大家分享了Android实现app每月签到功能的具体代码,供大家参考,具体内容如下 先上一张效果图: 其中这些签到的效果图是在网上找的,然后重要用到的控件就是 GridvVew 了, 代码很 ...

  7. Android多媒体功能开发(11)——使用AudioRecord类录制音频

    AudioRecord类优点是能录制到缓冲区,能够实现边录边播(AudioRecord + AudioTrack)以及对音频的实时处理(如QQ电话).缺点是输出是PCM格式的原始采集数据,如果直接保存 ...

  8. Android多媒体功能开发(6)——使用MediaPlayer类播放音频

    Android播放音频资源主要有两个类:MediaPlayer和SoundPool. MediaPlayer用于实现对一个音频的播放控制,侧重于启动.停止.暂停.位置控制等操作.不支持同时播放多个音频 ...

  9. Android网络功能开发(4)——文件下载和上传

    本篇介绍使用HTTP协议实现文件下载和上传.在客户端和服务器的通信过程中,可能有些多媒体或数据文件需要下载或上传,可以通过HTTP协议实现. 首先看使用HTTP协议下载文件的原理:客户端发送一个HTT ...

  10. Android 表情功能实现,封装面板方便使用

    最近项目要修改表情布局,看着那个心碎啊,好几个页面都用到了表情面板,以前的哥们不耐其凡的复制了好几份,每次都一大堆代码,看着心里有些无奈的抓狂. 原理:表情底层数据传输其实就是一个特殊文本传输,通过文 ...

最新文章

  1. Asp.NET 获取网站根目录
  2. python【蓝桥杯vip练习题库】ADV-100第二大整数
  3. 边工作边刷题:70天一遍leetcode: day 98
  4. 32位oracle_oracle 性能调优
  5. 建德有没有计算机培训,建德计算机培训,建德计算机培训班,建德计算机培训完好找工作吗 - IT教育频道...
  6. 【转】.NET Core 可移植类库PCL Portable Class Library详解
  7. 使用 jQuery Mobile 与 HTML5 开发 Web App (十) —— jQuery Mobile 默认配置与事件基础
  8. HTML页面在IOS上出现卡顿的解决方案(overflow:scroll)
  9. WPF 如何在代码中使用自定义的鼠标资源
  10. java 下载文件大小_如何在浏览器中显示使用角度5下载的文件的文件大小?
  11. PL/SQL Developer-官网下载地址
  12. 可信执行环境 TEE分类
  13. 《JavaScript忍者秘籍》——2.4 测试套件基础知识
  14. docker hub上镜像手动下载_Docker 下载镜像
  15. QDir setSorting 文件排序
  16. python信噪比signaltonoise, SNR
  17. elasticsearch使用中文拼音混合搜索的痛点解决
  18. 有点恐怖,这个工具能让你在 20 秒内,克隆你的声音,并转成英语!
  19. 33岁跳槽无路,濒临绝望之际受贵人指点,成功上岸阿里(Java岗)
  20. 【C++入门】静态成员详解(定义、实现原理、使用注意事项)

热门文章

  1. wow插件实现优雅的动画页面
  2. 什么是网点?印刷网点与CMYK色彩,彩色渐变色印刷原理。
  3. windows 7 专业版 64位 无法安装.Net 4.7版本解决方案
  4. App上架安卓应用市场最全指南
  5. 机器人三大定律只是人类的一厢情愿 AI可能并不遵守
  6. Netflix Conductor流程系统(二):官方样例搭建
  7. 项目经理面试必备20题
  8. python实现AES加密解密
  9. 最大堆(创建、删除、插入和堆排序)图文详解
  10. java正则表达式是什么6_进阶Java编程(6)正则表达式