【问题标题】:How to prevent onClick method on transparent portion of a PNG-loaded ImageView如何在 PNG 加载的 ImageView 的透明部分防止 onClick 方法
【发布时间】:2013-02-26 21:44:24
【问题描述】:

我目前正在开发一个 Android 应用程序,该应用程序显示多个堆叠在一起的图像(如 ImageView's)。以下是当前层的配置方式:

  • 背景层:缩放整个屏幕,必须是可点击的
  • 前景层:缩放整个屏幕,必须是可点击的, 包含透明度,允许用户看到一些 背景层

我面临的问题是前景层。我将onClick() 方法分配给imageview,但是无论它们是否击中可见的图像部分以及包含透明度的部分,都会调用该方法。我只希望在用户单击该图像视图的不透明部分时调用前景 ImageView onClick() 方法。

这就是场景的样子:

对角线表示前景图像的透明部分。如果用户触摸这个空间,我希望它访问背景图像而不是前景图像。感谢您提供的任何帮助。

这是我实施的解决方案(感谢下面的回答):

//ontouchlistener - gets X and Y from event
private void setClick(View view)
{
    view.setOnTouchListener(new View.OnTouchListener() 
    {
        public boolean onTouch(View v, MotionEvent event) 
        {
            int imageId = getImageId((int)event.getX(), (int)event.getY());
            if (imageId >= 0)
                performActions(imageId);
            return false;
        }
    });
}

//get the ID of the first imageview (starting from foreground, 
//working backwards) which contains a non-transparent pixel
private int getImageId(int x, int y)
{
    ViewGroup parent = (ViewGroup) findViewById(R.id.relative_layout);
    for (int a = parent.getChildCount()-1; a >= 0; a--)
    {
        if (parent.getChildAt(a) instanceof ImageView)
            if (!checkPixelTransparent((ImageView)parent.getChildAt(a), x, y))
                return parent.getChildAt(a).getId();
    }
    return -1;
}

//get bitmap from imageview, get pixel from x, y coord
//check if pixel is transparent
private boolean checkPixelTransparent(ImageView iv, int x, int y)
{
    Bitmap bitmap = ((BitmapDrawable) iv.getDrawable()).getBitmap();
    if (Color.alpha(bitmap.getPixel(x, y)) == 0)
        return true;
    else
        return false;
}

【问题讨论】:

  • 尽量不要有透明的部分。如果可以的话,裁剪图像以去除透明部分
  • 感谢您的评论,但有些前景图片非常复杂,无法裁剪
  • 那么你必须查看图像的像素并与透明进行比较
  • @JeremiahGreco,你的问题解决了吗?我试过你的代码,但它不能正常工作。当您深入获取堆叠图像的颜色时,它每次都会返回不同的颜色。你能帮帮我吗?

标签: android onclick imageview


【解决方案1】:

This one sample 使 ImageView 的透明区域不可点击。

图像视图:

ImageView imgView= (ImageView) findViewById(R.id.color_blue);
imgView.setDrawingCacheEnabled(true);
imgView.setOnTouchListener(changeColorListener);

OnTouchListener:

private final OnTouchListener changeColorListener = new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Bitmap bmp = Bitmap.createBitmap(v.getDrawingCache());
        int color = bmp.getPixel((int) event.getX(), (int) event.getY());
        if (color == Color.TRANSPARENT)
            return false;
        else {
            //code to execute
            return true;
        }
    }
};

【讨论】:

  • 我知道这是旧的,但这是一个很好的答案。你帮了我很多忙!
  • 如果您想将其用作 OnClick,您应该更新 //code 以通过 if(event.getAction()==MotionEvent.ACTION_UP){/*code to execute*/} 执行。
  • 如果没有引发 npe,我必须添加 v.buildDrawingCache()
  • 这是我在网站上看到的最好的答案之一!谢谢!花了最后 2.5 小时搞清楚这个!!!
【解决方案2】:

如果您的前景图像不仅仅是一个矩形,而是一个复杂的图像,并且您确实需要触摸是像素精确的,您可以使用

http://developer.android.com/reference/android/view/View.OnTouchListener.html

foregroundImage.setOnTouchListener(new View.OnTouchListener(){...});

回调中的MotionEvent 将包含发生的操作类型(例如修饰)和确切位置。

如果您知道前景图像显示时的确切大小,您可以确定单击了它的哪个像素,然后检查该像素的 alpha 是否为 0。或者,如果图像是,您可能需要应用一些缩放缩放。这可能会变得非常棘手,因为根据屏幕尺寸和比例,图像可能会以不同的方式缩放/定位。这也取决于您使用的布局。

为了检查像素值,您可能需要在内存中保存包含前景图像数据的 Bitmap 对象。

坦率地说,我怀疑你是否真的需要所有的精度,除非你的前景图像真的是非常不规则的形状。

【讨论】:

  • 让我看看我是否明白 - 使用 OnTouchListener 确定所选像素,然后从前到后检查所有图像中像素的 alpha
  • 感谢您的帮助 iseeall,我用您的回答构建的解决方案更新了我的问题
【解决方案3】:

Bitmap.createBitmap(v.getDrawingCache()imageView.setDrawingCacheEnabled(true) 已折旧,因此您可以通过以下 sn-p 代码执行此操作:

imageView.setOnTouchListener { v, event ->
            val bmp = convertViewToDrawable(v)
            val color: Int = bmp.getPixel(event.x.toInt(), event.y.toInt())
            if (color == Color.TRANSPARENT)
                return@setOnTouchListener false
            else {
                Toast.makeText(baseContext, "image clicked", Toast.LENGTH_SHORT).show()
                return@setOnTouchListener true
            }
        }

private fun convertViewToDrawable(view: View): Bitmap {
        val b = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight,
            Bitmap.Config.ARGB_8888)
        val c = Canvas(b)
        c.translate((-view.scrollX).toFloat(), (-view.scrollY).toFloat())
        view.draw(c)
        return b
    }

【讨论】:

    猜你喜欢
    • 2013-02-16
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 2013-07-20
    • 2012-11-03
    • 1970-01-01
    • 2015-03-18
    • 1970-01-01
    相关资源
    最近更新 更多