Android 模仿手机QQ表情输入和表情预览框

闲来无事花了一点空暇时间写了一个模仿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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值