android TouchImageView 进阶



实现图片放大缩小控制按钮进行大小缩放,双击放大缩小,移动,多点(两点)缩放功能 


DrawImageLayout 包含多张图片,可选择不同图片进行操作


部分代码:


<DrawImageLayout
        android:id="@+id/template_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/template_title"
        android:layout_marginLeft="12dp"
        android:layout_marginRight="12dp"
        android:layout_marginTop="12dp" >
    </DrawImageLayout>



import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.alibaba.fastjson.JSONObject;
import com.example.touch.R;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;

public class DrawImageLayout extends FrameLayout{

	
	private int id = 0;
	private int load_id = 0;
	private ImageInfo[] pats = null;
	/** 手指头的x坐标 */
	private float X = 0f;
	/** 手指头的y坐标 */
	private float Y = 0f;
	/** 按下时手指头的x坐标与图片的x坐标的距离 **/
	private float CX = 0f;
	/** 按下时手指头的y坐标与图片的y坐标的距离 **/
	private float CY = 0f;

	private int width;
	private int height;
	
	
	
	
	public DrawImageLayout(Context context) {
		super(context);
	}

	public DrawImageLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public DrawImageLayout(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
	}

	//设置界面为正方形
	public void setDisplayMetrics(DisplayMetrics metric) {
		try {
			Class<?> clazz = DrawImageLayout.this.getLayoutParams().getClass();
			int rightMargin = ((Integer) clazz.getField("rightMargin").get(DrawImageLayout.this.getLayoutParams())).intValue();
			int leftMargin = ((Integer) clazz.getField("leftMargin").get(DrawImageLayout.this.getLayoutParams())).intValue();
			width = metric.widthPixels - rightMargin - leftMargin;
			height = width;
			this.getLayoutParams().width = width;
			this.getLayoutParams().height = height;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	

	@Override
	protected void onAttachedToWindow() {
		super.onAttachedToWindow();
//		loadImage();//gg
	}
	
	private int load_count = 0;
	
	public int getLoadCount() {
		return this.load_count;
	}
	
	public int getPatsCount() {
		if (null == pats) {
			return 0;
		}
		return this.pats.length;
	}

	public void loadImage() {
		if (null == pats) {
			return;
		}
		if(load_id != id){
			return;
		}
		load_count = 0;
		id++;
		for (int i = 0; i < pats.length; i++) {
			final int idx = i;
			final OptionImageView iv = new OptionImageView(DrawImageLayout.this.getContext(), pats[i]);
			if(pats[i] != null){
					ImageLoader.getInstance().loadImage(pats[i].getPath(), BitmapUtils.getOptions(),new SimpleImageLoadingListener() {
						
						@Override
						public void onLoadingStarted(String imageUri, View view) {
						}
						
						@Override
						public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
							load_count++;
						}
						
						@Override
						public void onLoadingComplete(String arg0, View img, Bitmap bmp) {
							synchronized (DrawImageLayout.this) {
								initIv(iv,idx,bmp);
								
								SDCardUtils.saveImage(arg0.replaceAll("://","").replaceAll("/",""), bmp);
							}
						}
						
					});
//				}
			}
			
		}
		init = true;
	}
	/**
	 * 初始化OptionImageView
	 */
	private void initIv(OptionImageView iv,int idx, Bitmap bmp){
		if (id != DrawImageLayout.this.id) {//load_id
			return;
		}
//		OptionImageView iv = (OptionImageView)img;
		ImageInfo info = DrawImageLayout.this.pats[idx];
		iv.setPiority(idx);
		iv.setTag(idx);
		LayoutParams pa = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
		float s = 1.0F;
		if (bmp.getWidth() > bmp.getHeight()) {
			s = (float)pats[idx].width / (float)bmp.getWidth();
			int tar_height = (int)(bmp.getHeight() * s);
			pats[idx].setHeight(tar_height);
		} else if(bmp.getWidth() < bmp.getHeight()) {
			s = (float)pats[idx].height / (float)bmp.getHeight();
			int tar_width = (int)(bmp.getWidth() * s);
			pats[idx].setWidth(tar_width);
		} else {
			s = (float)pats[idx].width / (float)bmp.getWidth();
		}

		float preX = pats[idx].getX();
		float preY = pats[idx].getY();
		iv.setPreX(preX);
		iv.setPreY(preY);
		iv.setmWidth(pats[idx].getWidth());
		iv.setmHeight(pats[idx].getHeight());
		iv.setLayoutParams(pa);
		//idx == DrawImageLayout.this.pats.length - 1
		if (idx == DrawImageLayout.this.pats.length - 1) {
			iv.setDrawBorder(true);
			topImageInfo = iv;
			cur_check = idx;
		}
		info.setBit(bmp);
		iv.setImageBitmap(info.getBit());
		iv.getmMatrix().postScale(s, s);
		iv.setImageMatrix(iv.getmMatrix());
		iv.getmMatrix().postTranslate(preX - pats[idx].getWidth() / 2, preY - pats[idx].getHeight() / 2);
		iv.setImageMatrix(iv.getmMatrix());
		
		if(load_count < pats.length){
			iv.clearAnimation();
			Animation anim = selectAnimation(idx);
			if(anim != null){
				iv.startAnimation(anim);
			}
			this.addView(iv, pa);
			load_count++;
			if(load_count == pats.length){
				load_id++;
			}
		}
	}
	/**
	 * 动画
	 * @param idx
	 * @return
	 */
	private Animation selectAnimation(int idx){
		int x = pats[idx].getX();
		int y = pats[idx].getY();
		Animation anim = null;
		if(x <= y){
			anim = AnimationUtils.loadAnimation(YiApplication.getInstance().getApplicationContext(),R.anim.fade_in);
		}else {
			anim = AnimationUtils.loadAnimation(YiApplication.getInstance().getApplicationContext(),R.anim.fade_in2);
		}
		return anim;
	}
	public OptionImageView getCheckImg() {
		if (-1 == cur_check) {
			return null;
		}
		return topImageInfo;
	}

	private boolean init = false;

	public boolean isInit() {
		return init;
	}

	/**
	 * 重置
	 */
	public void reset() {
		this.removeAllViews();
		this.invalidate();
		loadImage();
	}

	/**
	 * 置顶
	 */
	public void top() {
		OptionImageView[] ivs = new OptionImageView[this.getChildCount()];
		OptionImageView t = findTopImage();
		int idx = 0;
		for (int i = 0; i < this.getChildCount(); i++) {
			if (this.getChildAt(i) == t) {
				continue;
			}
			ivs[idx] = (OptionImageView) this.getChildAt(i);
			idx++;
		}
		ivs[idx] = t;

		this.removeAllViews();

		for (int i = 0; i < ivs.length; i++) {
			this.addView(ivs[i]);
		}
	}

	public void up() {
		OptionImageView t = findTopImage();

		int idx = 0;
		for (int i = 0; i < this.getChildCount(); i++) {
			if (this.getChildAt(i) == t) {
				idx = i;
				break;
			}
		}

		if (this.getChildCount() - 1 < idx + 1) {
			return;
		}

		View v1 = this.getChildAt(idx + 1);
		View v2 = this.getChildAt(idx);
		this.removeView(v1);
		this.removeView(v2);
		this.addView(v2, idx);
		this.addView(v1, idx);
	}

	public void down() {
		OptionImageView t = findTopImage();

		int idx = 0;
		for (int i = 0; i < this.getChildCount(); i++) {
			if (this.getChildAt(i) == t) {
				idx = i;
				break;
			}
		}

		if (0 > idx - 1) {
			return;
		}

		View v1 = this.getChildAt(idx - 1);
		View v2 = this.getChildAt(idx);
		this.removeView(v1);
		this.removeView(v2);

		idx = idx - 1;

		if (this.getChildCount() - 1 < idx) {
			idx = this.getChildCount();
		}

		this.addView(v1, idx);
		this.addView(v2, idx);
	}

	@Override
	protected void onDetachedFromWindow() {
		super.onDetachedFromWindow();
	}

	public void setImages(ImageInfo[] paths) {
		if (paths == null)
			return;
		if(pats != null){
			for(int i = 0; i < pats.length; i++){
				ImageInfo info = pats[i];
				Bitmap bit = info.getBit();
				if(bit != null && !bit.isRecycled()){
					bit.recycle();
					bit = null;
				}
			}
		}
		pats = paths;
	}
	public ImageInfo[] getImages(){
		return pats;
	}
	
	
	private OptionImageView topImageInfo = null;
	private float[] rotalP = null;
	private float[] rotalP_2 = null;
	private float preLength = 480.0f;
	private float length = 480.0f;
	private float preCos = 0f;
	private float cos = 0f;
	private boolean bool = true;
	private boolean Begin = true;
	private float[] p1 = new float[2];
	private float[] p2 = new float[2];

	@SuppressLint("ClickableViewAccessibility")
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (null == findTopImage()) {
			return true;
		}
		if(isChange){
			return true;
		}
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			// LogUtil.d(tag, "onTouchEvent() -- 第一根手指点下...");
			actionDown(event);
			break;
		// 副点按下
		case MotionEvent.ACTION_POINTER_DOWN:
			topImageInfo.getSavedMatrix().set(topImageInfo.getmMatrix());
			p2[0] = event.getX(1);
			p2[1] = event.getY(1);
			topImageInfo.setMood(OptionImageView.MOOD_ACTION_POINTERDOWN);
			// LogUtil.d(tag,
			// "onTouchEvent() -- 副手指点下... p2[0]:"+p2[0]+"; p2[1]:"+p2[1]);
			break;
		case MotionEvent.ACTION_UP:
			// LogUtil.d(tag, "onTouchEvent() -- 手指头抬起..");
			CX = 0f;
			CY = 0f;
			topImageInfo.setMood(OptionImageView.MOOD_ACTION_UP);
			Begin = false;
			bool = true;
			return true;
		case MotionEvent.ACTION_POINTER_UP:
			topImageInfo.setMood(OptionImageView.MOOD_ACTION_POINTERUP);
			// LogUtil.d(tag, "onTouchEvent() -- 副手指头抬起..");
			Begin = false;
			bool = true;
			return true;
		case MotionEvent.ACTION_MOVE:
			// LogUtil.d(tag, "onTouchEvent() -- ACTION_MOVE..");
			boolean b = actionMove(event);
			if (b)
				return b;
			break;
		}
		// LogUtil.i(tag, "onTouchEvent() -- 开始刷新..");
		topImageInfo.setImageMatrix(topImageInfo.getmMatrix());
		// invalidate();
		return true;
	}

	private boolean actionMove(MotionEvent event) {
		if (Begin && topImageInfo.getMood() == OptionImageView.MOOD_ACTION_DOWN) {
			// topImageInfo.setMood(OptionImageView.MOOD_ACTION_MOVE);
			if (spacingSingel(event.getX(0), event.getY(0), p1[0], p1[1]) < 5)
				return true;
			p1[0] = event.getX(0);
			p1[1] = event.getY(0);
			// LogUtil.d(tag,
			// "actionMove() -- move.. preX:"+topImageInfo.getPreX()+"; preY:"+topImageInfo.getPreY());
			// 1根手指头移动
			this.X = event.getX();
			this.Y = event.getY();
			topImageInfo.getmMatrix().set(topImageInfo.getSavedMatrix());
			rotalP = rotalPoint(new float[] { this.X, this.Y }, topImageInfo.getPreX(), topImageInfo.getPreY(), topImageInfo.getmMatrix());
			
			// LogUtil.i(tag, "actionMove() -- x:" + rotalC[0] + ";y:" +
			// rotalC[1]);
			float oldPreX = topImageInfo.getPreX();
			float oldPreY = topImageInfo.getPreY();
			topImageInfo.setPreX(X + CX);
			topImageInfo.setPreY(Y + CY);
			topImageInfo.transFrame(topImageInfo.getPreX() - oldPreX, topImageInfo.getPreY() - oldPreY);
			
		}

		// 两指移动
		if (topImageInfo.getMood() == OptionImageView.MOOD_ACTION_POINTERDOWN) {
			float p1J = spacingSingel(event.getX(0), event.getY(0), p1[0], p1[1]);
			float p2J = spacingSingel(event.getX(1), event.getY(1), p2[0], p2[1]);
			// LogUtil.d(tag,
			// "onTouchEvent() -- 副手指  p2[0]:"+p2[0]+"; p2[1]:"+p2[1]+"; 最新的x:"+event.getX(1)+"; y:"+event.getY(1));
			// LogUtil.d(tag,
			// "onTouchEvent() -- 两个点move.. 手指1移动的距离 :"+p1J+";  手指2移动的距离 :"+p2J);
			// 防抖功能
			// 如果两个手指头移动的距离同时都小于5
			if (p1J < 5 && p2J < 5) {
				return true;
			}
			// LogUtil.d(tag,
			// "actionMove() -- MOOD_ACTION_POINTERDOWN.. preX:"+topImageInfo.getPreX()+"; preY:"+topImageInfo.getPreY());
			p1[0] = event.getX(0);
			p1[1] = event.getY(0);
			p2[0] = event.getX(1);
			p2[1] = event.getY(1);
			// topImageInfo.getmMatrix().set(topImageInfo.getSavedMatrix());
			rotalP = rotalPoint(new float[] { event.getX(0), event.getY(0) }, topImageInfo.getPreX(), topImageInfo.getPreY(), topImageInfo.getmMatrix());
			rotalP_2 = rotalPoint(new float[] { event.getX(1), event.getY(1) }, topImageInfo.getPreX(), topImageInfo.getPreY(), topImageInfo.getmMatrix());
			if ((Math.abs(rotalP[0] - topImageInfo.getPreX()) < topImageInfo.getmWidth() / 2f)
					&& (Math.abs(rotalP[1]
						 - topImageInfo.getPreY()) < topImageInfo.getmHeight() / 2f)
					&& (Math.abs(rotalP_2[0]
						 - topImageInfo.getPreX()) < topImageInfo.getmWidth() / 2f)
					&& (Math.abs(rotalP_2[1]
						 - topImageInfo.getPreY()) < topImageInfo.getmHeight() / 2f) || true) {
				if (bool) {
					// 第一次两指头点来,记录下角度和长度
					preLength = spacing(event);
					preCos = cos(event);
					bool = false;
				}
				// 获取最新角度和长度
				length = spacing(event);
				cos = cos(event);
				// LogUtil.i(tag, "actionMove() -- 旋转角度:"+cos);
				float width = topImageInfo.getmWidth();
				float height = topImageInfo.getmHeight();
				// LogUtil.i(tag,
				// "actionMove() -- width:"+width+"; height:"+height);
				// 放大和缩小
				if (length - preLength != 0) {

					float scW = (1.0f + (length - preLength) / length);
					topImageInfo.getmMatrix().postScale(scW, scW, topImageInfo.getPreX(), topImageInfo.getPreY());
					// scale(width/2, height/2, topImageInfo.getPreX(),
					// topImageInfo.getPreY(), topImageInfo.getmMatrix());
					topImageInfo.scalFrame(scW);
				}

				// 旋转
				if (Math.abs(cos) > 5 && Math.abs(cos) < 177
						&& Math.abs(cos - preCos) < 15) {
					topImageInfo.getmMatrix().postRotate(cos - preCos);
					this.getT(width / 2f, height / 2f, topImageInfo.getPreX(), topImageInfo.getPreY(), topImageInfo.getmMatrix());
					topImageInfo.rotateFrame(width, height);
				}
				preCos = cos;
				preLength = length;

			}
		}
		
		
		if(!StringUtils.isEmpty(UserBean.USER_CACHE)){//加入模板缓存
			TemplateUtils.saveTemplate(UserBean.USER_ID, pats,temp_url);
		}
		
		return false;
	}

	@SuppressWarnings("deprecation")
	private boolean actionDown(MotionEvent event) {
		try {
			order(event);
		} catch (Exception e) {
			return true;
		}
		/*设置最顶上的imageview*/
		topImageInfo = findTopImage();
		this.X = event.getX();
		this.Y = event.getY();
		int a = 0;
		
		for (int i = 0; i < getChildCount(); i++) {
			OptionImageView optionImageView = (OptionImageView) getChildAt(i);
			if(optionImageView.isOnView(this.X,this.Y)){
				optionImageView.setAlpha(255);   
			}else{
				a++;
				if(a==getChildCount()){/*当点击范围都不在每个OptionImageView范围内*/
					a = 0;
					for (int j = 0; j < getChildCount(); j++) {
						OptionImageView optionImageView2 = (OptionImageView) getChildAt(j);
						optionImageView2.setAlpha(255);   
					}
				}else{
					optionImageView.setAlpha(150);  
				}
			}
		}
		CX = topImageInfo.getPreX() - event.getX();
		CY = topImageInfo.getPreY() - event.getY();
		topImageInfo.getSavedMatrix().set(topImageInfo.getmMatrix());
		Begin = true;
		p1[0] = event.getX();
		p1[1] = event.getY();
		topImageInfo.setMood(OptionImageView.MOOD_ACTION_DOWN);
		return true;
	}

	/**
	 * 找到优先级最高的view
	 * 
	 * @return
	 */
	private OptionImageView findTopImage() {
		int pre = 0;
		OptionImageView temp = null;
		for (int i = 0; i < getChildCount(); i++) {
			OptionImageView my = (OptionImageView) getChildAt(i);
			if (my.getPiority() > pre) {
				pre = my.getPiority();
				temp = my;
			}
		}
		if(temp != null){
			cur_check = Integer.parseInt(temp.getTag().toString());
		}
		return temp;
	}

	/**
	 * 
	 * @param preX
	 *            图片中心点x
	 * @param preY
	 *            图片中心点y
	 * @param x
	 *            手指头x坐标加上移动的x轴距离
	 * @param y
	 *            手指头y坐标加上移动的y轴距离
	 * @param iv
	 * @return
	 */
	public float[] getT(float preX, float preY, float x, float y, Matrix iv) {
		float[] re = new float[2];
		float[] matrixArray = new float[9];
		iv.getValues(matrixArray);
		float a = x - preX * matrixArray[0] - preY * matrixArray[1];
		float b = y - preX * matrixArray[3] - preY * matrixArray[4];
		matrixArray[2] = a;
		matrixArray[5] = b;
		iv.setValues(matrixArray);
		re[0] = a;
		re[1] = b;
		return re;
	}

	/**
	 * 得到旋转点
	 * 
	 * @param p
	 *            当前手指头的x,y坐标
	 * @param X
	 *            图片之前的x坐标
	 * @param Y
	 *            图片之前的y坐标
	 * @param matrix
	 * @return
	 */
	public float[] rotalPoint(float[] p, float X, float Y, Matrix matrix) {
		float re[] = new float[2];
		float matrixArray[] = new float[9];
		matrix.getValues(matrixArray);
		// LogUtil.i(tag,
		// "rotalPoint() -- matrixArray[0]: "+matrixArray[0]+"; matrixArray[1] :"+matrixArray[1]
		// +"; matrixArray[2] :"+matrixArray[1] );
		// LogUtil.i(tag,
		// "rotalPoint() -- matrixArray[3]: "+matrixArray[3]+"; matrixArray[4] :"+matrixArray[4]
		// +"; matrixArray[5] :"+matrixArray[5] );
		// 计算出x,y的差值
		float a = p[0] - X;
		float b = p[1] - Y;
		// 矩阵公式
		// x' = a*x+b*y+c
		re[0] = a * matrixArray[0] - b * matrixArray[1] + X;
		re[1] = -a * matrixArray[3] + b * matrixArray[4] + Y;
		// re[0] = a * matrixArray[0] + b * matrixArray[1] + X;
		// re[1] = a * matrixArray[3] + b * matrixArray[4] + Y;
		// LogUtil.i(tag, "rotalPoint() -- re[0]: "+re[0]+"; re[1] :"+re[1]
		// +"; a :"+a+"; b:"+b +";X:"+X+";Y:"+Y );
		return re;
	}

	/**
	 * 计算长度
	 * 
	 * @param event
	 * @return
	 */
	private float spacing(MotionEvent event) {
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return (float) Math.sqrt(x * x + y * y);
	}

	private float spacingSingel(float newX, float newY, float oldX, float oldY) {
		float x = newX - oldX;
		float y = newY - oldY;
		return (float) Math.sqrt(x * x + y * y);
	}

	/**
	 * 计算余弦
	 * 
	 * @param event
	 * @return
	 */
	private float cos(MotionEvent event) {
		if ((event.getX(0) - event.getX(1)) * (event.getY(0) - event.getY(1)) > 0) {
			return (float) ((float) Math.acos(Math.abs(event.getX(0) - event.getX(1)) / spacing(event))	/ Math.PI * 180f);
		}
		if ((event.getX(0) - event.getX(1)) * (event.getY(0) - event.getY(1)) < 0) {
			return (float) ((float) Math.acos(-Math.abs(event.getX(0) - event.getX(1)) / spacing(event)) / Math.PI * 180f);
		}
		if (event.getX(0) - event.getX(1) == 0) {
			return (float) 90f;
		}
		if (event.getY(0) - event.getY(1) == 0) {
			return 0f;
		}
		return 45f;
	}

	public float[] scale(float preX, float preY, float x, float y, Matrix matrix) {
		float[] matrixArray = new float[9];
		matrix.getValues(matrixArray);
		float a = x - preX;
		float b = y - preY;
		matrixArray[2] = a;
		matrixArray[5] = b;
		matrix.setValues(matrixArray);
		float[] scale = { a, b };
		return scale;
	}

	public void setToO(Matrix matrix) {
		float[] matrixArray = new float[9];
		matrix.getValues(matrixArray);
		float a = 0f;
		float b = 0f;
		matrixArray[2] = a;
		matrixArray[5] = b;
		matrix.setValues(matrixArray);
	}
	
	private int cur_check = -1;

	public void order(MotionEvent event) {
		OptionImageView temp = null;
		// LogUtil.i(tag,
		// "order() -- event.x:"+event.getX()+";event.y:"+event.getY());
		for (int i = (getChildCount() - 1); i > -1; i--) {
			temp = (OptionImageView) getChildAt(i);
			// LogUtil.i(tag,
			// "order() -- i:"+i+";  width:"+temp.getmWidth()+"; height:"+temp.getmHeight());
			// rotalP = rotalPoint(new float[] { event.getX(), event.getY() },
			// temp.getPreX(),
			// temp.getPreY(),
			// temp.getImageMatrix());
			// 获取触控点
			float tx = event.getX();
			float ty = event.getY();
			// 存放新坐标的数组
			float[] dst = new float[2];
			// 触控点坐标的数组
			float[] src = { tx, ty };
			Matrix matrix = new Matrix();
			// 获取绘制图片的Matrix,并转换mantrix
			// set inverse to be the inverse of this matrix.
			if (temp.getImageMatrix().invert(matrix)) {
				// 触控坐标根据matrix转换成新的坐标,并存放于dst
				matrix.mapPoints(dst, src);
			}
			boolean isSelect = false;
			float[] ma = new float[9];
			temp.getImageMatrix().getValues(ma);

			// LogUtil.i(tag,
			// "order() -- dst[0]:"+dst[0]+" dst[1]:"+dst[1]+"; tx:"+tx+"; ty:"+ty);
			/**
			 * 判断是否击中bitmap
			 */
			if (dst[0] >= 0 && dst[0] <= temp.getmWidth() && dst[1] >= 0 && dst[1] <= temp.getmHeight()) {
				isSelect = true;
				cur_check = Integer.parseInt(temp.getTag().toString());
			}

			if (isSelect) {
				for (int j = (getChildCount() - 1); j > -1; j--) {
					OptionImageView child = (OptionImageView) getChildAt(j);
					if (child.getPiority() > temp.getPiority()) {
						child.setPiority(child.getPiority() - 1);
					}
					child.setDrawBorder(false);
					child.invalidate();
				}
				temp.setPiority(getChildCount() - 1);
				temp.setDrawBorder(true);

				return;
			}
		}
	}


	public class ImageInfo {
		private String path;
		/** 图片宽 **/
		private int width;
		/** 图片高 **/
		private int height;
		/** 左上角的x初始坐标 **/
		private int x;
		/** 左上角的y初始坐标 **/
		private int y;
		
		private int src_x;
		
		private int src_y;
		
		private int src_width;
		
		private int src_height;

		private Bitmap bit = null;

		private DisplayMetrics metric;
		
		private JSONObject option;
		
		private int tag;
		@Override
		public String toString() {
			return "ImageInfo [path=" + path + ", width=" + width + ", height="
					+ height + ", x=" + x + ", y=" + y + ", src_x=" + src_x
					+ ", src_y=" + src_y + ", src_width=" + src_width
					+ ", src_height=" + src_height + ", bit=" + bit
					+ ", metric=" + metric + ", option=" + option + "]";
		}

		public void reset() {
			this.width = this.src_width;
			this.height = this.src_height;
		}

		/**
		 * 200px为基准. 该基准为宽度的1/3.<br />
		 * 坐标位置以600*600区域为准.写下x与y值.
		 * 
		 * @param width
		 * @param height
		 * @param x
		 * @param y
		 * @param path
		 * @param metric
		 */
		public ImageInfo(int width, int height, int x, int y, String path, DisplayMetrics metric, JSONObject option,int tag) {
			this.metric = metric;
			this.width = (int) ((width / 200.0F) * (DrawImageLayout.this.width / 3.0F));
			this.height = (int) ((height / 200.0F) * (DrawImageLayout.this.width / 3.0F));
			this.x = (int) ((width / 200.0F) * (metric.density * 55)/*该位置需要与密度比值计算, 基数55*/) + (int) (x * (DrawImageLayout.this.width / 600.0F));
			this.y = (int) ((width / 200.0F) * (metric.density * 56.25)/*该位置需要与密度比值计算, 基数56.25*/) + (int) (y * (DrawImageLayout.this.height / 600.0F));
			this.path = path;
			this.option = option;
			
			this.src_width = this.width;
			this.src_height = this.height;
			this.src_x = this.x;
			this.src_y = this.y;
			this.tag = tag;
		}

		public int getTag(){
			return tag;
		}
		
		public int getSrc_x() {
			return src_x;
		}

		public int getSrc_y() {
			return src_y;
		}

		public int getSrc_width() {
			return src_width;
		}

		public int getSrc_height() {
			return src_height;
		}

		public String getPath() {
			return path;
		}

		public int getWidth() {
			return width;
		}
		
		public void setWidth(int width) {
			this.width = width;
		}

		public int getHeight() {
			return height;
		}
		
		public void setHeight(int height) {
			this.height = height;
		}

		public int getX() {
			return x;
		}
		
		public void setX(int x) {
			this.x = x;
		}

		public int getY() {
			return y;
		}
		
		public void setY(int y) {
			this.y = y;
		}

		public Bitmap getBit() {
			return bit;
		}

		public void setBit(Bitmap bit) {
			this.bit = bit;
		}

		public JSONObject getOption() {
			return option;
		}
	}
	private boolean isChange = false;

	/**
	 * 隐藏红色边框,设置每件商品的透明度
	 */
	@SuppressWarnings("deprecation")
	public void hiddenCurCK() {
		OptionImageView view = getCheckImg();
		if (null != view){
			view.setDrawBorder(false);
			view.postInvalidate();
		}
		
		for (int i = 0; i < getChildCount(); i++) {
			OptionImageView optionImageView = (OptionImageView) getChildAt(i);
			optionImageView.setAlpha(255);   
		}
		
	}

	public static class OptionImageView extends ImageView {
		/** 左上角的x初始坐标 **/
		private float preX;
		/** 左上角的y初始坐标 **/
		private float preY;
		/** 图片宽 **/
		private float mWidth;
		/** 图片高 **/
		private float mHeight;
		private Matrix mMatrix = new Matrix();
		private Matrix savedMatrix = new Matrix();
		private Matrix scaleMatrix = new Matrix();

		/** 优先级 **/
		private int piority;
		boolean isDrawBorder = false;
		boolean isInit = false;
		private int mood = 0;
		// 手指按下
		public static final int MOOD_ACTION_DOWN = 1;
		// 副手指按下
		public static final int MOOD_ACTION_POINTERDOWN = 2;
		// 副手指离开屏幕
		public static final int MOOD_ACTION_POINTERUP = 3;
		// 手指离开屏幕
		public static final int MOOD_ACTION_UP = 4;
		// 手指离在屏幕上滑动
		public static final int MOOD_ACTION_MOVE = 5;

		private ImageInfo info;

		/**
		 * 存储边框各个点的坐标,依次为左上、右上、右下、左下
		 */
		private float[] mFrame = new float[8];

		public OptionImageView(Context context, ImageInfo info) {
			super(context);
			this.info = info;
			// 设置ScaleType为ScaleType.MATRIX,这一步很重要
			this.setScaleType(ScaleType.MATRIX);
		}

		// 将图片加灰色的边框
		private int color;
		
		public void setColor(int color) {
			this.color = color;
		}
		
		public ImageInfo getInfo() {
			return info;
		}

		@Override
		protected void onDraw(Canvas canvas) {
			super.onDraw(canvas);
			// LogUtil.i(tag, "onDraw() -- isDrawBorder:"+isDrawBorder);
			// 根据MyImageView来获取bitmap对象
			// AsyncDrawable bd = (AsyncDrawable)this.getDrawable();
			if (!isInit) {
				isInit = true;
				this.mWidth = info.width;
				this.mHeight = info.height;
				setDefaultFrame(mWidth / 2, mHeight / 2);
			}
			dra(canvas);
		}

		public float getPreX() {
			return preX;
		}

		public void setPreX(float preX) {
			this.preX = preX;
		}

		public float getPreY() {
			return preY;
		}

		public void setPreY(float preY) {
			this.preY = preY;
		}

		public int getColor() {
			return color;
		}

		public float getmWidth() {
			// 根据MyImageView来获取bitmap对象
			BitmapDrawable bd = (BitmapDrawable) this.getDrawable();
			if (bd != null) {
				this.mWidth = bd.getBitmap().getWidth();
			}
			return mWidth;
		}

		public void setmWidth(float mWidth) {
			this.mWidth = mWidth;
		}

		public float getmHeight() {
			// 根据MyImageView来获取bitmap对象
			BitmapDrawable bd = (BitmapDrawable) this.getDrawable();
			if (bd != null) {
				this.mHeight = bd.getBitmap().getHeight();
			}
			return mHeight;
		}

		public void setmHeight(float mHeight) {
			this.mHeight = mHeight;
		}

		public int getPiority() {
			return piority;
		}

		public void setPiority(int piority) {
			this.piority = piority;
		}

		/**
		 * 设置默认边框,基于中心点的未经旋转的边框
		 * 
		 * @param desX
		 *            中心点距左右边界的距离
		 * @param desY
		 *            中心点距上下边界的距离
		 */
		public void setDefaultFrame(float desX, float desY) {
			mFrame[0] = this.preX - desX;
			mFrame[1] = this.preY - desY;
			mFrame[2] = this.preX + desX;
			mFrame[3] = this.preY - desY;
			mFrame[4] = this.preX + desX;
			mFrame[5] = this.preY + desY;
			mFrame[6] = this.preX - desX;
			mFrame[7] = this.preY + desY;
		}

		/**
		 * 移动边框
		 * 
		 * @param offsetX
		 *            X坐标移动的距离
		 * @param offsetY
		 *            Y坐标移动的距离
		 */
		public void transFrame(float offsetX, float offsetY) {
			mFrame[0] += offsetX;
			mFrame[1] += offsetY;
			mFrame[2] += offsetX;
			mFrame[3] += offsetY;
			mFrame[4] += offsetX;
			mFrame[5] += offsetY;
			mFrame[6] += offsetX;
			mFrame[7] += offsetY;
		}

		public void scalFrame(float scale) {
			rotateFrame(mWidth, mHeight);
		}

		/**
		 * 旋转边框,旋转前先先重置为正常未经旋转的边框,然后根据matrix的旋转值进行旋转 x = x0*cosα + y0*sinα y =
		 * y0*cosα + x0*sinα
		 * 
		 * 矩阵表示如下: x cosα -sinα 0 x0 y = sinα cosα 0 y0 1 0 0 1 1
		 */
		public void rotateFrame(float width, float height) {
			// 设置未经旋转的边框各点坐标值
			setDefaultFrame(width / 2f, height / 2f);

			float[] temp = new float[mFrame.length];
			System.arraycopy(mFrame, 0, temp, 0, mFrame.length);
			// 根据旋转后的matrix值,设置旋转后的边框各点坐标值
			float[] matrixArray = new float[9];
			this.mMatrix.getValues(matrixArray);
			mFrame[0] = temp[0] * matrixArray[0] + temp[1] * matrixArray[1];
			mFrame[1] = temp[1] * matrixArray[4] + temp[0] * matrixArray[3];
			mFrame[2] = temp[2] * matrixArray[0] + temp[3] * matrixArray[1];
			mFrame[3] = temp[3] * matrixArray[4] + temp[2] * matrixArray[3];
			mFrame[4] = temp[4] * matrixArray[0] + temp[5] * matrixArray[1];
			mFrame[5] = temp[5] * matrixArray[4] + temp[4] * matrixArray[3];
			mFrame[6] = temp[6] * matrixArray[0] + temp[7] * matrixArray[1];
			mFrame[7] = temp[7] * matrixArray[4] + temp[6] * matrixArray[3];
			// 根据matrix的偏移值,将边框旋转后产生的偏移再重置回去
			if (matrixArray[2] > mFrame[0]) {
				float offsetX = matrixArray[2] - mFrame[0];
				float offsetY = mFrame[1] - matrixArray[5];
				mFrame[0] += offsetX;
				mFrame[1] -= offsetY;
				mFrame[2] += offsetX;
				mFrame[3] -= offsetY;
				mFrame[4] += offsetX;
				mFrame[5] -= offsetY;
				mFrame[6] += offsetX;
				mFrame[7] -= offsetY;
			} else {
				float offsetX = mFrame[0] - matrixArray[2];
				float offsetY = matrixArray[5] - mFrame[1];
				mFrame[0] -= offsetX;
				mFrame[1] += offsetY;
				mFrame[2] -= offsetX;
				mFrame[3] += offsetY;
				mFrame[4] -= offsetX;
				mFrame[5] += offsetY;
				mFrame[6] -= offsetX;
				mFrame[7] += offsetY;
			}

		}

		/**
		 * 根据传入的x、y判断是否在控件里边
		 * 
		 * @param x
		 * @param y
		 * @return
		 */
		public boolean isOnView(float x, float y) {
			Matrix inMatrix = new Matrix();
			// inMatrix.set(mMatrix);
			mMatrix.invert(inMatrix);
			float[] xy = new float[2];
			inMatrix.mapPoints(xy, new float[] { x, y });
			if (xy[0] > 0 && xy[0] < mWidth && xy[1] > 0 && xy[1] < mHeight) {
				// LogUtil.i(tag, "isOnView() -- 在区域内...");
				return true;
			} else {
				// LogUtil.i(tag, "isOnView() -- 不在区域内...");
			}
			return false;
		}

		@Override
		protected void onAttachedToWindow() {
			super.onAttachedToWindow();

			// LogUtil.i(tag, "onAttachedToWindow() -- dw:"+getDrawable());
		}

		public float[] getmFrame() {
			return mFrame;
		}

		public Matrix getmMatrix() {
			return mMatrix;
		}

		// public void setmMatrix(Matrix mMatrix) {
		// this.mMatrix = mMatrix;
		// }
		class Point {
			float x0, y0, x1, y1, x2, y2, x3, y3;
		}

		private void drawAl(Point point, Canvas canvas, int color, int alpha) {
			// LogUtil.i(tag, "drawAl()");
			Paint paint = new Paint();
			paint.setAntiAlias(true);
			paint.setColor(color);
			paint.setStyle(Style.STROKE);
			paint.setStrokeWidth(4);

			canvas.drawLine(point.x0, point.y0, point.x1, point.y1, paint);
			canvas.drawLine(point.x1, point.y1, point.x2, point.y2, paint);
			canvas.drawLine(point.x2, point.y2, point.x3, point.y3, paint);
			canvas.drawLine(point.x3, point.y3, point.x0, point.y0, paint);
			// canvas.drawPath(p, paint);
		}

		private void dra(Canvas canvas) {
			
			canvas.setDrawFilter(new PaintFlagsDrawFilter(0,
					Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
			
			Point point = new Point();
			point.x0 = mFrame[0];
			point.y0 = mFrame[1];
			point.x1 = mFrame[2];
			point.y1 = mFrame[3];
			point.x2 = mFrame[4];
			point.y2 = mFrame[5];
			point.x3 = mFrame[6];
			point.y3 = mFrame[7];
			int color = Color.parseColor("#f977a7");
			if (!isDrawBorder) {
				color = Color.parseColor("#00000000");
			}
			drawAl(point, canvas, color, 0);
		}

		public void setDrawBorder(boolean isDrawBorder) {
			this.isDrawBorder = isDrawBorder;
		}

		public Matrix getSavedMatrix() {
			return savedMatrix;
		}

		public void setSavedMatrix(Matrix savedMatrix) {
			this.savedMatrix = savedMatrix;
		}

		public int getMood() {
			return mood;
		}

		public void setMood(int mood) {
			this.mood = mood;
		}

		public Matrix getScaleMatrix() {
			return scaleMatrix;
		}

		public void setScaleMatrix(Matrix scaleMatrix) {
			this.scaleMatrix = scaleMatrix;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值