Android 模仿手机QQ表情输入和表情预览框
来源:互联网 发布:当当网的网络广告宣传 编辑:程序博客网 时间:2024/04/29 15:02
闲来无事花了一点空暇时间写了一个模仿Android版手机QQ的表情输入框
效果图如下
- 一:布局
- 二:录入填充表情
- 三:监听表情的适配器的触摸监听显示出预览框
实现步骤
一 、布局
我是自己自定一个ExpressionGridView(RelativeLayout)只是集成了这些方法的一个自定义View而已
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.TextInputLayout android:id="@+id/expression_text_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.design.widget.TextInputLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="223dp" android:layout_alignParentBottom="true"> <view.ExpressionGridView android:id="@+id/expression_gridview" android:layout_width="fill_parent" android:layout_height="123dp" android:layout_alignParentBottom="true" /> <RelativeLayout android:id="@+id/face_view" android:layout_width="80dp" android:layout_height="80dp" android:background="#78072026" android:visibility="gone"> <!-- 预览框--> <ImageView android:id="@+id/face_img" android:layout_width="30dp" android:layout_height="30dp" android:layout_centerInParent="true" /> </RelativeLayout> </RelativeLayout></RelativeLayout>
二、录入填充表情
下载QQ解压出里面的资源文件获取表情包统一命名规范后定义 因为这些是我以前做个类似软件的时候使用了的现成资源拿来用
定义好的表情
package view;import anroid.qq_expression.shallcheek.shallcheek_qq_expression.R;/** * 表情文件 * * @author shallcheek * @version 1.0 */public class Expressions { public static Integer[] expressionImgs = new Integer[]{R.drawable.f001, R.drawable.f002, R.drawable.f003, R.drawable.f004, R.drawable.f005, R.drawable.f006, R.drawable.f007, R.drawable.f008, R.drawable.f009, R.drawable.f010, R.drawable.f011, R.drawable.f012, R.drawable.f013, R.drawable.f014, R.drawable.f015, R.drawable.f016, R.drawable.f017, R.drawable.f018, R.drawable.f019, R.drawable.f020, R.drawable.f021, R.drawable.f022, R.drawable.f023}; /** * 本地表情的名 */ public static String[] expressionImgNames = new String[]{"[f001]", "[f002]", "[f003]", "[f004]", "[f005]", "[f006]", "[f007]", "[f008]", "[f009]", "[f010]", "[f011]", "[f012]", "[f013]", "[f014]", "[f015]", "[f016]", "[f017]", "[f018]", "[f019]", "[f020]", "[f021]", "[f022]", "[f023]"}; public static Integer[] expressionImgs1 = new Integer[]{R.drawable.f024, R.drawable.f025, R.drawable.f026, R.drawable.f027, R.drawable.f028, R.drawable.f029, R.drawable.f030, R.drawable.f031, R.drawable.f032, R.drawable.f033, R.drawable.f034, R.drawable.f035, R.drawable.f036, R.drawable.f037, R.drawable.f038, R.drawable.f039, R.drawable.f040, R.drawable.f041, R.drawable.f042, R.drawable.f043, R.drawable.f044, R.drawable.f045, R.drawable.f046}; /** * 本地表情的名 */ public static String[] expressionImgNames1 = new String[]{"[f024]", "[f025]", "[f026]", "[f027]", "[f028]", "[f029]", "[f030]", "[f031]", "[f032]", "[f033]", "[f034]", "[f035]", "[f036]", "[f037]", "[f038]", "[f039]", "[f040]", "[f041]", "[f042]", "[f043]", "[f044]", "[f045]", "[f046]"}; public static Integer[] expressionImgs2 = new Integer[]{R.drawable.f047, R.drawable.f048, R.drawable.f049, R.drawable.f050, R.drawable.f051, R.drawable.f052, R.drawable.f053, R.drawable.f054, R.drawable.f055, R.drawable.f056, R.drawable.f057, R.drawable.f058, R.drawable.f059, R.drawable.f060, R.drawable.f061, R.drawable.f062, R.drawable.f063, R.drawable.f064, R.drawable.f065, R.drawable.f066, R.drawable.f067, R.drawable.f068, R.drawable.f069}; /** * 本地表情的名 */ public static String[] expressionImgNames2 = new String[]{"[f047]", "[f048]", "[f049]", "[f050]", "[f051]", "[f052]", "[f053]", "[f054]", "[f055]", "[f056]", "[f057]", "[f058]", "[f059]", "[f060]", "[f061]", "[f062]", "[f063]", "[f064]", "[f065]", "[f066]", "[f067]", "[f068]", "[f069]"}; public static Integer[] expressionImgs3 = new Integer[]{R.drawable.f070, R.drawable.f071, R.drawable.f072, R.drawable.f073, R.drawable.f074, R.drawable.f075, R.drawable.f076, R.drawable.f077, R.drawable.f078, R.drawable.f079, R.drawable.f080, R.drawable.f081, R.drawable.f082, R.drawable.f083, R.drawable.f084, R.drawable.f085, R.drawable.f086, R.drawable.f087, R.drawable.f088, R.drawable.f089, R.drawable.f090, R.drawable.f091, R.drawable.f092}; /** * 本地表情的名 */ public static String[] expressionImgNames3 = new String[]{"[f070]", "[f071]", "[f072]", "[f073]", "[f074]", "[f075]", "[f076]", "[f077]", "[f078]", "[f079]", "[f080]", "[f081]", "[f082]", "[f083]", "[f084]", "[f085]", "[f086]", "[f087]", "[f088]", "[f089]", "[f090]", "[f091]", "[f092]"}; public static Integer[] expressionImgs4 = new Integer[]{R.drawable.f093, R.drawable.f094, R.drawable.f095, R.drawable.f096, R.drawable.f097, R.drawable.f098, R.drawable.f099, R.drawable.f100, R.drawable.f101, R.drawable.f102, R.drawable.f103, R.drawable.f104, R.drawable.f105, R.drawable.f106, R.drawable.f107, R.drawable.f108, R.drawable.f109, R.drawable.f110, R.drawable.f111, R.drawable.f112, R.drawable.f113, R.drawable.f114, R.drawable.f115}; /** * 本地表情的名 */ public static String[] expressionImgNames4 = new String[]{"[f093]", "[f094]", "[f095]", "[f096]", "[f097]", "[f098]", "[f099]", "[f100]", "[f101]", "[f102]", "[f103]", "[f104]", "[f105]", "[f106]", "[f107]", "[f108]", "[f109]", "[f110]", "[f111]", "[f112]", "[f113]", "[f114]", "[f115]"}; /** * 在存入数据库时,将表情名字进行替换即 */ public static String[] replaceStrings(String[] str, String[] str2) { String newStr[] = new String[str.length - 1]; for (Integer i = 0; i < str.length; i++) { newStr[i] = str[i].replace(str[i], str2[i]); } return newStr; }}
定义好一个mode 将弄成数组制作填充进去
List<ExpressionMode> expressionUtils = new ArrayList<>(); List<Integer> imgs = new ArrayList<>(); imgs.addAll(Arrays.<Integer>asList(Expressions.expressionImgs)); imgs.addAll(Arrays.<Integer>asList(Expressions.expressionImgs1)); imgs.addAll(Arrays.<Integer>asList(Expressions.expressionImgs2)); imgs.addAll(Arrays.<Integer>asList(Expressions.expressionImgs3)); imgs.addAll(Arrays.<Integer>asList(Expressions.expressionImgs4)); List<String> nams = new ArrayList<>(); nams.addAll(Arrays.asList(Expressions.expressionImgNames)); nams.addAll(Arrays.asList(Expressions.expressionImgNames1)); nams.addAll(Arrays.asList(Expressions.expressionImgNames2)); nams.addAll(Arrays.asList(Expressions.expressionImgNames3)); nams.addAll(Arrays.asList(Expressions.expressionImgNames4)); for (int i = 0; i < imgs.size(); i++) { ExpressionMode expressionMode = new ExpressionMode(); expressionMode.setValue(nams.get(i)); expressionMode.setResources(imgs.get(i)); expressionUtils.add(expressionMode); }
ExpressionMode.java
/** * Created by Shall on 2015.9.11. */public class ExpressionMode { private int resources; private int resourcesgif; private String value; public int getResources() { return resources; } public void setResources(int resources) { this.resources = resources; } public int getResourcesgif() { return resourcesgif; } public void setResourcesgif(int resourcesgif) { this.resourcesgif = resourcesgif; } public String getValue() { return value; } public void setValue(String value) { this.value = value; }}
自定义View ExpressionGridView 里面集成了ViewPage 使用GridView填充表情
public void setExpressionModes(List<ExpressionMode> expressionModes) { this.expressionModes = expressionModes; page = expressionModes.size() / (PAGE_MAX_NUMBER) + 1; expressionGridViewList = new ArrayList<>(); for (int i = 0; i < page; i++) { final GridView gridView = (GridView) View.inflate(getContext(), R.layout.gridview, null); List<ExpressionMode> list = this.expressionModes.subList(PAGE_MAX_NUMBER * i, PAGE_MAX_NUMBER * (i + 1) > expressionModes.size() ? expressionModes.size() - 1 : PAGE_MAX_NUMBER * (i + 1)); lists.add(list); if (i == 0) { this.list = list; } final ExpressionAdapter expressionAdatper = new ExpressionAdapter(list, getContext()); gridView.setAdapter(expressionAdatper); gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { expressionViewPager.setScanScroll(true);//屏蔽ViewPage滑动事件 isMove = true; setSelect(choose); return false; } }); gridView.setOnTouchListener(this); gridView.setOnItemClickListener(this); expressionGridViewList.add(gridView); } expressionViewPager = (ExpressionViewPager) View.inflate(getContext(), R.layout.viewpage, null); addView(expressionViewPager); PagerAdapter mPagerAdapter = new PagerAdapter() { @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public int getCount() { return expressionGridViewList.size(); } @Override public void destroyItem(View container, int position, Object object) { ((ViewPager) container).removeView(expressionGridViewList.get(position)); } @Override public Object instantiateItem(View container, int position) { ((ViewPager) container).addView(expressionGridViewList.get(position)); return expressionGridViewList.get(position); } }; expressionViewPager.setAdapter(mPagerAdapter); expressionViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {// relativeLayout.setVisibility(GONE);// imageView.setVisibility(View.GONE); } @Override public void onPageSelected(int position) { list = lists.get(position); } @Override public void onPageScrollStateChanged(int state) { } }); }
表情的插入根据OnItemClickListener 的点击获取到点击的mode 填充到输入框
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ExpressionAdapter expressionAdapter = (ExpressionAdapter) parent.getAdapter(); ExpressionMode expressionMode = (ExpressionMode) expressionAdapter.getItem(position); ExpressionUtil.installExpression(getContext(), editText, expressionMode); }
实现代码
/** * 插入表情 */ public static void installExpression(Context mCon, EditText mEditTextContent, ExpressionMode expressionMode) { Bitmap bitmap = BitmapFactory.decodeResource(mCon.getResources(), expressionMode.getResources()); bitmap = Bitmap.createScaledBitmap(bitmap, dip2px(30, mCon), dip2px(30, mCon), true); ImageSpan imageSpan = new ImageSpan(mCon, bitmap); SpannableString spannableString = new SpannableString(expressionMode.getValue().substring(1, expressionMode.getValue().length() - 1)); spannableString.setSpan(imageSpan, 0, expressionMode.getValue().length() - 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); mEditTextContent.getText().insert(mEditTextContent.getSelectionStart(), spannableString); }
三、滑动监听探出预览框
获取到到View的滑动X,Y左边计算出滑动的item 并展示出来预览框
//首先需要长按时间完成之后才处理监听事件 屏蔽ViewPage的事件监听 gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { expressionViewPager.setScanScroll(true);//屏蔽ViewPage滑动事件 isMove = true; setSelect(choose); return false; } }); gridView.setOnTouchListener(this);
触摸事件的处理
@Override public boolean onTouch(View v, MotionEvent event) { final int action = event.getAction(); final float x = event.getX(); final float y = event.getY(); Log.e("12","x:"+x+"y:"+y); int heighnum = (int) (y / (v.getHeight() / VERTICAL_NUMBER)); int widthnum = (int) (x / (v.getWidth() / TRANSVERSE_NUMBER)); //超出View 范围 if (heighnum <= 0) heighnum = 0; if (heighnum >= VERTICAL_NUMBER) heighnum = VERTICAL_NUMBER - 1; if (widthnum <= 0) widthnum = 0; if (widthnum >= TRANSVERSE_NUMBER) widthnum = TRANSVERSE_NUMBER - 1; //没有填充满 int listSize = list.size(); if (heighnum >= listSize / TRANSVERSE_NUMBER && widthnum >= listSize % TRANSVERSE_NUMBER) { widthnum = listSize % TRANSVERSE_NUMBER; heighnum = listSize / TRANSVERSE_NUMBER; heighnum--; } final int c = (heighnum) * TRANSVERSE_NUMBER + widthnum; choose = c; if (choose >= listSize) choose = listSize - 1;//需要减1 不要越界 switch (action) { case MotionEvent.ACTION_UP: choose = -1;// expressionViewPager.setScanScroll(false); isMove = false; relativeLayout.setVisibility(GONE); imageView.setVisibility(View.GONE); break; default: if (isMove) setSelect(choose); break; } return false; }
ViewPage监听处理
public class ExpressionViewPager extends ViewPager { private boolean isCanScroll = false; public ExpressionViewPager(Context context) { super(context); } public ExpressionViewPager(Context context, AttributeSet attrs) { super(context, attrs); } public void setScanScroll(boolean isCanScroll) { this.isCanScroll = isCanScroll; } @Override protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { if (v instanceof ViewPager) { return isCanScroll; } return super.canScroll(v, checkV, dx, x, y); } @Override public void scrollTo(int x, int y) { super.scrollTo(x, y); }}
imageView.setVisibility(View.VISIBLE); relativeLayout.setVisibility(VISIBLE); int w = choose % TRANSVERSE_NUMBER; int h = choose / TRANSVERSE_NUMBER; //设置弹出框的大小个位置 View v = expressionGridViewList.get(0); RelativeLayout.LayoutParams layoutParams = new LayoutParams((v.getWidth() / TRANSVERSE_NUMBER), (v.getWidth() / TRANSVERSE_NUMBER)); layoutParams.setMargins(w * (v.getWidth() / TRANSVERSE_NUMBER), (h) * (v.getHeight() / VERTICAL_NUMBER) - 30 + v.getHeight() / VERTICAL_NUMBER, 0, 0); relativeLayout.setLayoutParams(layoutParams); imageView.setBackgroundResource(list.get(choose > list.size() ? list.size() : select).getResources());
介绍的简单凑合着看吧 不懂可以留言可以加我微信 shallcheek
开发环境Android Studio
下载地址
0 0
- Android 模仿手机QQ表情输入和表情预览框
- 模仿QQ、微信表情输入框
- 仿qq表情输入框
- 类似android手机QQ表情实现
- android Emoji表情输入,输入表情和输入法表情输入相同
- 像QQ一样输入表情
- QQ聊天 代码 输入表情
- android 输入表情icon
- android开发表情输入
- Android开发技巧之像QQ一样输入文字和表情图像
- Android开发技巧:像QQ一样输入表情图像
- Android开发技巧:像QQ一样输入表情图像
- Android开发技巧:像QQ一样输入表情图像
- Android开发技巧:像QQ一样输入表情图像
- Android开发技巧:像QQ一样输入表情图像
- Android开发技巧:像QQ一样输入表情图像
- Android开发技巧:像QQ一样输入表情图像
- Android开发(28)--EditText实现输入QQ表情图像
- 原子操作与混杂设备
- Linux内核工程导论——网络:内核特性
- 矩阵计算工具——Eigen的简单用法
- Linux 文件系统(三)---dup和fork函数执行后的文件情况 http://blog.csdn.net/shanshanpt/article/details/39049579
- 什么是黑盒测试法?它的常用方法有哪些?
- Android 模仿手机QQ表情输入和表情预览框
- 音频的播放、简单音乐播放器
- 使用Python实现Hadoop MapReduce程序
- MARK一下,nodejs 使用session
- 设置前面板对象的Tab键顺序
- 软件常用语
- Adapter适配器模式
- C/C++重要知识点总结
- 项目11.5 坐标转换