android 表情控件,android如果重写onDraw实现一个类似TextView可以显示表情和链接的控件(二)...

下面来写IntroView的onMeasureHeight:

private int measureHeight(int measureSpec) {

int result = 0;

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

Paint paint = new Paint();

paint.setTextSize(getTextSize());

paint.setAntiAlias(true);

paint.setStyle(Style.FILL);

displayHeight = -paint.ascent() + paint.descent() + 2;//-paint.ascent() 为字体高于baseLine的部分 paint.descent() 为低于baseline的部分

measureList(paint, titleList, 0);

if (specMode == MeasureSpec.EXACTLY) {

result = specSize;

} else {

if (specMode == MeasureSpec.AT_MOST) {

result = Math.min((int)displayHeight, specSize);

}

else{

result = (int)displayHeight;

}

}

return result;

}

private float measureList(Paint paint, ArrayList infoList, float StartX){

if(infoList == null || infoList.size() == 0){

displayHeight = StartX;

return StartX;

}

float x = StartX;

int len = infoList.size();

//FontMetrics fontMetrics = paint.getFontMetrics();

float fontHeight = -paint.ascent() + paint.descent();//fontMetrics.bottom - fontMetrics.top;

for(int i = 0; i < len; i++){

LinkInfo info = infoList.get(i);

//这里开始计算每个链接的点击区域

info.getRectFList().clear();

if(info.isFace()){//表情符排版

Bitmap faceBmp = null;

if(mFaceType == MSG_FACE_TYPE) {

faceBmp = MessageFaceModel.getInstance().getFaceIcon(info.getContent());

}

if(faceBmp != null){

int xLen = faceBmp.getWidth() + 4;//表情图标左右各空两个像素

if(x + xLen >= displayWidth){

displayHeight += fontHeight;

x = 0;

}

x += xLen;

}

continue;

}

String strContent = info.getContent();

strContent = strContent.replaceAll("\n", " ");

float xLen = paint.measureText(strContent);

//这里处理换行的情况

if(x + xLen >= displayWidth){

float startX = x;

int lenStr = strContent.length();

for(int j = 0; j < lenStr; j++){

float width = paint.measureText(strContent, j, j + 1);

if(x + width >= displayWidth){

RectF rectF = new RectF();

rectF.set(startX, displayHeight - fontHeight, x, displayHeight);

info.addRectF(rectF);

displayHeight += fontHeight;

x = width;//下一行的X方向起始偏移量,width是一个字符的偏移量,所以这里rectF只在换行的时候执行一次

startX = 0;

}else{

x += width;

}

}

RectF rectF = new RectF();

//如果换行则startX为0,x为第下一行的宽度

rectF.set(startX, displayHeight - fontHeight, x - startX, displayHeight);

info.addRectF(rectF);

}

else{

RectF rectF = new RectF();

rectF.set(x, displayHeight - fontHeight, x + xLen, displayHeight);

info.addRectF(rectF);

x += xLen;

}

}

return x;

}

onDraw:

@Override

protected void onDraw(Canvas canvas){

super.onDraw(canvas);

try{

if(titleList == null || titleList.size() == 0){

return;

}

curLen = 0;

Paint paint = new Paint();

paint.setTextSize(getTextSize());

paint.setAntiAlias(true);

paint.setStyle(Style.FILL);

float y = -paint.ascent();//(fontMetrics.bottom - fontMetrics.ascent);

y = drawList(canvas, paint, titleList, y);

}catch(Exception ex){

}

}

private float drawList(Canvas canvas, Paint paint, ArrayList infoList, float StartY){

if(infoList == null || infoList.size() == 0){

return StartY;

}

float y = StartY;

float fontHeight = -paint.ascent() + paint.descent();//fontMetrics.bottom - fontMetrics.ascent;

int len = infoList.size();

int color = getCurrentTextColor();

for(int i = 0; i < len; i++){

LinkInfo info = infoList.get(i);

if(info.isFace()){//表情符排版

Bitmap faceBmp = null;

if(mFaceType == MSG_FACE_TYPE) {

faceBmp = MessageFaceModel.getInstance().getFaceIcon(info.getContent());

}

if(faceBmp != null){

int xLen = faceBmp.getWidth() + 4;//表情图标左右各空两个像素

if(curLen + xLen >= displayWidth){

y += fontHeight;

curLen = 0;

}

canvas.drawBitmap(faceBmp, curLen + 2, y - fontHeight + 4, paint);

curLen += xLen;

}

continue;

}

String strContent = info.getContent();

if(mFaceType == MSG_FACE_TYPE && strContent.startsWith("\n")){

y += fontHeight;

curLen = 0;

}

strContent = strContent.replaceAll("\n", " ");

if((info.isEmail() || info.isPhoneNumber() || info.isWebUrl()) && info.isSelected()){

paintSelectRectF(canvas, paint, info);

}

float xLen = paint.measureText(strContent);

int starLen = 0;

if(info.isCommonString()){

paint.setColor(color);

}else{

paint.setColor(getResources().getColor(R.drawable.blue1));

}

if(curLen + xLen + starLen >= displayWidth){

int lenStr = strContent.length();

for(int j = 0; j < lenStr; j++){

float width = paint.measureText(strContent, j, j + 1);

if(curLen + width >= displayWidth){

y += fontHeight;

curLen = 0;

}

canvas.drawText(strContent, j, j + 1, curLen, y, paint);

curLen += width;

}

}else{

canvas.drawText(strContent, curLen, y, paint);

curLen += xLen;

}

}

return y;

}

onTouch事件,可以点击Text里面的链接(email,phone)

@Override

public boolean onTouchEvent(MotionEvent event){

super.onTouchEvent(event);

if(!this.isEnabled() || Listener == null){

return false;

}

if(event.getAction() == MotionEvent.ACTION_UP){

float x = event.getX();

float y = event.getY();

boolean flag = cancelCurInfo(x, y);

if(flag){

return false;//up时的坐标已经不在down时记录的Link对象中,则直接返回

}

if(clickLink(titleList, x, y, MotionEvent.ACTION_UP)){

//Log.i("curInfo", "ACTION_UP");

return true;

}

}

else if(event.getAction() == MotionEvent.ACTION_DOWN){

float x = event.getX();

float y = event.getY();

boolean flag = clickLink(titleList, x, y, MotionEvent.ACTION_DOWN);

if(flag){

//Log.i("curInfo", "ACTION_DOWN");

return true;

}

}

else{

float x = event.getX();

float y = event.getY();

cancelCurInfo(x, y);

}

return false;

}

private void paintSelectRectF(Canvas canvas, Paint paint, LinkInfo info){

ArrayList rectList = info.getRectFList();

int len = rectList.size();

for(int i = 0; i < len; i++){

RectF rectF = rectList.get(i);

paint.setColor(this.getContext().getResources().getColor(R.drawable.gray3));

canvas.drawRect(rectF.left, rectF.top - 2, rectF.right, rectF.bottom - 2, paint);

}

}

/** x,y所代表的点已经不在当前Link对象中,则清除掉当前Link对象的选中效果 */

private boolean cancelCurInfo(float x, float y){

if(curInfo == null){

return true;

}

if(!curInfo.contains(x, y)){

curInfo.setSelected(false);

this.invalidate();

curInfo = null;

return true;

}

return false;

}

private boolean clickLink(ArrayList infoList, float x, float y, int action){

if(infoList == null){

return false;

}

int len = infoList.size();

for(int i = 0; i < len; i++){

LinkInfo info = infoList.get(i);

if(info.isCommonString()){

continue;

}

if(info.contains(x, y)){

if(action == MotionEvent.ACTION_DOWN){

info.setSelected(true);

this.invalidate();

this.curInfo = info;

}

else if(action == MotionEvent.ACTION_UP){

this.curInfo = null;

info.setSelected(false);

this.invalidate();

Listener.onClick(info);

}

return true;

}

}

return false;

}

Listener:

private OnClickLinkListener Listener;

public void setOnClickLinkListener(OnClickLinkListener listener){

this.Listener = listener;

}

public interface OnClickLinkListener{

/**点击了动态中的某个链接对象*/

public abstract void onClick(LinkInfo linkInfo);

}

原文:http://blog.csdn.net/baidu_nod/article/details/38470275

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值