如何在Android中以编程方式仅显示/隐藏ImageView的背景/图像?

lh80um4z  于 2023-05-21  发布在  Android
关注(0)|答案(2)|浏览(215)

我有一个ImageView,它的alpha在XML中设置为0。XML看起来像这样:

<LinearLayout

            android:layout_width="match_parent"
            android:layout_height="<height>"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/<id>"
                android:layout_width="<width>"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:alpha="0"
                android:background="#ff00ff"
                android:clickable="true"
                android:focusable="true"
                app:srcCompat="@drawable/<drawable>" />

            <ImageView
                android:id="@+id/<id>"
                android:layout_width="<width>"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:alpha="0"
                android:background="#0000ff"
                android:clickable="true"
                android:focusable="true"
                app:srcCompat="@drawable/<drawable>" />

</LinearLayout>

我试着搜索如何做到这一点,但大多数问题都是关于如何隐藏背景或整个ImageView,而不仅仅是背景。此外,alpha必须设置为"0"。有没有什么方法可以只隐藏图像,这样就只有background(纯色)是可见的?只有ImageViewbackground颜色必须显示,所以容器(LinearLayout)的background不能同时显示(背景颜色不同)。
将图像的源更改为纯色图像,与背景颜色相同,可以工作,但我需要以编程方式更改此颜色,因此可能效率低下。我还尝试了ImageView.-setAlpha(float)setImageAlpha(int)setImageResource(int)(到0)和setImageDrawable(Drawable)(再次显示图像,背景[颜色])的不同组合,但它们产生奇怪的结果。使用setImageResource(0)(使用alpha 1f)隐藏图像,仅显示纯色背景,但我无法再次显示图像。有什么简单的方法我不知道吗?
我需要以编程方式完成这项工作,因此像Java android Linearlayout set two colors中的方法将无法工作。什么是最好的方式来做到这一点编程?

kxxlusnw

kxxlusnw1#

Imageview可以显示一个位图,正如你所知道的。可以通过删除相关位图的背景来设置位图。
主要对象

object BackgroundRemover {

    private val segment: Segmenter
    private var buffer = ByteBuffer.allocate(0)
    private var width = 0
    private var height = 0

    init {
        val segmentOptions = SelfieSegmenterOptions.Builder()
            .setDetectorMode(SelfieSegmenterOptions.SINGLE_IMAGE_MODE)
            .build()
        segment = Segmentation.getClient(segmentOptions)
    }

    /**
     * Process the image to get buffer and image height and width
     * @param bitmap Bitmap which you want to remove background.
     * @param trimEmptyPart After removing the background if its true it will remove the empty part of bitmap. by default its false.
     * @param listener listener for success and failure callback.
     **/
    fun bitmapForProcessing(
        bitmap: Bitmap,
        trimEmptyPart: Boolean? = false,
        listener: OnBackgroundChangeListener
    ) {
        //Generate a copy of bitmap just in case the if the bitmap is immutable.
        val copyBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
        val input = InputImage.fromBitmap(copyBitmap, 0)
        segment.process(input)
            .addOnSuccessListener { segmentationMask ->
                buffer = segmentationMask.buffer
                width = segmentationMask.width
                height = segmentationMask.height

                CoroutineScope(Dispatchers.IO).launch {
                    val time = measureTimeMillis {
                        val resultBitmap = if (trimEmptyPart == true) {
                            val bgRemovedBitmap = removeBackgroundFromImage(copyBitmap)
                            trim(bgRemovedBitmap)
                        } else {
                            removeBackgroundFromImage(copyBitmap)
                        }
                        withContext(Dispatchers.Main) {
                            listener.onSuccess(resultBitmap)
                        }
                    }
                    Log.e("TAG", "bitmapForProcessingTime: $time")
                }

            }
            .addOnFailureListener { e ->
                println("Image processing failed: $e")
                listener.onFailed(e)

            }
    }

    /**
     * Change the background pixels color to transparent.
     * */
    private suspend fun removeBackgroundFromImage(
        image: Bitmap
    ): Bitmap {
        val bitmap = CoroutineScope(Dispatchers.IO).async {
            for (y in 0 until height) {
                for (x in 0 until width) {
                    val bgConfidence = ((1.0 - buffer.float) * 255).toInt()
                    if (bgConfidence >= 100) {
                        image.setHasAlpha(true)
                        image.setPixel(x, y, 0)
                    }
                }
            }
            buffer.rewind()
            return@async image
        }
        return bitmap.await()
    }

    /**
     * trim the empty part of a bitmap.
     **/
    private suspend fun trim(
        bitmap: Bitmap
    ): Bitmap {
        val result = CoroutineScope(Dispatchers.Default).async {
            var firstX = 0
            var firstY = 0
            var lastX = bitmap.width
            var lastY = bitmap.height
            val pixels = IntArray(bitmap.width * bitmap.height)
            bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
            loop@ for (x in 0 until bitmap.width) {
                for (y in 0 until bitmap.height) {
                    if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
                        firstX = x
                        break@loop
                    }
                }
            }
            loop@ for (y in 0 until bitmap.height) {
                for (x in firstX until bitmap.width) {
                    if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
                        firstY = y
                        break@loop
                    }
                }
            }
            loop@ for (x in bitmap.width - 1 downTo firstX) {
                for (y in bitmap.height - 1 downTo firstY) {
                    if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
                        lastX = x
                        break@loop
                    }
                }
            }
            loop@ for (y in bitmap.height - 1 downTo firstY) {
                for (x in bitmap.width - 1 downTo firstX) {
                    if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
                        lastY = y
                        break@loop
                    }
                }
            }
            return@async Bitmap.createBitmap(bitmap, firstX, firstY, lastX - firstX, lastY - firstY)
        }
        return result.await()
    }

}

监听器

interface OnBackgroundChangeListener {

    fun onSuccess(bitmap: Bitmap)

    fun onFailed(exception: Exception)

}
yc0p9oo0

yc0p9oo02#

但是,不可能直接像预期的那样使用两个视图,正如您所说的,您有多个这样的视图&这就是为什么它不是内存有效的。
但是我们可以使用根据我们的需要设计的**CustomView**来实现该功能。

**如果你知道一点drawing on the canvas以及它是如何工作的,那么它会更容易。

在这里,我制作了自定义视图,以实现您想要的效果。

public class ImageAlphaBGView extends View {
    private Bitmap bitmap;
    Paint mPaint;
    Paint mPaintBG;
    Rect bgRect;

    private int mWidth;
    private int mHeight;
    float centreX;
    float centreY;

    public ImageAlphaBGView(Context context) {
        super(context);
        init();
    }

    public ImageAlphaBGView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ImageAlphaBGView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public ImageAlphaBGView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);

        mPaintBG = new Paint();
        mPaintBG.setColor(Color.parseColor("#000000"));
        mPaintBG.setStyle(Paint.Style.FILL);
        mPaintBG.setAntiAlias(true);
    }

    public void setImageBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
        try {
            centreX = (mWidth - bitmap.getWidth()) / 2;
            centreY = (mHeight - bitmap.getHeight()) / 2;
        } catch (Exception e) {
            e.printStackTrace();
        }
        invalidate();
    }

    public void setBGColor(int color) {
        mPaintBG.setColor(color);
        invalidate();
    }

    public void setImageAlpha(@IntRange(from = 0, to = 255) int alpha) {
        mPaint.setAlpha(alpha);
        invalidate();
    }

    public void setBGAlpha(@IntRange(from = 0, to = 255) int alpha) {
        mPaintBG.setAlpha(alpha);
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawRect(bgRect, mPaintBG);
        if (bitmap != null)
            canvas.drawBitmap(bitmap, centreX, centreY, mPaint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;

        bgRect = new Rect(0, 0, mWidth, mHeight);
        invalidate();
    }
}

只需将此视图放入您的XML中&然后您就可以通过编程方式传递背景的位图和alpha。
支持单独设置图片alpha、背景alpha以及背景色。

以下是您需要做的:
在xml中,

<com.demo.example.views.ImageAlphaBGView
            android:id="@+id/alphaView"
            android:layout_width="150dp"
            android:layout_height="150dp"/>

在活动或片段中,

ImageAlphaBGView imageView = findViewById(R.id.alphaView)
imageView.setImageBitmap(bitmap)
imageView.setBGColor(Color.RED)
imageView.setImageAlpha(255)

你得到了它。:)

相关问题