近期也是由于项目的原因,所以有机会接触到这边的算法。 此文重点不是怎样实现的思路和原理, 有须要的同事能够借鉴一下

废话不多说,直接上代码:

  1. <span style="font-size:18px;"><span style="font-size:18px;">public class MyImage extends ImageView {
  2.  
  3. private DisplayMetrics dm;
  4.  
  5. private int bodyImageViewHeight = 0;
  6. private int bodyImageViewWidth = 0;
  7.  
  8. public MyImage(Context context) {
  9. super(context);
  10. }
  11.  
  12. public MyImage(Context context, AttributeSet attrs) {
  13. super(context, attrs);
  14. dm = context.getResources().getDisplayMetrics();
  15. }
  16.  
  17. @Override
  18. public boolean onTouchEvent(MotionEvent event) {
  19.  
  20. int x = (int) event.getX();
  21. int y = (int) event.getY();
  22.  
  23. //初始化各个部位的范围
  24. initParametersForRegion();
  25.  
  26. if(isTouchPointInTransparent(x, y)) {
  27. Log.e("mcoy", "the point is in transparent area now");
  28. } else {
  29. positionType position = pointToPosition(x, y);
  30. Log.e("mcoy", "the position is " + position);
  31. }
  32.  
  33. return super.onTouchEvent(event);
  34. }
  35.  
  36. private enum positionType{
  37. REGION_FRONT_HAND,
  38. REGION_FRONT_HEAD,
  39. REGION_FRONT_CHEST,
  40. REGION_FRONT_WAIST,
  41. REGION_FRONT_LEG
  42. }
  43.  
  44. private positionType pointToPosition(int x, int y) {
  45. if(x < mHandX1 || x > mHandX2)
  46. return positionType.REGION_FRONT_HAND;
  47. else if (y < mHeadY)
  48. return positionType.REGION_FRONT_HEAD;
  49. else if(y < mChestY)
  50. return positionType.REGION_FRONT_CHEST;
  51. else if(y < mWaistY)
  52. return positionType.REGION_FRONT_WAIST;
  53. else
  54. return positionType.REGION_FRONT_LEG;
  55. }
  56.  
  57. /**
  58. *
  59. * @param x
  60. * @param y
  61. * @return 推断点击区域是否在透明区域
  62. */
  63. private boolean isTouchPointInTransparent(int x, int y) {
  64.  
  65. int paddingLeft = this.getPaddingLeft();
  66. int paddingTop = this.getPaddingTop();
  67.  
  68. int imageHeight = this.getHeight();
  69. int imageWidth = this.getWidth();
  70.  
  71. Drawable drawable = this.getDrawable();
  72. Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
  73.  
  74. int intrinsicHeight = drawable.getIntrinsicHeight();
  75. int intrinsicWidth = drawable.getIntrinsicWidth();
  76.  
  77. int locationInBitmapX = (x - paddingLeft) * intrinsicWidth / imageWidth;
  78. int locationInBitmapY = (y - paddingTop) * intrinsicHeight / imageHeight;
  79.  
  80. int pixel = bitmap.getPixel(locationInBitmapX, locationInBitmapY);
  81.  
  82. Log.e("mcoy", "x is " + x);
  83. Log.e("mcoy", "y is " + y);
  84. Log.e("mcoy", "imageHeight is " + imageHeight);
  85. Log.e("mcoy", "imageWidth is " + imageWidth);
  86. Log.e("mcoy", "intrinsicHeight is " + intrinsicHeight);
  87. Log.e("mcoy", "intrinsicWidth is " + intrinsicWidth);
  88. Log.e("mcoy", "locationInBitmapX is " + locationInBitmapX);
  89. Log.e("mcoy", "locationInBitmapY is " + locationInBitmapY);
  90. Log.e("mcoy", "actualBitmapX is " + locationInBitmapX / dm.density);
  91. Log.e("mcoy", "actualBitmapY is " + locationInBitmapY / dm.density);
  92. Log.e("mcoy", "pixel is " + pixel);
  93.  
  94. return pixel == 0;
  95. }
  96.  
  97. private int mHeadY;
  98. private int mHandX1;
  99. private int mHandX2;
  100. private int mChestY;
  101. private int mWaistY;
  102.  
  103. //下面数据须要同UI同事沟通好每一个部位定义的范围。或者自己手动量一下
  104. private final int HEAD_AREA = 130;
  105. private final int LEFT_HAND_AREA = 126;
  106. private final int RIGHT_HAND_AREA = 280;
  107. private final int CHEST_AREA = 260;
  108. private final int WAIST_AREA = 417;
  109.  
  110. private void initParametersForRegion() {
  111.  
  112. if(bodyImageViewHeight != this.getHeight()) {
  113.  
  114. bodyImageViewHeight = this.getHeight();
  115. bodyImageViewWidth = this.getWidth();
  116. int imageIntrinsicHeight = this.getDrawable().getIntrinsicHeight();
  117. int imageIntrinsicWidht = this.getDrawable().getIntrinsicWidth();
  118. Log.e("danny", "bodyImageViewHeight is " + bodyImageViewHeight);
  119. Log.e("danny", "bodyImageViewWidth is " + bodyImageViewWidth);
  120. Log.e("danny", "imageIntrinsicHeight is " + imageIntrinsicHeight);
  121. Log.e("danny", "imageIntrinsicWidht is " + imageIntrinsicWidht);
  122.  
  123. mHeadY = DensityUtil.dip2px(getContext(), HEAD_AREA) * bodyImageViewHeight / imageIntrinsicHeight
  124. + this.getPaddingTop();
  125. mHandX1 = DensityUtil.dip2px(getContext(), LEFT_HAND_AREA) * bodyImageViewWidth / imageIntrinsicWidht
  126. + this.getPaddingLeft();
  127. mHandX2 = DensityUtil.dip2px(getContext(), RIGHT_HAND_AREA) * bodyImageViewWidth / imageIntrinsicWidht
  128. + this.getPaddingLeft();
  129. mChestY = DensityUtil.dip2px(getContext(), CHEST_AREA) * bodyImageViewHeight / imageIntrinsicHeight
  130. + this.getPaddingTop();
  131. mWaistY = DensityUtil.dip2px(getContext(), WAIST_AREA) * bodyImageViewHeight / imageIntrinsicHeight
  132. + this.getPaddingTop();
  133.  
  134. Log.e("danny", "mHeadY is " + mHeadY);
  135. Log.e("danny", "mHandX1 is " + mHandX1);
  136. Log.e("danny", "mHandX2 is " + mHandX2);
  137. Log.e("danny", "mChestY is " + mChestY);
  138. Log.e("danny", "mWaistY is " + mWaistY);
  139.  
  140. }
  141. }
  142. }</span></span>

代码非常easy, 就是一个自己实现的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文件:

  1. <span style="font-size:18px;"><span style="font-size:18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingBottom="@dimen/activity_vertical_margin"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. tools:context="com.mcoy.pixelinbitmaptest.MainActivity" >
  10.  
  11. <TextView
  12. android:id="@+id/tv"
  13. android:layout_width="wrap_content"
  14. android:layout_height="80dp"
  15. android:text="@string/hello_world" />
  16.  
  17. <com.example.jiangxinxing.views.MyImage
  18. android:id="@+id/iv"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:adjustViewBounds="true"
  22. android:scaleType="fitXY"
  23. android:src="@drawable/man_front"
  24. android:layout_below="@+id/tv" />
  25.  
  26. </RelativeLayout></span></span>

也有一点须要注意:

须要将adjustViewBounds属性设置为true。这样会调整ImageView的界限来保持图像纵横比不变

demo下载链接:http://download.csdn.net/detail/zxm317122667/9000969

自己定义ImageView,实现点击之后算出点击的是身体的哪个部位的更多相关文章

  1. Android 自己定义ImageView实现圆角/圆形 附加OnTouchListener具体凝视以及Button圆角

    转载请注明出处:王亟亟的大牛之路 平时要用一些非方方正正的button之类的小伙伴们是怎样实现的?RadioButton? ImageButton? 还是其它? 今天亟亟上的是ImageView来实现 ...

  2. 实现RecycleView动态使列表item可以点击或不可点击切换

    效果 这里讲的是第二个button跳转的Activity,这里和上一篇不同之处在于可以item点击.item子控件点击 继承BaseAdapter 同样也要继承BaseAdapter public c ...

  3. 利用Kotlin扩展函数实现任意View的点击处理(点击效果和防止快速点击)

    利用Kotlin扩展函数实现View的点击处理(点击效果和防止快速点击) kotlin经典写法: view?.setOnClickListener { //实现 } 项目实践证明,这种写法存在问题 例 ...

  4. 点击li,点击的li添加class,其余去掉class

    点击li,点击的li添加class,其余去掉class <script type="text/javascript"> $(function () { var liob ...

  5. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验三:按键模块② — 点击与长点击

    实验三:按键模块② - 点击与长点击 实验二我们学过按键功能模块的基础内容,其中我们知道按键功能模块有如下操作: l 电平变化检测: l 过滤抖动: l 产生有效按键. 实验三我们也会z执行同样的事情 ...

  6. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验五:按键模块④ — 点击,长点击,双击

    实验五:按键模块④ - 点击,长点击,双击 实验二至实验四,我们一共完成如下有效按键: l 点击(按下有效) l 点击(释放有效) l 长击(长按下有效) l 双击(连续按下有效) 然而,不管哪个实验 ...

  7. jquery对类的操作,添加,删除,点击添加,再点击删除

    jquery对类的操作,添加(addClass),删除l类(remoceClass),点击添加,再点击删除(toggleClass)

  8. C# Chart 点击获取当前点击坐标和Series

    C# Chart 点击获取当前点击坐标和Series https://blog.csdn.net/wumuzhizi/article/details/47168989 2015年07月31日 13:5 ...

  9. input radio点击选中再点击取消

    这里主要说一下这个jquery中的data()方法,个人感觉这个方法平时挺少用到的,所以说一说,按照官方的解释就是 向元素附加数据,然后取回该数据; 嗯,是的,就是这么简单. 那这里说一下这个方法的使 ...

随机推荐

  1. 大数据学习——spark-steaming学习

    官网http://spark.apache.org/docs/latest/streaming-programming-guide.html 1.1.  用Spark Streaming实现实时Wor ...

  2. 51nod 1010 只包含因子2 3 5的数 二分答案

    1010 只包含因子2 3 5的数 K的因子中只包含2 3 5.满足条件的前10个数是:2,3,4,5,6,8,9,10,12,15. 所有这样的K组成了一个序列S,现在给出一个数n,求S中 > ...

  3. 【Luogu】P3389高斯消元模板(矩阵高斯消元)

    题目链接 高斯消元其实是个大模拟qwq 所以就着代码食用 首先我们读入 ;i<=n;++i) ;j<=n+;++j) scanf("%lf",&s[i][j]) ...

  4. 浅谈android反调试之 签名校验

    反调试原理 很多时候,我们都需要进行修改修改应用程序的指令,然后重打包运行,重新打包就需要充签名. 利用签名的变化我们用于反调试.反调试实现代码如下: 为了更加隐藏,比较函数可能在SO层进行实现,如下 ...

  5. 【前端学习笔记】2015-09-09~~~~nodejs中的require()和module.exports

    nodejs中一个js文件就可以看做是一个模块 在node环境中,可以直接var a=require('模块路径以及不带扩展名的模块名') exports---module.exports 其中nod ...

  6. Django标签之包含标签Inclusion tags

    Django过滤器和标签功能很强大,而且支持自定义标签,很是方便:其中一种标签是Inclusion tags,即包含标签,个人感觉比较反人类的 包含标签(Inclusion tags)通过渲染其他的模 ...

  7. d3 使用数据

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. build android on macOS

    http://blog.csdn.net/loften_93663469/article/details/51503293 @import url(http://i.cnblogs.com/Load. ...

  9. py2exe打包整个项目

    这段时间做了用Python做了一个科学计算的项目,项目中用到了很多的第三方Python库,包括PyQt.traits.traitsui.matplotlib.pyface.table.numpy.tv ...

  10. LeetCode OJ——Minimum Depth of Binary Tree

    http://oj.leetcode.com/problems/minimum-depth-of-binary-tree/ 贡献了一次runtime error,因为如果输入为{}即空的时候,出现了c ...