自定义ImageView,实现点击之后算出点击的是身体的哪个部位
最近也是因为项目的原因,所以有机会接触到这边的算法。 此文重点不是如何实现的思路和原理, 有需要的同事可以借鉴一下
废话不多说,直接上代码:
public class MyImage extends ImageView {private DisplayMetrics dm;private int bodyImageViewHeight = 0;private int bodyImageViewWidth = 0;public MyImage(Context context) {super(context);}public MyImage(Context context, AttributeSet attrs) {super(context, attrs);dm = context.getResources().getDisplayMetrics();}@Overridepublic boolean onTouchEvent(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();//初始化各个部位的范围initParametersForRegion();if(isTouchPointInTransparent(x, y)) {Log.e("mcoy", "the point is in transparent area now");} else {positionType position = pointToPosition(x, y);Log.e("mcoy", "the position is " + position);}return super.onTouchEvent(event);}private enum positionType{REGION_FRONT_HAND,REGION_FRONT_HEAD,REGION_FRONT_CHEST,REGION_FRONT_WAIST,REGION_FRONT_LEG}private positionType pointToPosition(int x, int y) {if(x < mHandX1 || x > mHandX2)return positionType.REGION_FRONT_HAND;else if (y < mHeadY)return positionType.REGION_FRONT_HEAD;else if(y < mChestY)return positionType.REGION_FRONT_CHEST;else if(y < mWaistY)return positionType.REGION_FRONT_WAIST;elsereturn positionType.REGION_FRONT_LEG;}/**** @param x* @param y* @return 判断点击区域是否在透明区域*/private boolean isTouchPointInTransparent(int x, int y) {int paddingLeft = this.getPaddingLeft();int paddingTop = this.getPaddingTop();int imageHeight = this.getHeight();int imageWidth = this.getWidth();Drawable drawable = this.getDrawable();Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();int intrinsicHeight = drawable.getIntrinsicHeight();int intrinsicWidth = drawable.getIntrinsicWidth();int locationInBitmapX = (x - paddingLeft) * intrinsicWidth / imageWidth;int locationInBitmapY = (y - paddingTop) * intrinsicHeight / imageHeight;int pixel = bitmap.getPixel(locationInBitmapX, locationInBitmapY);Log.e("mcoy", "x is " + x);Log.e("mcoy", "y is " + y);Log.e("mcoy", "imageHeight is " + imageHeight);Log.e("mcoy", "imageWidth is " + imageWidth);Log.e("mcoy", "intrinsicHeight is " + intrinsicHeight);Log.e("mcoy", "intrinsicWidth is " + intrinsicWidth);Log.e("mcoy", "locationInBitmapX is " + locationInBitmapX);Log.e("mcoy", "locationInBitmapY is " + locationInBitmapY);Log.e("mcoy", "actualBitmapX is " + locationInBitmapX / dm.density);Log.e("mcoy", "actualBitmapY is " + locationInBitmapY / dm.density);Log.e("mcoy", "pixel is " + pixel);return pixel == 0;}private int mHeadY;private int mHandX1;private int mHandX2;private int mChestY;private int mWaistY;//以下数据需要同UI同事沟通好每个部位定义的范围,或者自己手动量一下private final int HEAD_AREA = 130;private final int LEFT_HAND_AREA = 126;private final int RIGHT_HAND_AREA = 280;private final int CHEST_AREA = 260;private final int WAIST_AREA = 417;private void initParametersForRegion() {if(bodyImageViewHeight != this.getHeight()) {bodyImageViewHeight = this.getHeight();bodyImageViewWidth = this.getWidth();int imageIntrinsicHeight = this.getDrawable().getIntrinsicHeight();int imageIntrinsicWidht = this.getDrawable().getIntrinsicWidth();Log.e("danny", "bodyImageViewHeight is " + bodyImageViewHeight);Log.e("danny", "bodyImageViewWidth is " + bodyImageViewWidth);Log.e("danny", "imageIntrinsicHeight is " + imageIntrinsicHeight);Log.e("danny", "imageIntrinsicWidht is " + imageIntrinsicWidht);mHeadY = DensityUtil.dip2px(getContext(), HEAD_AREA) * bodyImageViewHeight / imageIntrinsicHeight+ this.getPaddingTop();mHandX1 = DensityUtil.dip2px(getContext(), LEFT_HAND_AREA) * bodyImageViewWidth / imageIntrinsicWidht+ this.getPaddingLeft();mHandX2 = DensityUtil.dip2px(getContext(), RIGHT_HAND_AREA) * bodyImageViewWidth / imageIntrinsicWidht+ this.getPaddingLeft();mChestY = DensityUtil.dip2px(getContext(), CHEST_AREA) * bodyImageViewHeight / imageIntrinsicHeight+ this.getPaddingTop();mWaistY = DensityUtil.dip2px(getContext(), WAIST_AREA) * bodyImageViewHeight / imageIntrinsicHeight+ this.getPaddingTop();Log.e("danny", "mHeadY is " + mHeadY);Log.e("danny", "mHandX1 is " + mHandX1);Log.e("danny", "mHandX2 is " + mHandX2);Log.e("danny", "mChestY is " + mChestY);Log.e("danny", "mWaistY is " + mWaistY);}}
}
代码很简单, 就是一个自己实现的ImageView, 但是有几点需要注意的点:
1 图片需要跟UI同事沟通好相应坐标(认真看完代码之后就会知道原因), 如果换图片的话,那HEAD_AREA等值可能需要重新定义
2 算法思路---在不同的desity的的设备上, 我们都可以算出图片对应的drawable的width/height,而图片缩放或者是放大是按照比例缩放/放大, 因此我们可以得出如下等式:
touchX / imageWidth = positonInBitmap / drawable.getIntransicWidth ;
==> positonInBitmap = touchX * drawable.getIntransicWidth / imageWidth;
touchX是点击在ImageView上的x坐标;imageWidth是图片的宽度;positionInBitmap是touchX映射在ImageView所对应drawable上的x坐标(这句话有点拗口,可以仔细想一下)
以下是xml文件:
也有一点需要注意:
需要将adjustViewBounds属性设置为true,这样会调整ImageView的界限来保持图像纵横比不变
demo下载链接:http://download.csdn.net/detail/zxm317122667/9000969
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
