android TouchImageView 进阶
2016-01-11 17:24
405 查看
实现图片放大缩小控制按钮进行大小缩放,双击放大缩小,移动,多点(两点)缩放功能
DrawImageLayout 包含多张图片,可选择不同图片进行操作
部分代码:
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; } } }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories