Android实用视图动画及工具系列之六:通用表情栏,仿QQ微信聊天弹出表情选框

实现效果



功能说明

仿QQ微信聊天表情库框,这个目前市面上已经很多类似的功能了,我就不做多的累赘,本表情栏的优势在于便于集成,而且适用于多种环境,可转换为html标签和转义表情标签等,由于总体代码和资源较少,集成方便,就未上传jcenter或Maven central上了,需要用到类似功能的自行下载源码集成到项目中即可。
适用于新手及新学习Android的码友们,老玩家当然也可以看看,这个还是挺简单挺实用的,在后面会简略介绍实现方法及源代码,同时博客的最后还提供源代码和图片等资源github下载地址。

本部分内容主要讲解表情栏实现,不讲解底部弹出框的实现,需要查看底部弹出框部分实现的请查看这篇文章:
--------------------------------------------------------------------------------------------------------------------
Android实用视图动画及工具系列之五:底部回复对话框,仿QQ空间微信朋友圈回复对话框:
--------------------------------------------------------------------------------------------------------------------

功能讲解

一:项目结构和外观样式

既然是表情库就需要表情,可以是本地的,也可以是从网络加载的,看需求更改,本例子提供了一些本地表情包:(其他图片资源在源代码内,需要的自行下载):
微笑
吐舌头
偷笑
大笑

项目结构如下,总共5个类,一些表情和两个布局文件,还是很简约的:



二:部分代码详解

主类为FaceView.class,主要完成了表情的布局,适配,和转义功能,提供了两种模式:
转义为<img>标签或转义为表情标签,如“/e002”,约定一个转义规则。
转义为表情标签的方法为getImgTag();
转换为<img>标签修改imgTag即可。
private static String imgTag = "<img src=\"http://www.host.com/images/-1.png\" border=\"0\" alt=\"\"/>";
//mode , html tag or escape tag
public static int TAG_MODE_IMG = 1;
public static int TAG_MODE_EMOJI = 2;
package com.jaiky.test.faceview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
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.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;


import java.util.ArrayList;
import java.util.List;

public class FaceView extends LinearLayout implements OnPageChangeListener,
		OnItemClickListener, OnClickListener {
	/**
	 * Convert to Html Tag, using for webPage
	 */
	private static String imgTag = "<img src=\"http://www.host.com/images/-1.png\" border=\"0\" alt=\"\"/>";

	/**
	 * Face size
	 */
	private int faceDefaultSize = 17;

	private List<View> m_arrFacePageView;
	private ViewPager m_vpFace;
	private List<ImageView> m_arrDotView;
	private LinearLayout m_dotBar;
	private Context m_context;
	private OnFaceSelectedListener m_listener;
	private EditText m_edit;
	private View m_btnView;

	private int m_tagMode;

	//mode , html tag or escape tag
	public static int TAG_MODE_IMG = 1;
	public static int TAG_MODE_EMOJI = 2;

	private int faceStyleResource;
	private int textStyleResource;

	/**
	 * 实例化方法
	 *
	 * @param context
	 * @param attrs
	 */
	public FaceView(Context context, AttributeSet attrs) {
		super(context, attrs);

		m_context = context;
		m_tagMode = TAG_MODE_IMG;
		LayoutInflater.from(context).inflate(R.layout.global_face_view, this, true);
		initView();
	}

	// 设置标签模式
	public void setTagMode(int tagMode) {
		m_tagMode = tagMode;
	}

	/**
	 * set the button of show or hide the faceview
	 *
	 * @param btnView
	 * @author saderos
	 *
	 */
	public void setBtnView(View btnView) {
		m_btnView = btnView;
		m_btnView.setOnClickListener(this);
	}

	public void setFaceAndTextStyle(int faceStyle, int textStyle){
		this.faceStyleResource = faceStyle;
		this.textStyleResource = textStyle;
	}


	/**
	 * if you just need to set the editText, and them ,you don't have to append
	 * text to the editText yourself
	 *
	 * @author saderos
	 * @param editText
	 */
	public void setEdit(EditText editText) {
		m_edit = editText;
		m_edit.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					FaceView.this.setVisibility(View.GONE);
					setShowImageResource();
				}
				return false;
			}
		});
	}

	public void setHideToggle(View v) {
		v.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					FaceView.this.setVisibility(View.GONE);
					setShowImageResource();
				}
				return false;
			}
		});
	}

	public void setOnFaceSelectedListener(OnFaceSelectedListener listener) {
		m_listener = listener;
	}

	/**
	 * 初始化视图
	 */
	private void initView() {
		if (isInEditMode()) {
			return;
		}
		m_vpFace = (ViewPager) findViewById(R.id.chat_vpFace);
		m_dotBar = (LinearLayout) findViewById(R.id.chat_dotbar);
		initFaceBar();
	}

	private void initFaceBar() {
		m_arrFacePageView = new ArrayList<View>();
		for (int i = 0; i < 9; i++) {
			GridView view = new GridView(m_context);
			FaceAdapter adapter = new FaceAdapter(m_context, i);
			view.setOnItemClickListener(this);
			view.setAdapter(adapter);
			view.setNumColumns(7);
			view.setBackgroundColor(Color.TRANSPARENT);
			view.setHorizontalSpacing(1);
			view.setVerticalSpacing(1);
			view.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
			view.setCacheColorHint(0);
			view.setSelector(new ColorDrawable(Color.TRANSPARENT));
			view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
					LayoutParams.WRAP_CONTENT));
			view.setGravity(Gravity.CENTER);
			m_arrFacePageView.add(view);
		}

		ViewPagerAdapter adapter = new ViewPagerAdapter(m_arrFacePageView);
		if (!isInEditMode()) {
			m_vpFace.setAdapter(adapter);
			m_vpFace.setCurrentItem(1);
		}
		m_vpFace.setOnPageChangeListener(this);
		initDotBar();

	}

	private void initDotBar() {
		m_arrDotView = new ArrayList<ImageView>();

		if (m_arrFacePageView.size() <= 3)
			return;

		for (int i = 0; i < m_arrFacePageView.size() - 2; i++) {
			ImageView imgView = new ImageView(m_context);
			imgView.setBackgroundResource(R.drawable.common_indicator_nor);
			LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
					new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,
							LayoutParams.WRAP_CONTENT));
			DisplayMetrics dm = getResources().getDisplayMetrics();
			params.leftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, dm);
			params.rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, dm);
			// params.width = 7;
			// params.height = 7;
			m_dotBar.addView(imgView, params);
			m_arrDotView.add(imgView);
		}
		setSelDot(0);
	}

	private void setSelDot(int nSelIndex) {
		for (int i = 0; i < m_arrDotView.size(); i++) {
			if (nSelIndex == i) {
				m_arrDotView.get(i).setBackgroundResource(
						R.drawable.common_indicator_checked);
			} else {
				m_arrDotView.get(i).setBackgroundResource(
						R.drawable.common_indicator_nor);
			}
		}
	}

	@Override
	public void onPageSelected(int arg0) {

		if (0 == arg0) {
			m_vpFace.setCurrentItem(arg0 + 1);
		} else if (arg0 == m_arrFacePageView.size() - 1) {
			m_vpFace.setCurrentItem(arg0 - 1);
		} else {
			setSelDot(arg0 - 1);
		}
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View v, int arg2, long arg3) {
		View img = v.findViewById(R.id.facelistitem_imgFace);
		String selImgTag = "";
		int id = Integer.parseInt(img.getTag().toString());
		if (m_tagMode == TAG_MODE_IMG) {
			selImgTag = imgTag.replace("-1", id + "");
		} else {
			selImgTag = getImgTag(id);
		}
		Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
				FaceManager.getInstance().getFace(id));
		if (m_listener != null) {
			m_listener.OnFaceSelected(selImgTag, bitmap);
		}
		if (m_edit != null) {
			Drawable drawable=new BitmapDrawable(m_context.getResources(),bitmap);
			int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, faceDefaultSize, getResources().getDisplayMetrics());
			drawable.setBounds(0, 0, size, size);
			ImageSpan imgSpan = new ImageSpan(drawable);

			SpannableString spanString = new SpannableString(selImgTag);
			spanString.setSpan(imgSpan, 0, spanString.length(),
					Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
			m_edit.append(spanString);
		}
	}

	public interface OnFaceSelectedListener {
		public void OnFaceSelected(String imgTag, Bitmap face);
	}

	@Override
	public void onPageScrollStateChanged(int arg0) {

	}

	@Override
	public void onPageScrolled(int arg0, float arg1, int arg2) {

	}


	@Override
	public void onClick(View v) {
		// 点击输入框,则隐藏表情
		if (v == m_btnView) {
			InputMethodManager imm = (InputMethodManager) m_context
					.getSystemService(Context.INPUT_METHOD_SERVICE);

			if (this.getVisibility() == View.GONE) {
				imm.hideSoftInputFromWindow(getApplicationWindowToken(),
						InputMethodManager.HIDE_NOT_ALWAYS);
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				this.setVisibility(View.VISIBLE);
			} else {
				imm.showSoftInput(m_edit, InputMethodManager.SHOW_IMPLICIT);
				this.setVisibility(View.GONE);
			}
			setShowImageResource();
		}

	}


	private void setShowImageResource() {
		if (textStyleResource == 0 || faceStyleResource == 0) {
			//设置默认显示
			if (m_btnView instanceof ImageView) {
				if (getVisibility() == View.GONE)
					((ImageView)m_btnView).setImageResource(R.drawable.chatform_face_selector);
				else
					((ImageView)m_btnView).setImageResource(R.drawable.chatform_setmodetext_selector);
			}
		}
		else {
			if (getVisibility() == View.GONE)
				m_btnView.setBackgroundResource(faceStyleResource);
			else
				m_btnView.setBackgroundResource(textStyleResource);
		}
	}

	private String getImgTag(int position) {
		String imgTag = "";

		// the number of total image is 134,so when the image number larger than
		// 134 ,them return null
		if (position > 134)
			return null;
		imgTag = position + "";
		switch (imgTag.length()) {
			case 1:
				imgTag = "/e00" + imgTag;
				break;
			case 2:
				imgTag = "/e0" + imgTag;
				break;
			case 3:
				imgTag = "/e" + imgTag;
				break;
			default:
				break;
		}
		return imgTag;
	}

}

二:使用表情库

使用比较简单,在布局文件中添加:
<com.jaiky.test.faceview.FaceView
    android:id="@+id/face_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="gone" >
</com.jaiky.test.faceview.FaceView>

在代码中添加:
//此处绑定表情栏
FaceView faceView = (FaceView) findViewById(R.id.face_view);
//表情的编辑框EditText
faceView.setEdit(etContent);
//弹出表情库的按钮
faceView.setBtnView(ivFace);

设置显示的TextView:
TextView.setText(Html.fromHtml(replyDialog.getContent(), new FaceImageGetter(context), null));


--------------------------------------------------------------------------------------------------------------------
获取源代码及资源文件:
--------------------------------------------------------------------------------------------------------------------

声明

欢迎转载,但请保留文章原始出处
作者:Jaiky_杰哥 
出处:http://blog.csdn.net/jaikydota163/article/details/52098873


  • 38
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值