自定义ImageView,实现点击之后算出点击的是身体的哪个部位

最近也是因为项目的原因,所以有机会接触到这边的算法。 此文重点不是如何实现的思路和原理, 有需要的同事可以借鉴一下

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

<span style="font-size:18px;"><span style="font-size:18px;">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();
    }

    @Override
    public 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;
        else
            return 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);

        }
    }
}</span></span>

代码很简单, 就是一个自己实现的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文件:

<span style="font-size:18px;"><span style="font-size:18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.mcoy.pixelinbitmaptest.MainActivity" >

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:text="@string/hello_world" />

    <com.example.jiangxinxing.views.MyImage
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="fitXY"
        android:src="@drawable/man_front"
        android:layout_below="@+id/tv" />

</RelativeLayout></span></span>

也有一点需要注意:

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

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-08 01:41:10

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

自己定义ImageView,实现点击之后算出点击的是身体的哪个部位

近期也是由于项目的原因,所以有机会接触到这边的算法. 此文重点不是怎样实现的思路和原理, 有须要的同事能够借鉴一下 废话不多说,直接上代码: <span style="font-size:18px;"><span style="font-size:18px;">public class MyImage extends ImageView { private DisplayMetrics dm; private int bodyImageVie

自定义ImageView实现局部截图功能

1.前言 最近在做一个能够自选区域进行局部截图的功能,接下来,会给大家讲解,整个截图的实现过程.笔者这边实现的自选区域的形状是矩形,读者如果有需要,可以根据我给大家讲解的思路,修改成适合自己的截图工具.先来看看效果图 2.效果图 这里的图片是来自笔者对webView的截图产生的,读者可以根据自己的需要,替换上面的图片. 通过拖拽四条边框,可以实现屏幕的局部截图: 拖拽之后,只有需要截图的部分才会高亮显示,其余部分用遮罩掩盖.笔者实现的拖拽四条边都可以任意拖拽,并不一定要正方形或者长方形.也可以如

Android 自定义ImageView实现圆角/圆形 附加OnTouchListener详细注释以及Button圆角

转载请注明出处:王亟亟的大牛之路 平时要用一些非方方正正的按钮之类的小伙伴们是如何实现的?RadioButton?ImageButton?还是其他? 今天亟亟上的是ImageView来实现的 先上下效果图(目录结构) 分析: shape.xml用于Button的"倒角"(做过机械类的都懂,哈哈) attr.xml用于自定义ImageView的标签的定义 ids.xml用于控件findbyid用,为什么补+id 等会我会来解释 效果图: 分析:一个Button 2个自定义ImageVie

自定义ImageView实现图片手势滑动,多点触摸放大缩小效果

首先呢,还是一贯作风,我们先来看看众多应用中的示例:(这种效果是很常见的,可以说应用的必须品.)                搜狐客户端                                    百度新闻客户端                              新浪微博                              凤凰新闻客户端 也许大家对这些客户端并不陌生,但是不知道大家有没有注意到这些不足之处呢,这里我就叨唠吓这些不人性化的地方. 首先搜狐:她的图片放大后

自定义Imageview控件实现多种手势操作 (拖动、水平缩放、竖直缩放、等比例缩放、双击、长按)

项目中需要使用自定义控件的多种手势操作,之前在网上查阅资料的时候发现能找到的一般是只实现了其中的几种,这次就把我做的控件分享一下,人人为我,我为人人嘛,哈哈! 这个自定义控件实现的主要功能是控件的拖动和缩放(注意:不是对控件中的图片进行操作,话说很多帖子都把这两个混了),其中缩放可以按照三个方向进行,就是水平.竖直和等比例.双击操作只做了一个提示,长按加上了一个简单的弹出菜单. 抱歉的是没有足够的时间写详细注释了,如果跟你需要的功能相同就请直接调用,要是需要改代码就费点神自己读懂代码吧,看不懂的

Android自定义ImageView实现图片圆形 ,椭圆和矩形圆角显示

Android中的ImageView只能显示矩形的图片,为了用户体验更多,Android实现圆角矩形,圆形或者椭圆等图形,一般通过自定义ImageView来实现,首先获取到图片的Bitmap,然后通过Paint和onDraw()进行圆形图片显示. 效果图: 代码: 1 activity_image.xml 2 <?xml version="1.0" encoding="utf-8"?> 3 <LinearLayoutxmlns:android=&q

SalesForce自定义按钮(javascript执行),点击按钮更新Filed

学salesforce一个多月了,文档也看了不少,但大都是没有深究.salesforce国外很多文档资料,以前做java时百度很多都可以解决,现在做salesforce倒是提升了不少谷歌搜索的能力. 谷歌很多的东西在中国都是给屏蔽掉了,一般搜索不了什么东西,建议谷歌浏览器翻下墙(附上百度一http://jingyan.baidu.com/article/c85b7a64562eac003bac95b1.html). 创建自定义按钮点击更新字段: 1 进入salesforce的开发主页,没有就申请

android自定义组件监听,监听网络,防止组件点击过快重复点击

1 组件监听事件,业务逻辑之前判断网络情况 public abstract class OnClickNetworkListener implements View.OnClickListener { @Override public void onClick(View v) { boolean isNetworkOk = Config.isNetworkConnected(Config.currentContext); if (isNetworkOk) { onNetworkClick(v);

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

实验三:按键模块② - 点击与长点击 实验二我们学过按键功能模块的基础内容,其中我们知道按键功能模块有如下操作: l 电平变化检测: l 过滤抖动: l 产生有效按键. 实验三我们也会z执行同样的事情,不过却是产生不一样的有效按键: l 按下有效(点击): l 长按下有效(长点击). 图3.1 按下有效,时序示意图. 图3.2 长按下有效,时序示意图. 如图3.1所示,按下有效既是"点击",当按键被按下并且消抖完毕以后,isSClick信号就有被拉高一个时钟(Short Click).