Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android如果重寫onDraw實現一個類似TextView可以顯示表情和鏈接的控件(二)

android如果重寫onDraw實現一個類似TextView可以顯示表情和鏈接的控件(二)

編輯:關於Android編程

下面來寫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://download.csdn.net/detail/baidu_nod/7736733

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved