• 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;//<span style="font-family: Arial, Helvetica, sans-serif;">-paint.ascent() 为字体高于baseLine的部分  paint.descent() 为低于baseline的部分</span>
    
            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<LinkInfo> 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("
    ", " ");
    			
    			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<LinkInfo> 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("
    ")){
    				y += fontHeight;
    				curLen = 0;
    			}
    				
    			strContent = strContent.replaceAll("
    ", " ");
    			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<RectF> 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<LinkInfo> 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://download.csdn.net/detail/baidu_nod/7736733

  • 相关阅读:
    [文摘20070723]最经典的爱情观
    [转]ASP .Net C# 下 Word开发资料
    [引]如何藉由使用 Visual C# . NET 處理 Word 中的事件
    简单的搭建Web系统常用的框架页面
    Gentle 简单配置方法之一种
    在 可编辑的 Div 的 光标位置 插入 文字 或 HTML
    [转]使用FileUpload控件上传图片并自动生成缩略图、自动生成带文字和图片的水印图
    VS2005 添加 Microsoft.Office.Tools.Word.dll 等引用
    要事第一 事不过三
    VC slider用法
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5075555.html
Copyright © 2020-2023  润新知