• 自己定义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>

    代码非常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文件:

    <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

  • 相关阅读:
    【数据分享】学生受欢迎程度评价数据集
    拓端tecdat|Matlab用Copula模型进行蒙特卡洛(Monte Carlo)模拟和拟合股票收益数据分析
    聊一聊并行文件系统的客户端优化之道
    从Redis7.0发布看Redis的过去与未来
    辛辛苦苦原创的网站,被抄袭了怎么办?
    常用Yum镜像源
    Wget/httrack 爬取整站资源
    Maven:第二章:去中央仓库下载包到本地引入依赖到项目中
    消息队列:第五章:RabbitMQ的使用
    我的分享:第一章:SpringBoot专栏
  • 原文地址:https://www.cnblogs.com/yfceshi/p/7222465.html
Copyright © 2020-2023  润新知