15

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

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

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

这是场景的样子:

在此处输入图像描述

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

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

//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;
}
4

3 回答 3

38

这个示例使 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;
        }
    }
};
于 2013-10-24T13:04:54.460 回答
3

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

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

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

回调中的MotionEvent将包含发生了什么样的动作(例如修饰)和确切的位置。

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

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

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

于 2013-03-11T17:03:49.723 回答
1

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

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
    }
于 2019-09-24T17:32:38.177 回答