基于socket的可发送表情简单即时通讯

来源:互联网 发布:淘宝主店怎么绑定分店 编辑:程序博客网 时间:2024/04/27 15:46

前言

这段时间做的东西比较杂,但是对学习来说还是很有帮助的,这次做的基于socket的即时通讯也是为了更加了解IM,本来是打算使用openfire或者apollo服务器来实现的,但是中途时间上的问题,临时改了需求,后期的语音通话还是要借助第三方服务器的,这里主要是自己用myeclipse写了一个简单的代理服务器,主要是将客户端发来的消息转发到已经保存到链表中的socket中,实现比较简单,主要是解决发送图片的模块,我参考了很多文章,但是大多写的都不是很全,故自己写了一下,[socket即时通讯源码](https://github.com/firesmog/MyGreenDao),写这篇博客,一是为了记录自己的学习进度,而是希望能给正在学习路上的各位同学一点点帮助。

服务端介绍

这里的服务端是采用myeclipse写的,比较简单单,主要负责将任意客户端传过来的消息的进行转发,然后使得客户端收到信息后能在自己的界面上进行展示,具体代码如下,仅供参考。

public class tcpservice {    private static final int SERVERPORT = 8090;     private static List<Socket> mClientList = new ArrayList<Socket>();     private ExecutorService mExecutorService;      private ServerSocket mServerSocket;      public static void main(String[] args) {        new tcpservice();    }    public tcpservice() {        try {            //服务端套接字,这里给定客户端要连接的目标端口即可                    mServerSocket = new ServerSocket(SERVERPORT);               //使用线程池,来一个客户端,开一个线程处理                  mExecutorService = Executors.newCachedThreadPool();            System.out.println("start...");            Socket client = null;            while (true) {                //监听客户端的连接,一旦客户端连接上,则将客户端套接字赋值给client                          client = mServerSocket.accept();            //在链表中保存客户端,以便后面的消息转发                mClientList.add(client);                System.out.println(client.toString());           //开启线程                mExecutorService.execute(new ThreadServer(client));            }        }        catch (IOException e) {            e.printStackTrace();        }    }       //新建自己的线程类,实现线程内run方法的实现    static class ThreadServer implements Runnable {        private Socket            mSocket;        private BufferedReader    mBufferedReader;        private PrintWriter        mPrintWriter;        private String            mStrMSG;        //构造方法,将客户端套接字socket传进来        public ThreadServer(Socket socket) throws IOException {            this.mSocket = socket;         //获得客户端输入流,用于读取客户端数据            mBufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));            mStrMSG = "user:"+this.mSocket.getInetAddress()+" come total:" + mClientList.size();        }        //run方法的实现        public void run() {            try {            //判断客户端发送过来的信息是否是要退出聊天                              while ((mStrMSG = mBufferedReader.readLine()) != null) {                    if (mStrMSG.trim().equals("exit")) {                                            mClientList.remove(mSocket);                        mBufferedReader.close();                        mPrintWriter.close();                        mStrMSG = "user:"+this.mSocket.getInetAddress()+" exit total:" + mClientList.size();                        mSocket.close();                        sendMessage();                        break;                    }                    else {                       // mStrMSG = mSocket.getInetAddress() + ":" + mStrMSG;                        System.out.println( mStrMSG);                        sendMessage();                    }                }            }            catch (IOException e) {                e.printStackTrace();            }        }        private void sendMessage() throws IOException {                  System.out.println(mStrMSG);             //遍历所有的客户端套接字,将消息转发出去            for (Socket client : mClientList) {                             mPrintWriter = new PrintWriter(client.getOutputStream(), true);                mPrintWriter.println(mStrMSG);                mPrintWriter.flush();            }        }    }}

服务端就介绍到,这里,因为实现比较简单,所以也不多做赘述。

客户端介绍

这里的客户端实在Androidstudio上实现的,逻辑不难,主要是界面上的操作,大家可以参考一下。这里先贴出界面图,比较丑陋,大家见谅。
模仿QQ主界面发送图片

主界面主要采用的ViewPger+Recycleview,发送表情主要是采用Recycleview+girdView+EditText,,下面写给出主界面布局,以及聊天界面布局,大家仅参考,具体内容,数据资源都在源码中,大家自行下载。

//主界面<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"    android:layout_width="match_parent" android:layout_height="match_parent"    android:orientation="vertical"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="example.com.myapplication.MainActivity">   <example.com.myapplication.MyViewPager.MyViewPager        android:id="@+id/vp_main"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1" >        android:persistentDrawingCache="animation"    </example.com.myapplication.MyViewPager.MyViewPager>    <RadioGroup        android:id="@+id/rd_group"        android:layout_width="match_parent"        android:layout_height="90dp"        android:layout_alignParentBottom="true"        android:orientation="horizontal">        <RadioButton            android:id="@+id/rd_1"            style="@style/tab_menu_item"            android:drawableTop="@drawable/message"            android:text="消息"/>        <RadioButton            android:id="@+id/rd_2"            style="@style/tab_menu_item"            android:drawableTop="@drawable/contactor"            android:text="联系人"/>        <RadioButton            android:id="@+id/rd_3"            style="@style/tab_menu_item"            android:drawableTop="@drawable/statues"            android:text="动态"/>    </RadioGroup></LinearLayout>
//聊天界面<LinearLayout 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"    tools:context=".MainActivity"    android:orientation="vertical"    >    <android.support.v7.widget.RecyclerView        android:id="@+id/msg_recyclerView"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1">    </android.support.v7.widget.RecyclerView>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="60dp"        android:orientation="horizontal"        >        <ImageView            android:id="@+id/iv_motion"            android:onClick="true"            android:layout_marginLeft="10dp"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:background="@drawable/chat_icon"/>        <EditText            android:onClick="true"            android:id="@+id/input_text"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:hint="Type something here"            android:maxLines="2"/>        <Button            android:layout_marginLeft="20dp"            android:id="@+id/btnsend"            android:layout_width="80dp"            android:layout_height="50dp"            android:layout_marginTop="10dp"            android:text="发送"            android:textSize="20dp"/>    </LinearLayout>    <android.support.v4.view.ViewPager        android:paddingTop="5dp"        android:id="@+id/vp_motion"        android:layout_width="match_parent"        android:layout_height="150dp"        android:visibility="gone">    </android.support.v4.view.ViewPager></LinearLayout>

聊天界面当中的girdview是为了展示图片内容的,在初始的时候采用Gone将其隐藏起来,点击的时候将其设置为Visable展示出来,这里要注意的是图片的显示与软键盘弹出来的冲突,具体完全解决问题的做法,本人还没做好,在本demo中只是做了点强制的切换,隐藏,使得在软键盘和图片展示界面切换的时候有点卡顿,大家感兴趣的自己解决一下,解决好了的可以教一下我,谢谢。这里顺便说一下,主界面中使用了MyViewPger是自定义的viewpager主要目的,其实是我自己之前做仿qq的Recycleview的侧滑删除Item操作时,测试事件分发机制用的,感兴趣的同学可以自行添加事件分发方法,打log查看一下事件分发顺序。这里已经有点偏离话题,大家勿怪。

MyViewPger代码如下:

package example.com.myapplication.MyViewPager;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
/**
* Created by firesmog on 2017/2/22.
*/
public class MyViewPager extends ViewPager {
private boolean noScroll = false;
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyViewPager(Context context) {
super(context);
}
public void setNoScroll(boolean noScroll) {
this.noScroll = noScroll;
}
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
}
//下面内容其实是为了测试事假分发,其实有点绕,一段时间不做,就会有点生疏
@Override
public boolean onTouchEvent(MotionEvent arg0) {
/* return false;//super.onTouchEvent(arg0); */
Log.i(MyViewPager.class.getSimpleName(), ” onTouchEvent” + ” event = ” + arg0);
if (noScroll){
return false;
}
else
return true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev){
Log.i(MyViewPager.class.getSimpleName(), ” dispatchTouchEvent” + ” event = ” + ev + ” noScroll = ” + noScroll);
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
Log.i(MyViewPager.class.getSimpleName(), ” onInterceptTouchEvent” + ” event = ” + arg0);
if (noScroll) {
return false;
}
else
return super.onInterceptTouchEvent(arg0);
}
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
super.setCurrentItem(item, smoothScroll);
}
@Override
public void setCurrentItem(int item) {
super.setCurrentItem(item);
}
}
到了这里的话,就需要给girdview,Recycleview等添加适配器了,这两个适配器在写的时候注意的地方有很多,我也是参考了别人的代码,做了修改,时间有点久,不记得是谁的博客了,见谅。首先需要展示图片,所以列出girdview的adapter。代码如下所示。

package example.com.myapplication.Adapter;import android.content.Context;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;import example.com.myapplication.Bean.HeaderViewBean;import example.com.myapplication.R;/** * Created by firesmog on 2017/3/3. */public class GridViewAdapter extends BaseAdapter {    private List<HeaderViewBean> mDatas;    private LayoutInflater mLayoutInflater;    private Context context;    private int columnWidth;    /**     * 页数下标,从0开始     */    private int mIndex;    /**     * 每页显示最大条目个数 ,默认是dimes.xml里 HomePageHeaderColumn 属性值的两倍     */    private int mPageSize;    /**     * @param context 上下文     * @param mDatas 传递的数据     * @param columnWidth     * @param mIndex 页码     */    public GridViewAdapter(Context context, List<HeaderViewBean> mDatas, int columnWidth, int mIndex) {        this.context = context;        this.mDatas = mDatas;        mLayoutInflater = LayoutInflater.from(context);        this.mIndex = mIndex;        mPageSize =28;        this.columnWidth= columnWidth;    }    public GridViewAdapter(Context context, List<HeaderViewBean> mDatas, int index) {        this.context = context;        this.mDatas = mDatas;        mLayoutInflater = LayoutInflater.from(context);        this.mIndex = index;        mPageSize =28;    }    /**     * 先判断数据集的大小是否足够显示满本页?mDatas.size() > (mIndex+1)*mPageSize,     * 如果够,则直接返回每一页显示的最大条目个数mPageSize,     * 如果不够,则有几项返回几,(mDatas.size() - mIndex * mPageSize);     */    @Override    public int getCount() {        return mDatas.size() > (mIndex + 1) * mPageSize ? mPageSize : (mDatas.size() - mIndex * mPageSize);    }    @Override    public Object getItem(int position) {        return mDatas.get(position + mIndex * mPageSize);    }    @Override    public long getItemId(int position) {        return position + mIndex * mPageSize;    }    @Override    public View getView(final int position, View convertView, ViewGroup parent) {        Log.i("TAG", "position:" + position);        ViewHolder vh = null;        if (convertView == null) {            convertView = mLayoutInflater.inflate(R.layout.item_gird, parent, false);            vh = new ViewHolder();            vh.iv = (ImageView) convertView.findViewById(R.id.id_iv_icon);            convertView.setTag(vh);        } else {            vh = (ViewHolder) convertView.getTag();        }        /**         * 在给View绑定显示的数据时,计算正确的position = position + mIndex * mPageSize,         */        int pos = position + mIndex * mPageSize;        vh.iv.setImageResource(mDatas.get(pos).iconRes);        return convertView;    }    class ViewHolder {        public TextView tv;        public ImageView iv;    }}

有了展示图片的adapter的界面后,主要就是聊天对话框的dapter,代码如下:

package example.com.myapplication.Adapter;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.TextView;import java.util.List;import example.com.myapplication.Bean.Msg;import example.com.myapplication.R;/** * Created by firesmog on 2017/3/3. */public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder>{    List<Msg> msgList;    @Override    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)    {        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycly, parent, false);        return new ViewHolder(view);    }    @Override    public void onBindViewHolder(ViewHolder holder, int position)    {        Msg msg = msgList.get(position);        if (msg.getType() == Msg.TYPE_RECEIVE)        {            holder.leftLayout.setVisibility(View.VISIBLE);            holder.rightLayout.setVisibility(View.GONE);            holder.leftMsg.setText(msg.getContent());        } else if (msg.getType() == Msg.TYPE_SEND)        {            holder.rightLayout.setVisibility(View.VISIBLE);            holder.leftLayout.setVisibility(View.GONE);            holder.rightMsg.setText(msg.getContent());        }    }    public MsgAdapter(List<Msg> msgs)    {        this.msgList = msgs;    }    @Override    public int getItemCount()    {        return msgList.size();    }    static class ViewHolder extends RecyclerView.ViewHolder    {        LinearLayout leftLayout;        LinearLayout rightLayout;        TextView leftMsg;        TextView rightMsg;        ViewHolder(View view)        {            super(view);            //这里要分为左边对话框            leftLayout = (LinearLayout) view.findViewById(R.id.left_layout);             //这里要分为右边对话框            rightLayout = (LinearLayout) view.findViewById(R.id.right_layout);            //这里要分为左边消息            leftMsg = (TextView) view.findViewById(R.id.left_msg);            //这里要分为右边消息            rightMsg = (TextView) view.findViewById(R.id.right_msg);        }    }}

最后这里附上聊天Activity的代码,中间主要实现了socket连接、发送,在输入图片是,对图片的转换,这
里的将图片显示在编辑框中方法也写在了该activity中,接收服务器的图片再经过转化后才能在对话框中将图
片显示出来,这里注意,获取到的图片内容,并不是图片本身,而是用一个与图片资源对应的字符串数组来
替代图片,但是编辑框和对话框并不能通过string将图片展示出来,需要将之先转化为spannerString,但是
我们最好收到服务器的图片显示的时候,使用handler传输时,进行传值时,必须用CharSequence而不是
String ,说的乱七八糟,具体大家看代码吧。**关键点就是编辑框、对话框不能直接显示图片,它们只能显示
String,所以要将图片先转化对应的SpannerString传到对话框中才能显示,这是个人笨拙的简易理解,应
该有错误**

public class ChatActivity extends AppCompatActivity implements View.OnClickListener {    private ViewPager mViewPager;    private List<View> mViewPagerGridList;    private static final String SERVERIP = "172.28.12.130";    private static final int SERVERPORT = 8090;    private Thread mThread = null;    private Socket mSocket = null;    private BufferedReader mBufferedReader = null;    private PrintWriter mPrintWriter = null;    private static String mStrMSG = "";    private static String TAG = "TCP";    private List<Msg> msgList = new ArrayList<>();    private EditText inputText;    private  ImageView iv_motion;    private Boolean IsShow=false;    private ViewPager vp_motion;    private List<HeaderViewBean> mDatas = new ArrayList<>();    private  Button btnSend;    private Button btLogin;    private RecyclerView recyclerView;    private MsgAdapter adapter;    private int[] drawable;    private TextView tv_Show;    private  boolean IsSend=false;    private String[] faceScr;    private  Pattern pattern;    private HashMap<String, Integer> faceBook;    private Handler handler = new Handler() {        // 该方法运行在主线程中        // 接收到handler发送的消息,对UI进行操作        @Override        public void handleMessage(Message msg) {            // TODO Auto-generated method stub            if (msg.what == 1) {              //  tv_Show.setText(msg.getData().getCharSequence("time"));            //这里必须是CharSequence,如果传过来是String,图片是显示不出来的,大家可试一下                msgList.add(new Msg(msg.getData().getCharSequence("time"), Msg.TYPE_SEND));                adapter.notifyItemInserted(msgList.size() - 1);                recyclerView.scrollToPosition(msgList.size() - 1);            }else if(msg.what==2){                //这里必须是CharSequence,如果传过来是String,图片是显示不出来的,大家可试一下                msgList.add(new Msg(msg.getData().getCharSequence("recive"), Msg.TYPE_RECEIVE));                adapter.notifyItemInserted(msgList.size() - 1);                recyclerView.scrollToPosition(msgList.size() - 1);            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_chat);        initMsg();        initDatas();        //连接服务器        ConnectServ();        btnSend = (Button) this.findViewById(R.id.btnsend);       // btLogin=(Button) this.findViewById(R.id.btLogin);        inputText = (EditText) this.findViewById(R.id.input_text);        mViewPager = (ViewPager) findViewById(R.id.vp_motion);        iv_motion = (ImageView) findViewById(R.id.iv_motion);        vp_motion=(ViewPager)findViewById(R.id.vp_motion);        recyclerView = (RecyclerView) this.findViewById(R.id.msg_recyclerView);        mViewPagerGridList = new ArrayList<>();        LayoutInflater inflater = getLayoutInflater();        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);        recyclerView.setLayoutManager(linearLayoutManager);        adapter = new MsgAdapter(msgList);        recyclerView.setAdapter(adapter);        btnSend.setOnClickListener(this);        //btLogin.setOnClickListener(this);        iv_motion.setOnClickListener(this);        inputText.setOnClickListener(this);        //下面部分是针对girdview的,对girdview进行相关操作,显示图片        **// 每页显示最大条目个数        int pageSize = 28;        //页数        int pageCount = (int) Math.ceil(mDatas.size() * 1.0 / pageSize);        //获取屏幕的宽度,单位px        int screenWidth = getResources().getDisplayMetrics().widthPixels;        //获取GridView中每个item的宽度 = 屏幕宽度 / GridView显示的列数        int columnWidth = (int) Math.ceil((screenWidth) * 1.0 / 7);        for (int index = 0; index < pageCount; index++) {            GridView grid = (GridView) inflater.inflate(R.layout.gird_motion, mViewPager, false);            //设置GridView每个item的宽度            grid.setColumnWidth(columnWidth);            //设置GirdView的布局参数(宽和高,宽为包裹父容器,高 = columnWidth)            grid.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, columnWidth));            grid.setAdapter(new GridViewAdapter(this, mDatas, index));            //响应图片选择事件            grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {                @Override                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                   Log.i("TAG",position+"******************"+id+"");                    faceReplace(getApplicationContext(),drawable[(int) id],faceScr[(int)id],inputText);                }            });            mViewPagerGridList.add(grid);**        }        mViewPager.setAdapter(new MyViewPagerAdapter(mViewPagerGridList));    }    //发送信息到服务器    public void sendMsg(){//因为,聊天界面分为发送端和接收端,两端的数据分别显示在左边和右边,需要用IsSend标记自己是发送端        IsSend=true;        if (!content.equals(""))        {            mPrintWriter.println(content);            mPrintWriter.flush();            inputText.setText("");        }        mThread = new Thread(mRunnable);        mThread.start();    }    private Runnable mRunnable = new Runnable() {        public void run() {            while (true) {                try {                    if ((mStrMSG = mBufferedReader.readLine()) != null) {                        if(IsSend){                            Message message=new Message();                            Bundle bundle=new Bundle();                           //这里是将接收到的消息,先判断是否有图片,如果有在抽取出来显示,                           //而且这里返回值我用的是CharSequence,如果是String则显示不出图片                            CharSequence addSmileySpans=addSmileySpans(mStrMSG);                            bundle.putCharSequence("time",addSmileySpans);                            message.setData(bundle);//bundle传值,耗时,效率低                            handler.sendMessage(message);//发送message信息                            message.what=1;//标志是哪个线程传数据                        }else{                            Message message=new Message();                            Bundle bundle=new Bundle();                            CharSequence addSmileySpans=addSmileySpans(mStrMSG);                            bundle.putCharSequence("recive",addSmileySpans);                            message.setData(bundle);//bundle传值,耗时,效率低                            handler.sendMessage(message);//发送message信息                            message.what=2;//标志是哪个线程传数据                        }                        IsSend=false;                    }                } catch (Exception e) {                    Log.e(TAG, e.toString());                }            }        }    };    private void initMsg()    {        Msg msg1 = new Msg("hello sealong", Msg.TYPE_RECEIVE);        msgList.add(msg1);        Msg msg2 = new Msg("hello peipei", Msg.TYPE_SEND);        msgList.add(msg2);        Msg msg = new Msg("What are you doing", Msg.TYPE_RECEIVE);        msgList.add(msg);    }    public void ConnectServ(){        new Thread(new Runnable() {            @Override            public void run() {                try {                    Log.i(TAG, "lianjie ");                    // ①Socket实例化,连接服务器                    mSocket = new Socket(SERVERIP, SERVERPORT);                    // ②获取Socket输入输出流进行读写操作                    mBufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));                    mPrintWriter = new PrintWriter(mSocket.getOutputStream(), true);                } catch (Exception e) {                    // TODO: handle exception                    Log.e(TAG, e.toString());                }            }        }).start();    }   private void initDatas() {       initMotion();       for(int i=0;i<drawable.length;i++){           HeaderViewBean headerViewBean = new HeaderViewBean("Item " + (i + 1), drawable[i]);           mDatas.add(headerViewBean);           headerViewBean=null;       }   }   //下面两个数据时加载图片资源,并且为图片资源设置对应的名称,用于后期使用正则表达式将图片分离出来    **public void initMotion(){        drawable = new int[]                {                       R.drawable.f000,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,                        R.drawable.f024,R.drawable.f025,R.drawable.f026,R.drawable.f027,R.drawable.f059,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,                        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,                };        faceScr = new String[] { "#000", "#001", "#002", "#003", "#004",                "#005", "#006", "#007", "#008", "#009", "#010", "#011", "#012",                "#013", "#014", "#015", "#016", "#017", "#018", "#019", "#020",                "#021", "#022", "#023", "#024", "#025", "#026", "#027", "#028",                "#029", "#030", "#031", "#032", "#033", "#034", "#035", "#036",                "#037", "#038", "#039", "#040", "#041", "#042", "#043", "#044",                "#045", "#046", "#047", "#048", "#049", "#050", "#051", "#052",                "#053", "#054", "#055", "#056", "#057", "#058", "#059" };        faceBook=buildSmileyToRes();        pattern=buildPattern();    }****//下面的方法是抽取出图片,并将图片转化SpannableString    private HashMap<String, Integer> buildSmileyToRes() {        /**         * 文字和ID不匹配,异常         */        if (drawable.length != faceScr.length) {            throw new IllegalStateException("Smiley resource ID/text mismatch");        }        HashMap<String, Integer> smileyToRes = new HashMap<String, Integer>(                faceScr.length);        for (int i = 0; i < faceScr.length; i++) {            smileyToRes.put(faceScr[i], drawable[i]);        }        return smileyToRes;    }    public  void showMotion(){        if(IsShow==false){            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);            imm.hideSoftInputFromWindow(inputText.getWindowToken(),0);            vp_motion .setVisibility(View.VISIBLE);            IsShow=true;        }else {            vp_motion.setVisibility(View.GONE);            IsShow=false;        }    }    public void faceReplace(Context context, int resourceId,                            String spannableStr, EditText edit) {        /**         * 根据ID获取图片资源         */        Drawable dr = context.getResources().getDrawable(resourceId);        dr.setBounds(0, 0, dr.getIntrinsicWidth()*4/5, dr.getIntrinsicHeight()*4/5);        /**         * SpannableString 配置被替代的文字描述;ImageSpan 配置替代的图片         */        SpannableString spanStr = new SpannableString(spannableStr);        ImageSpan spanImg = new ImageSpan(dr, ImageSpan.ALIGN_BASELINE);        /**         * 将文字如【smile】替换为表情 参数二、参数三分别指定所要替代字符的位置         */        spanStr.setSpan(spanImg, 0, spanStr.length(), spanStr.SPAN_EXCLUSIVE_EXCLUSIVE);        edit.append(spanStr);    }    public CharSequence addSmileySpans(CharSequence text) {        SpannableStringBuilder builder = new SpannableStringBuilder(text);        Matcher matcher = pattern.matcher(text);        while (matcher.find()) {            int resId = faceBook.get(matcher.group());            Drawable dr = this.getResources().getDrawable(resId);            dr.setBounds(0, 0, dr.getIntrinsicWidth()*4/5, dr.getIntrinsicHeight()*4/5);            builder.setSpan(new ImageSpan(dr, ImageSpan.ALIGN_BASELINE),                    matcher.start(), matcher.end(),                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);        }        return builder;    }    private Pattern buildPattern() {        StringBuilder patternString = new StringBuilder(faceScr.length * 3);        patternString.append('(');        for (String s : faceScr) {            patternString.append(Pattern.quote(s));            patternString.append('|');        }        patternString.replace(patternString.length() - 1,                patternString.length(), ")");        return Pattern.compile(patternString.toString());    }    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.btnsend:                sendMsg();                break;            case R.id.iv_motion:                showMotion();                break;            case R.id.input_text:                vp_motion.setVisibility(View.GONE);                break;        }**    }}

最后给大家道歉一下,因为,本人写的博客不多,有点乱,时间也有点紧,所以可能看起来会很费力,希望大家谅解,也真心希望能帮到大家,该demo确实是亲测可用的。

1 0
原创粉丝点击