AndroidはEditTextに表情画像を挿入

16469 ワード

EditTextは通常文字を表示するために使われていますが、QQで表情画像を使うことができたり、必要な文字をハイライト表示したりするなど、文字に画像を混ぜる必要がある場合もあります.androidでもどうすればいいのでしょうか. 
androidの中にandroidがあるのを覚えています.textパッケージは、テキストに対する強力な処理機能を提供します. 
画像の追加は主にSpannablesStringとImagesSpanクラスで、具体的にはsdkドキュメントSpannablesStringを参照してください.
ここでは、人人網クライアントがメッセージを公開するインタフェースを例に挙げます.
レイアウトファイルmain.xml



    

        

        

        

        
    

    

        
    

    

    

        

            

MainActivity.java

package com.yulore.emotion;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.ImageView;

public class MainActivity extends Activity implements OnClickListener {
    private static final String TAG = "MainActivity";
	private ImageButton ib_emotion;
	private GridView gv_emotion;
	private EmotionAdapter mAdapter;
	private EditText et_content;
	private ImageView iv_publish;

	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        findViewById();
        initEmotionIcons();
        setListener();
        
        mAdapter = new EmotionAdapter();
        gv_emotion.setAdapter(mAdapter);
    }

	private void initEmotionIcons() {
		String json = EmotionUtil.getInstance().readFromFile(EmotionUtil.DOWNLOAD_EMOTION_PATH, "Emoticons.json");
		if(json!=null){
			Log.e(TAG, json);
			RenRenData.mEmotionList = new DataProvider().resolve(json);
		}
	}

	private void findViewById() {
		ib_emotion = (ImageButton) findViewById(R.id.newsfeedpublish_emoticon);
		gv_emotion = (GridView) findViewById(R.id.newsfeedpublish_emoticons);
		et_content = (EditText) findViewById(R.id.newsfeedpublish_content);
		iv_publish = (ImageView) findViewById(R.id.newsfeedpublish_publish);
	}
	
	private void setListener() {
		ib_emotion.setOnClickListener(this);
		et_content.setOnClickListener(this);
		
		gv_emotion.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView> parent, View view,
					int position, long id) {
				
				String emotion = RenRenData.mEmotionList.get(position).getEmotion();
				
				if(et_content.getText().length()+emotion.length()<=140){	//    140
					
//					et_content.setText(et_content.getText().toString()+emotion);
					CharSequence ret = EmotionUtil.getInstance().replace(getApplicationContext(), et_content.getText().toString()+emotion);
					Log.e(TAG, "ret="+ret);
					et_content.setText(ret);
				}
			}
		});
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.newsfeedpublish_emoticon:
			if(gv_emotion.isShown()){
				gv_emotion.setVisibility(View.GONE);
				ib_emotion.setImageResource(R.drawable.v5_0_1_publisher_emotion_button);
			}else{
				gv_emotion.setVisibility(View.VISIBLE);
				ib_emotion.setImageResource(R.drawable.v5_0_1_publisher_pad_button);
				
				//       
				InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
				imm.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
			}
			break;
		case R.id.newsfeedpublish_content:
			if(gv_emotion.isShown()){
				gv_emotion.setVisibility(View.GONE);
				ib_emotion.setImageResource(R.drawable.v5_0_1_publisher_emotion_button);
			}
			break;

		default:
			break;
		}
	}
	
	private class EmotionAdapter extends BaseAdapter{

		@Override
		public int getCount() {
			
			return RenRenData.mEmotionList.size();
		}

		@Override
		public Object getItem(int position) {
			
			return RenRenData.mEmotionList.get(position);
		}

		@Override
		public long getItemId(int position) {
			
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View view;
			ViewHolder holder;
			if(convertView==null){
				holder = new ViewHolder();
				view = View.inflate(getApplicationContext(), R.layout.emotion_item, null);
				holder.iv_emotion = (ImageView) view.findViewById(R.id.emotcons_item_img);
				
				view.setTag(holder);
			}else{
				view = convertView;
				holder = (ViewHolder) view.getTag();
			}
			EmotionIcon em = RenRenData.mEmotionList.get(position);
			holder.iv_emotion.setImageBitmap(EmotionUtil.getInstance().getLocalEmotionIcon(em.getEmotion()));
			
			return view;
		}
	}
	
	public static class ViewHolder{
		public ImageView iv_emotion;
	}
}

EmotionUtil.java
package com.yulore.emotion;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;

public class EmotionUtil {

	public static final String DOWNLOAD_EMOTION_PATH = Environment
			.getExternalStorageDirectory().getAbsolutePath()
			+ "/RenRenForAndroid/Emoticons/";

	private static EmotionUtil instance = new EmotionUtil();

	private EmotionUtil() {
	};

	public static EmotionUtil getInstance() {

		return instance;
	}

	/**
	 *                 
	 * 
	 * @param text
	 *                   
	 * @return        
	 */
	public CharSequence replace(Context context,CharSequence text) {
		try {
			SpannableStringBuilder builder = new SpannableStringBuilder(text);
			Pattern pattern = buildPattern();
			Matcher matcher = pattern.matcher(text);
			while (matcher.find()) {
				Bitmap bitmap = getLocalEmotionIcon(matcher.group());
				ImageSpan span = new ImageSpan(context, bitmap);
				builder.setSpan(span, matcher.start(), matcher.end(),
						Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
			}
			return builder;
		} catch (Exception e) {
			return text;
		}
	}
	
	/**
	 *      
	 * 
	 * @return
	 */
	private Pattern buildPattern() {
		/**
		 *             ,         Json,   
		 */
		if(RenRenData.mEmotionList==null || RenRenData.mEmotionList.size()==0){
			
			String json = EmotionUtil.getInstance().readFromFile(EmotionUtil.DOWNLOAD_EMOTION_PATH, "Emoticons.json");

			if(json!=null){
				RenRenData.mEmotionList = new DataProvider().resolve(json);
			}
		}

		StringBuilder patternString = new StringBuilder(
				RenRenData.mEmotionList.size() * 3);
		patternString.append('(');
		for (EmotionIcon result : RenRenData.mEmotionList) {
			String s = result.getEmotion();
			patternString.append(Pattern.quote(s));
			patternString.append('|');
		}
		patternString.replace(patternString.length() - 1,
				patternString.length(), ")");
		return Pattern.compile(patternString.toString());
	}

	public String readFromFile(String filePath, String fileName) {
		if (fileName == null || "".equals(fileName)) {
			return null;
		}
		String ret = "";
		if (Environment.MEDIA_MOUNTED.equals(Environment
				.getExternalStorageState())) {

			File dir = new File(filePath);
			if (dir == null || !dir.exists()) {
				dir.mkdirs();
			}

			File targetFile = new File(filePath + fileName);
			try {

				if (targetFile == null || targetFile.exists()) {
					targetFile.createNewFile();
				}

				InputStream in = new BufferedInputStream(new FileInputStream(
						targetFile));
				BufferedReader br = new BufferedReader(new InputStreamReader(
						in, "UTF-8"));
				String tmp;
				while ((tmp = br.readLine()) != null) {
					ret += tmp;
				}
				br.close();
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return ret;
	}

	/**
	 *             
	 * @param imageName
	 * @return
	 */
	public Bitmap getEmotionIcon(String imageName) {

		File cacheDir = new File(DOWNLOAD_EMOTION_PATH);

		if (!cacheDir.exists()) {
			cacheDir.mkdirs();
		}

		File[] cacheFiles = cacheDir.listFiles();
		int i = 0;
		if (cacheFiles != null) {
			for (; i < cacheFiles.length; i++) {
				if (imageName.equals(cacheFiles[i].getName())) {
					break;
				}
			}
		}
		if (i < cacheFiles.length) {
			return BitmapFactory.decodeFile(DOWNLOAD_EMOTION_PATH + imageName);
		}
		return null;
	}

	/**
	 *  SD              
	 * 
	 * @param imageName
	 *                 
	 * @return    Bitmap
	 */
	public Bitmap getLocalEmotionIcon(String imageName) {

		File dir = new File(DOWNLOAD_EMOTION_PATH);
		if (!dir.exists()) {
			dir.mkdirs();
		}

		File[] cacheFiles = dir.listFiles();

		int index = 0;

		for (int i = 0; cacheFiles != null && i < cacheFiles.length; i++) {

			if (imageName.equals(cacheFiles[i].getName())) {
				index = i;
				break;
			}
		}

		Bitmap bitmap = null;

		if (index < cacheFiles.length) {
			/**
			 *        ,        60*60 Bitmap,          
			 */
			bitmap = Bitmap
					.createScaledBitmap(
							BitmapFactory.decodeFile(DOWNLOAD_EMOTION_PATH
									+ imageName), 60, 60, true);
		}

		return bitmap;
	}

	/**
	 *                 
	 * 
	 * @param text
	 * @return
	 */
	/*public CharSequence replace02(Context context, CharSequence text, int resId) {
		// SpannableString      ,     ,        object;      SpannableStringBuilder,  sdk  
		SpannableString ss = new SpannableString(text.toString() + "[smile]");
		//           
		Drawable d = context.getResources().getDrawable(resId);
		//     
		d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
		//                
		ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
		//     
		ss.setSpan(span, text.length(), text.length() + "[smile]".length(),
				Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

		return ss;
	}*/
}