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
原创粉丝点击