实现RichEdit(一)---如何在EditText中插入图片表情

前言:现在软件开发用到了这个功能,对于不会的东东,难度都是比较大的,会的不难,难的不会,反正就是学吧,这次总共分两篇,这篇讲解如何实现在EditText中插入图片,第二篇讲如何实现与服务器通信(PHP);

效果:

步骤:

1、我们为了将图片与更多的信息结合起来,所以我们采用XML的形式先将图片的各信息组织起来,保存在assets/brow.xml里
2、定义一个类(class smile),用来保存从brow.xml里提取的各种信息

3、利用保存提取的信息的 List<smile> simles 变量 ,生成GridView的Adapter,加载到GridView中

4、最后是逻辑处理,定义监听函数等

一、设置AndroidManifest.xml
在MainActivity对应的Activity里添加一个属性:表示当弹出软键时,程序底部自适应

android:windowSoftInputMode="stateVisible|adjustResize"
所有的AndroidManifest.xml的代码为:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.edit_with_expression"
    android:versionCode="1"
    android:versionName="1.0" >
 
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />
 
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.edit_with_expression.MainActivity"
            android:label="@string/app_name" 
            android:windowSoftInputMode="stateVisible|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>
二、保存表情信息的brow.xml和smile类
1、brow.xml
根据上面的步骤,我们先看保存表情信息的brow.xml是怎样的格式;

<?xml version="1.0" encoding="utf-8"?>
<brows>
    <brow>
        <code><![CDATA[[em:1:]]]></code>
        <name>f001</name>
    </brow>
    <brow>
        <code><![CDATA[[em:2:]]]></code>
        <name>f002</name>
    </brow>
    <brow>
        <code><![CDATA[[em:3:]]]></code>
        <name>f003</name>
    </brow>
<brows>    
这个就是brow.xml的完整格式,每个图片占一个<brow></brow>标签,大家可以看到在源码中不只这些<brow>标签,其实有50个,这里只是为了说明格式,所以并没有全部列出来,只是让大家看一下格式。

2、smile类
这个类只是为了保存从brow.xml里提取到了每个图片的信息,也就是CODE和图片的NAME;

package com.example.edit_with_expression;
/**
 * @author  harvic
 * @date 2014-1-14
 */
public class Smile {
    private String code; //表情代码
    
    private String name ;  //表情名字
 
    public String getName() {
        return name;
    }
 
    
    public void setName(String name) {
        this.name = name;
    }
 
    
    public String getCode() {
        return code;
    }
 
 
    public void setCode(String code) {
        this.code = code;
    }
    
}
三、解析XML的类(ParserBrowXml.java)
功能:解析brow.xml,返回List<Smile>

package com.example.edit_with_expression;
 
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
 
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
/**
 * @author harvic
 * @date   2014-1-11
 */
public class ParserBrowXml {
public  static List<Smile> getInfo(InputStream inputStream){
        
        XmlPullParser parser = Xml.newPullParser() ;
        int eventType = 0;
        List<Smile> smiles = null ;
        Smile smile = null ;
        try {
            parser.setInput(inputStream, "UTF-8") ;
            eventType = parser.getEventType();
            while(eventType != XmlPullParser.END_DOCUMENT){
                
                switch (eventType) {
                case XmlPullParser.START_DOCUMENT:
                    
                    smiles = new ArrayList<Smile>() ;
                    break ;
                case XmlPullParser.START_TAG:
                    if("brow".equals(parser.getName())){
                        smile = new Smile() ;
                        
                    }else if("code".equals(parser.getName())){
                        smile.setCode(parser.nextText()) ;
                    }else if("name".equals(parser.getName())){
                        smile.setName(parser.nextText()) ;
                    }
                    break ;
                case XmlPullParser.END_TAG:
                    if("brow".equals(parser.getName())){
                        smiles.add(smile) ;
                        smile = null ;
                    }
                    break;
                    
                default:
                    break;
                }
                
                eventType = parser.next() ;
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return smiles;
        }
}
四、主程序(MainActivity.java)
先看全部代码:

package com.example.edit_with_expression;
/**
 * @author harvic
 * @date   2014-1-11
 */
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
 
public class MainActivity extends Activity {
 
    private List<Smile> smiles = null; // 表情集合
    private EditText ET_content; //输入框
    private ImageView IV_face;  //表情显示按钮
 
    private GridView GV_faceView;//存放表情列表的GridView
    private InputMethodManager inputManager;//软键盘管理类 
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // 和 各个组件变量初始化
        InitVariable();
        // 初始化GridView,将其与Adapter绑定
        InitGridView();
        
        //表情显示图片点击监听
        IV_face.setOnClickListener(faceClickListener);
        
        //监听点击了表情的哪一项
        GV_faceView.setOnItemClickListener(gridViewFaceItemClickListener);
        
        //EditText点击监听
        ET_content.setOnClickListener(EditContentClickListener);
        
        
    }
    /**
     * 初始化变量
     */
    private void InitVariable(){
        //软键盘管理类 
        inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        //其它变量
        GV_faceView = (GridView) this.findViewById(R.id.tweet_pub_faces); // 取得放置表情的gridView组件
        ET_content = (EditText) findViewById(R.id.tweet_pub_content);
        IV_face = (ImageView) findViewById(R.id.tweet_pub_footbar_face);
    }
 
    private void InitGridView() {
        try {
            InputStream inputStream = this.getResources().getAssets()
                    .open("brow.xml"); // 取得assets中的borw.xml文件
            smiles = ParserBrowXml.getInfo(inputStream); // 解析borw.xml
            addexpression(this, smiles, GV_faceView);// 调用生情表情的方法
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 点击显示表情的监听器,当用户点击时显示表示列表
     */
    private View.OnClickListener faceClickListener = new View.OnClickListener() {
 
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            try {
                showOrHideIMM();
            } catch (Exception e) {
                // TODO: handle exception
                Log.w("msg", e.getMessage());
            }
        }
        
    };
    /**
     * 点击EditText的监听器,当用户点击EditText的时候显示键盘
     */
    private View.OnClickListener EditContentClickListener = new View.OnClickListener() {
 
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            showIMM();
        }
        
    };
    /**
     * 点击表情GRIDVIEW中的某一项的监听器
     */
    private OnItemClickListener gridViewFaceItemClickListener=new AdapterView.OnItemClickListener(){
 
        @Override
        public void onItemClick(AdapterView<?> arg0, View view, int position,
                long id) {
            // TODO Auto-generated method stub
            //首先得到当前用户点击的表情的信息
            Smile smile = smiles.get(position);
            //得到当前CURSOR位置
            int cursor = ET_content.getSelectionStart();
            Field f;
            try {
                //根据资源名字得到Resource和对应的Drawable
                f = (Field) R.drawable.class.getDeclaredField(smile
                        .getName());
                int j = f.getInt(R.drawable.class);
                Drawable d = getResources().getDrawable(j);
                d.setBounds(0, 0, 35, 35);//设置表情图片的显示大小
                
                //显示在EditText中
                String str="img";
                SpannableString ss = new SpannableString(str);
                ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BOTTOM);
                ss.setSpan(span, 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);    
                
                ET_content.getText().insert(cursor,ss);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        
    };
    
    /**
     * 根据SMILE列表找到对应的SORCE ID,生成simpleAdatper 传到GrideView中
     * 生成表情的方法 
     * @param context 要传入的上下文
     * @param smiles  表情集合
     * @param gridView 要显示器的grildView
     * @throws Exception 异常
     */
        public void addexpression(Context context,List<Smile> smiles,GridView gridView) throws Exception {
 
            // 通过反射把资源文件中的图片取出来放在GridView上
            ArrayList<HashMap<String, Object>> lstImageItem = new ArrayList<HashMap<String, Object>>();
            for (int i = 0; i < 50; i++) {
                Smile smile = smiles.get(i);
                if (smile != null) {
                    HashMap<String, Object> map = new HashMap<String, Object>();
                    Field f = (Field) R.drawable.class.getDeclaredField(smile
                            .getName());
                    int j = f.getInt(R.drawable.class);
                    map.put("ItemImage", j);// 添加图像资源的ID
                    lstImageItem.add(map);
 
                }
            }
 
            // 生成适配器的ImageItem <====> 动态数组的元素,两者一一对应
            SimpleAdapter saImageItems = new SimpleAdapter(context, lstImageItem,// 数据来源
                    R.layout.brow_item,
                    // 动态数组与ImageItem对应的子项
                    new String[] { "ItemImage" },
                    // ImageItem的XML文件里面的一个ImageView
                    new int[] { R.id.iv_brow });
            gridView.setSelector(new ColorDrawable(Color.TRANSPARENT));//解决点击GridView背景变黑的情况
            gridView.setAdapter(saImageItems);
        }
    
    //以下显示隐藏软键或表情的方法集合
    private void showIMM() {
        IV_face.setTag(1);
        showOrHideIMM();
    }
 
    private void showFace() {
        IV_face.setTag(1);
        GV_faceView.setVisibility(View.VISIBLE);
    }
 
    private void hideFace() {
        IV_face.setTag(null);
        GV_faceView.setVisibility(View.GONE);
    }
 
    private void showOrHideIMM() {
        if (IV_face.getTag() == null) {
            // 隐藏软键盘
            inputManager.hideSoftInputFromWindow(IV_face.getWindowToken(), 0);
            // 显示表情
            showFace();
        } else {
            // 显示软键盘
            inputManager.showSoftInput(ET_content, 0);
            // 隐藏表情
            hideFace();
        }
    }
 
}
代码有点长,这是因为我把所有相关的东东都包装成了方法,放在了这个页面,所以我们从主到次,根据逻辑慢慢来;

1、看主函数(OnCreate)
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    // 和 各个组件变量初始化
    InitVariable();
    // 初始化GridView,将其与Adapter绑定
    InitGridView();
    
    //表情显示图片点击监听
    IV_face.setOnClickListener(faceClickListener);
    
    //监听点击了表情的哪一项
    GV_faceView.setOnItemClickListener(gridViewFaceItemClickListener);
    
    //EditText点击监听
    ET_content.setOnClickListener(EditContentClickListener);
}
只看这些,就比较好理解了,这是整个程序的脉络:

(1)、初始化变量
(2)、初始化GridView
(3)、各种监听函数的设置

下面我们逐个函数的讲

 2、初始化变量InitVairiable()
/**
 * 初始化变量
 */
private void InitVariable(){
    //软键盘管理类 
    inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
    //其它变量
    GV_faceView = (GridView) this.findViewById(R.id.tweet_pub_faces); // 取得放置表情的gridView组件
    ET_content = (EditText) findViewById(R.id.tweet_pub_content);
    IV_face = (ImageView) findViewById(R.id.tweet_pub_footbar_face);
}
这部分什么都没有,就是将资源与变量绑定起来,也就是根据资源初始化变量;
3、初始化GridView------InitGridView() 
private void InitGridView() {
    try {
        InputStream inputStream = this.getResources().getAssets()
                .open("brow.xml"); // 取得assets中的borw.xml文件
        smiles = ParserBrowXml.getInfo(inputStream); // 解析borw.xml
        addexpression(this, smiles, GV_faceView);// 调用生情表情的方法
    } catch (Exception e) {
        e.printStackTrace();
    }
}
这部分看起来挺简单,可仔细一看并不简单:
(1)、前两句比较容易,就是利用ParserBrowXml解析XML,将返回的List<smile> 类型的变量赋值给smiles变量
(2)、最后一句是封装的方法,这个方法传进去三个变量,第一个是this,第二个List<smile>  smile,第三个是 GridView GV_faceView;单从这三个变量的类型上看应该也能猜出来这个函数的功能:将brow.xml里的smile信息传进去 ,然后生成GrideViewAdapter,初始化GrideView,下面看看这个addexpression()方法

/**
 * 根据SMILE列表找到对应的SORCE ID,生成simpleAdatper 传到GrideView中
 * 生成表情的方法 
 * @param context 要传入的上下文
 * @param smiles  表情集合
 * @param gridView 要显示器的grildView
 * @throws Exception 异常
 */
public void addexpression(Context context,List<Smile> smiles,GridView gridView) throws Exception {
 
    // 通过反射把资源文件中的图片取出来放在GridView上
    ArrayList<HashMap<String, Object>> lstImageItem = new ArrayList<HashMap<String, Object>>();
    for (int i = 0; i < 50; i++) {
        Smile smile = smiles.get(i);
        if (smile != null) {
            HashMap<String, Object> map = new HashMap<String, Object>();
            Field f = (Field) R.drawable.class.getDeclaredField(smile
                    .getName());
            int j = f.getInt(R.drawable.class);
            map.put("ItemImage", j);// 添加图像资源的ID
            lstImageItem.add(map);
 
        }
    }
 
    // 生成适配器的ImageItem <====> 动态数组的元素,两者一一对应
    SimpleAdapter saImageItems = new SimpleAdapter(context, lstImageItem,// 数据来源
            R.layout.brow_item,
            // 动态数组与ImageItem对应的子项
            new String[] { "ItemImage" },
            // ImageItem的XML文件里面的一个ImageView
            new int[] { R.id.iv_brow });
    gridView.setSelector(new ColorDrawable(Color.TRANSPARENT));//解决点击GridView背景变黑的情况
    gridView.setAdapter(saImageItems);
}
上面的代码有点部分要注意一下:
(1)、根据名称得到资源的ID

Field f = (Field) R.drawable.class.getDeclaredField(smile
        .getName());
int j = f.getInt(R.drawable.class);
(2)、生成适配器
SimpleAdapter saImageItems = new SimpleAdapter(context, lstImageItem,// 数据来源
        R.layout.brow_item,
        // 动态数组与ImageItem对应的子项
        new String[] { "ItemImage" },
        // ImageItem的XML文件里面的一个ImageView
        new int[] { R.id.iv_brow });
4、监听部分---gridViewFaceItemClickListener
对于监听部分,我只讲一个gridViewFaceItemClickListener,也就是当用户点击gridView里某一项时,怎样把这个表情添加到EditView中;其它的监听函数都是些对于软键盘和表情GridView显示隐藏的问题了,就不多了,具体看下对应的代码吧。
下面只是gridViewFaceItemClickListener的代码:

private OnItemClickListener gridViewFaceItemClickListener=new AdapterView.OnItemClickListener(){
 
    @Override
    public void onItemClick(AdapterView<?> arg0, View view, int position,
            long id) {
        // TODO Auto-generated method stub
        //首先得到当前用户点击的表情的信息
        Smile smile = smiles.get(position);
        //得到当前CURSOR位置
        int cursor = ET_content.getSelectionStart();
        Field f;
        try {
            //根据资源名字得到Resource和对应的Drawable
            f = (Field) R.drawable.class.getDeclaredField(smile
                    .getName());
            int j = f.getInt(R.drawable.class);
            Drawable d = getResources().getDrawable(j);
            d.setBounds(0, 0, 35, 35);//设置表情图片的显示大小
            
            //显示在EditText中
            String str="img";
            SpannableString ss = new SpannableString(str);
            ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BOTTOM);
            ss.setSpan(span, 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);    
            
            ET_content.getText().insert(cursor,ss);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
步骤:
(1)、先得到用户点击的ITEM,对应的smile图片的信息
(2)、根据图片名得到该图片的Drawable;
(3)、利用SpannableString和setSpan将其加入到EditView中;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值