15

私は現在、複数の画像を (としてImageView's) 重ねて表示する Android アプリを開発しています。レイヤーが現在どのように構成されているかを次に示します。

  • 背景レイヤー: 画面全体をスケーリングし、クリック可能にする必要があります
  • 前景レイヤー: 画面全体をスケーリングし、クリック可能である必要があり、ユーザーが背景レイヤーの一部を見ることができる透明度が含まれています

私が直面している問題は、前景レイヤーにあります。メソッドをイメージビューに割り当てて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

この 1 つのサンプルは、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には、発生したアクションの種類 (タッチアップなど) と正確な位置が含まれます。

表示されている前景画像の正確なサイズがわかっている場合は、クリックされたピクセルを特定し、そのピクセルのアルファが 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 に答える