Android EditText图文混排的总结

开始:

下面就具体说一下我遇到的问题,首先是EditText里面的图文混排问题,这个问题的难点就是三点:

1.怎么插图片 

2.怎么保存插入的图片和文字 

3.怎么解析回图片和文字

解决方法:

1.怎么插入图片

通过一个自己写的具体的界面来说:

Android EditText图文混排的总结_第1张图片

在这里定义了两个Button按钮和一个EditText,插入图片的话,就是点击插入图片按钮然后从sd卡中选择一张图片出来。下面是实现代码:

首先是button的监听事件:

1
2
3
4
5
6
7
8
9
10
btn_insertImage.setOnClickListener( new  OnClickListener() {
             @Override
             public  void  onClick(View v) {
                 // TODO Auto-generated method stub
                 Intent getImage =  new  Intent(Intent.ACTION_GET_CONTENT);
                 getImage.addCategory(Intent.CATEGORY_OPENABLE);
                 getImage.setType( "image/*" );
                 startActivityForResult(getImage,  1 );
             }
         });

来分析一下代码:

  1. ACTION_GET_CONTENT是标准的Activity Action的一种,那什么是Activity Action呢,简单来说就是让用户选择一种特殊的数据并得到它。

  2. ACTION_GET_CONTENT可以让用户在运行的程序中取得数据,例如取照片,当然这里的运行的程序指的是手机上的文件管理器之类的。

  3. addCategory是要增加一个分类,增加一个什么分类呢?就是增加CATEGORY_OPENABLE,从字面意思值是增加一个可以打开的分类,也即是取得的uri要可以被ContentResolver解析,注意这里的分类即是执行的附加条件。

  4. setType就是设置取得的数据类型为image,也即是取照片。

通过以上分析,可以知道我们定义了这样一个intent,要取得数据,取得数据要能够被打开,且类型为image,这样我们就可以执行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Override
     protected  void  onActivityResult( int  requestCode,  int  resultCode,
             Intent intent) {
         // TODO Auto-generated method stub
         super .onActivityResult(requestCode, resultCode, intent);
         ContentResolver resolver = getContentResolver();
         if  (resultCode == RESULT_OK) {
             if  (requestCode ==  1 ) {
                 originalUri = intent.getData();
                 try  {
                     Bitmap originalBitmap = BitmapFactory.decodeStream(resolver
                             .openInputStream(originalUri));
                     bitmap = resizeImage(originalBitmap,  100 100 );
                 catch  (FileNotFoundException e) {
                     e.printStackTrace();
                 }
                 if  (bitmap !=  null ) {
                     editText = (EditText) findViewById(R.id.edit);
                     insertIntoEditText(getBitmapMime(bitmap, originalUri));
                 else  {
                     Toast.makeText(MainActivity. this "获取图片失败" ,
                             Toast.LENGTH_SHORT).show();
                 }
             }
         }
         if  (bitmap !=  null ) {
         }
     }

代码分析:

1.首先使用intent.getData得到uri

2.然后调用BitmapFactory的解码函数decodeStream且要求的参数为流(Stream),所以要用ContentResolver解析uri为流。

3.接着通过一个resizeImage函数重新调整bitmap大小,这里不再给出

4.然后就是要把所得到的图片放到EditText里了


1
2
3
4
5
6
7
private  SpannableString getBitmapMime(Bitmap pic, Uri uri) {
         String path = uri.getPath();
         SpannableString ss =  new  SpannableString(path);
         ImageSpan span =  new  ImageSpan( this , pic);
         ss.setSpan(span,  0 , path.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
         return  ss;
     }
1
2
3
4
5
6
7
private  void  insertIntoEditText(SpannableString ss) {
     Editable et = editText.getText(); // 先获取Edittext中的内容
     int  start = editText.getSelectionStart();
     et.insert(start, ss); // 设置ss要添加的位置
     editText.setText(et); // 把et添加到Edittext中
     editText.setSelection(start + ss.length()); // 设置Edittext中光标在最后面显示
}

代码分析:

  1. 在getBitmapMime()中,首先建立一个SpannableString,r然后我们要给它附一张图片,这张图片来自我们的sd卡,然后是setSpan()函数,这里有4个参数,分别是要插入的对象,起始位置,终止位置,标记,在本程序里插入的对象为一张图片,起始位置为0,终止位置为path的长度,标记为会删除缓冲区里原有的text,这里即为path。

  2. 在insertIntoEditText()中,因为是动态添加,所以要用到Editable,然后先把ss添加到et里,然后在放到editText里,最后在设置一下光标的位置为最后

至此,插入图片完成


2. 怎么保存图片?

保存按钮的监听事件代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Button btn_save = (Button) findViewById(R.id.save);
         btn_save.setOnClickListener( new  OnClickListener() {
         
             @Override
             public  void  onClick(View v) {
                 // TODO Auto-generated method stub
                 String content = editText.getText().toString();
                 Bundle data =  new  Bundle();
                 data.putString( "nei" , content);
                 Intent intent =  new  Intent(MainActivity. this , Display. class );
                 intent.putExtra( "neirong" , data);
                 startActivity(intent);
             }
         });

代码分析:

代码非常简单,我们只需保存editText里面的内容转化成String存到content中,(注意:这里的图片会变为它的路径即为/mnt/sdcard/.........这样的形式),

然后我们启动另外一个Activity,这里当然也可以保存content到数据库中。

至此,保存图片完成


3. 怎么解析回图片和文字

首先,我们有另外一个Activity,名字为display,注这里不在给图,因为view里只有一个EditText

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
EditText display;
       
@Override
protected  void  onCreate(Bundle savedInstanceState) {
     // TODO Auto-generated method stub
     super .onCreate(savedInstanceState);
     setContentView(R.layout.display);
     display = (EditText) findViewById(R.id.display);
     String imagePath = getIntent().getBundleExtra( "neirong" ).getString(
             "nei" );
     SpannableString ss =  new  SpannableString(imagePath);
     Pattern p=Pattern.compile( "/mnt/sdcard/.+?\\.\\w{3}" );
     Matcher m=p.matcher(imagePath);
     while (m.find()){
         Bitmap bm = BitmapFactory.decodeFile(m.group());
         Bitmap rbm = resizeImage(bm,  100 100 );
         ImageSpan span =  new  ImageSpan( this , rbm);
         ss.setSpan(span, m.start(), m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
     }
     display.setText(ss);
}

代码分析:

首先取出上一个Activity里面的内容,保存到imagePath中,接下来就是把imagePath中的图片改为图片即可,同样使用SpannableString,但怎么在一个很长的String中找到图片的路径呢,要使用正则表达式,这里是我写的一个正则表达式/mnt/sdcard/.+?\\.\\w{3}写的比较差,呵呵,通过正则表达式找到路径,就可以在BitmapFactory中找到图片,然后就可以利用setSpan()函数进行替换,最后在显示出来。

至此,解析回图片和文字完成


另外一种实现图文混编的方式:是通过html的标签的方式插入到edittext中去:

标记中有一个标记。通过这个标记,可以很容易地实现将图像插入到EditText的功能。不过使用标签要比使用其他的标签多一个步骤,这就是要实现一个ImageGetter接口,通过这个接口,可以获得一个Drawable对象。先看看如下的代码:


Java代码:

private ImageGetter imageGetter = new ImageGetter(){     
  1.          @Override     
  2.          public Drawable getDrawable(String source)     
  3.          {     
  4.              int id = Integer.parseInt(source);     
  5.              Drawable d = getResources().getDrawable(id);     
  6.              d.setBounds(00, d.getIntrinsicWidth(), d.getIntrinsicHeight());     
  7.              return d;     
  8.          }     
  9. };    


上面的代码通过ImageGetter接口的getDrawable方法返回了一个Drawable对象,其中source参数的值就是标签的src属性的值。我们需要通过如下的代码来使用标签。


Java代码:
  1. editText.append(Html.fromHtml("+ faces[new Random().nextInt(6)] +"'/>", imageGetter, null));  


其中faces是一个int类型数组,保存了相应的drawable资源的ID值。在使用标签之前需要使用Html.fromHtml方法来封装这些标签,如果使用的是标签,需要使用fromHtml方法的第2个参数指定ImageGetter对象,以便通过标签的src属性获得相应的Drawable对象。通过EditText.append方法插入标签后,系统会自动将标签转换成相应的图像显示在EditText中.

你可能感兴趣的:(Android EditText图文混排的总结)