накладіть два зображення в android, щоб встановити перегляд зображення


100

Я намагаюся перекрити два зображення в моєму додатку, але вони, здається, розбиваються на моїй canvas.setBitmap()лінії. Що я роблю неправильно?

private void test() {
    Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.t);
    Bitmap mBitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.tt);
    Bitmap bmOverlay = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), mBitmap.getConfig());
    Canvas canvas = new Canvas();
    canvas.setBitmap(bmOverlay);
    canvas.drawBitmap(mBitmap, new Matrix(), null);
    canvas.drawBitmap(mBitmap2, new Matrix(), null);
    testimage.setImageBitmap(bmOverlay);
}

Можна використовувати framelayout , а також, як це: stackoverflow.com/a/11658554/586484
Лізогенія

Відповіді:


234

Ви можете пропустити складну маніпуляцію Canvas і зробити це повністю за допомогою Drawables, використовуючи LayerDrawable. У вас є один з двох варіантів: ви можете визначити його в XML, а потім просто встановити зображення, або ви можете налаштувати aLayerDrawable динамічно код.

Рішення №1 (через XML):

Створіть новий XML-файл Dravable, назвемо його layer.xml:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/t" />
    <item android:drawable="@drawable/tt" />
</layer-list>

Тепер встановіть зображення за допомогою програми Dravable:

testimage.setImageDrawable(getResources().getDrawable(R.layout.layer));

Рішення №2 (динамічне):

Resources r = getResources();
Drawable[] layers = new Drawable[2];
layers[0] = r.getDrawable(R.drawable.t);
layers[1] = r.getDrawable(R.drawable.tt);
LayerDrawable layerDrawable = new LayerDrawable(layers);
testimage.setImageDrawable(layerDrawable);

(Я не перевіряв цей код, тому може виникнути помилка, але цей загальний контур повинен працювати.)


1
дякую, спрацювало! одна помилка друку, якщо хтось інший використовує код: LayerDravable шари2 = новий LayerDravable (шари); testimage.setImageDravable (шари2);
Джон

1
Чудовий спосіб заощадити місце та повторно використовувати зображення. Також ви можете використовувати android: left, android: right, android: top and android: down, щоб керувати положенням одного із шарів у файлі .xml.
zabawaba99

Я використав це для малювання круглої форми, що малюється за зображенням, дуже приємне рішення!
Даніель Вілсон

1
Чи є спосіб програмно приховати шари [1]? Я хочу показати шар зображення із шаром завантажувача ajax зверху. Через деякий час я хочу приховати навантажувач ajax поодинці. Будь-яка пропозиція?
harishannam

1
Добре працює для моїх потреб (я використовував кодовий підхід). У мене є ряд "плиток", на які користувач натискає, щоб переміщатися по додатку. Використовуючи такий підхід, мені вдалося створити єдине фонове зображення (загальне для всіх плиток) та численні зображення переднього плану (з прозорими фонами), які я можу завантажувати під час виконання. Не дивився б на LayerDravable без цієї відповіді :-)
DilbertDave

10

гаразд, щоб ви знали, що там є програма, яка називається DroidDraw. Це може допомогти вам намалювати об'єкти та спробувати їх один на інший. Я спробував ваше рішення, але у мене була анімація під меншим зображенням, щоб це не спрацювало. Але потім я спробував розмістити одне зображення у відносному макеті, який, мабуть, знаходиться спочатку, а потім поверх того, що я намалював інше зображення, яке, мабуть, накладене, і все спрацювало чудово. Тож RelativeLayout, DroidDraw і вам добре їхати :) Просте, ніякого джиггерського покера :) і ось трохи коду для вас:

Логотип розташовується поверх фонового зображення шазаму.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/widget30"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<ImageView
android:id="@+id/widget39"
android:layout_width="219px"
android:layout_height="225px"
android:src="@drawable/shazam_bkgd"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
>
</ImageView>
<ImageView
android:id="@+id/widget37"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/shazam_logo"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
>
</ImageView>
</RelativeLayout>

6

Ви можете використовувати код нижче, щоб вирішити проблему або завантажити демонстрацію тут

Створіть дві функції для обробки кожної.

Спочатку малюється полотно, а зображення малюються один на одного з точки (0,0)

Натисніть кнопку

public void buttonMerge(View view) {

        Bitmap bigImage = BitmapFactory.decodeResource(getResources(), R.drawable.img1);
        Bitmap smallImage = BitmapFactory.decodeResource(getResources(), R.drawable.img2);
        Bitmap mergedImages = createSingleImageFromMultipleImages(bigImage, smallImage);

        img.setImageBitmap(mergedImages);
    }

Функція для створення накладки.

private Bitmap createSingleImageFromMultipleImages(Bitmap firstImage, Bitmap secondImage){

    Bitmap result = Bitmap.createBitmap(firstImage.getWidth(), firstImage.getHeight(), firstImage.getConfig());
    Canvas canvas = new Canvas(result);
    canvas.drawBitmap(firstImage, 0f, 0f, null);
    canvas.drawBitmap(secondImage, 10, 10, null);
    return result;
}

Детальніше


2

Це трохи пізня відповідь, але вона охоплює об'єднання зображень із URL-адрес за допомогою Picasso

MergeImageView

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Build;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;

import java.io.IOException;
import java.util.List;

public class MergeImageView extends ImageView {

    private SparseArray<Bitmap> bitmaps = new SparseArray<>();
    private Picasso picasso;
    private final int DEFAULT_IMAGE_SIZE = 50;
    private int MIN_IMAGE_SIZE = DEFAULT_IMAGE_SIZE;
    private int MAX_WIDTH = DEFAULT_IMAGE_SIZE * 2, MAX_HEIGHT = DEFAULT_IMAGE_SIZE * 2;
    private String picassoRequestTag = null;

    public MergeImageView(Context context) {
        super(context);
    }

    public MergeImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MergeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public MergeImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean isInEditMode() {
        return true;
    }

    public void clearResources() {
        if (bitmaps != null) {
            for (int i = 0; i < bitmaps.size(); i++)
                bitmaps.get(i).recycle();
            bitmaps.clear();
        }
        // cancel picasso requests
        if (picasso != null && AppUtils.ifNotNullEmpty(picassoRequestTag))
            picasso.cancelTag(picassoRequestTag);
        picasso = null;
        bitmaps = null;
    }

    public void createMergedBitmap(Context context, List<String> imageUrls, String picassoTag) {
        picasso = Picasso.with(context);
        int count = imageUrls.size();
        picassoRequestTag = picassoTag;

        boolean isEven = count % 2 == 0;
        // if url size are not even make MIN_IMAGE_SIZE even
        MIN_IMAGE_SIZE = DEFAULT_IMAGE_SIZE + (isEven ? count / 2 : (count / 2) + 1);
        // set MAX_WIDTH and MAX_HEIGHT to twice of MIN_IMAGE_SIZE
        MAX_WIDTH = MAX_HEIGHT = MIN_IMAGE_SIZE * 2;
        // in case of odd urls increase MAX_HEIGHT
        if (!isEven) MAX_HEIGHT = MAX_WIDTH + MIN_IMAGE_SIZE;

        // create default bitmap
        Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_wallpaper),
                MIN_IMAGE_SIZE, MIN_IMAGE_SIZE, false);

        // change default height (wrap_content) to MAX_HEIGHT
        int height = Math.round(AppUtils.convertDpToPixel(MAX_HEIGHT, context));
        setMinimumHeight(height * 2);

        // start AsyncTask
        for (int index = 0; index < count; index++) {
            // put default bitmap as a place holder
            bitmaps.put(index, bitmap);
            new PicassoLoadImage(index, imageUrls.get(index)).execute();
            // if you want parallel execution use
            // new PicassoLoadImage(index, imageUrls.get(index)).(AsyncTask.THREAD_POOL_EXECUTOR);
        }
    }

    private class PicassoLoadImage extends AsyncTask<String, Void, Bitmap> {

        private int index = 0;
        private String url;

        PicassoLoadImage(int index, String url) {
            this.index = index;
            this.url = url;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            try {
                // synchronous picasso call
                return picasso.load(url).resize(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE).tag(picassoRequestTag).get();
            } catch (IOException e) {
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap output) {
            super.onPostExecute(output);
            if (output != null)
                bitmaps.put(index, output);

            // create canvas
            Bitmap.Config conf = Bitmap.Config.RGB_565;
            Bitmap canvasBitmap = Bitmap.createBitmap(MAX_WIDTH, MAX_HEIGHT, conf);
            Canvas canvas = new Canvas(canvasBitmap);
            canvas.drawColor(Color.WHITE);

            // if height and width are equal we have even images
            boolean isEven = MAX_HEIGHT == MAX_WIDTH;
            int imageSize = bitmaps.size();
            int count = imageSize;

            // we have odd images
            if (!isEven) count = imageSize - 1;
            for (int i = 0; i < count; i++) {
                Bitmap bitmap = bitmaps.get(i);
                canvas.drawBitmap(bitmap, bitmap.getWidth() * (i % 2), bitmap.getHeight() * (i / 2), null);
            }
            // if images are not even set last image width to MAX_WIDTH
            if (!isEven) {
                Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmaps.get(count), MAX_WIDTH, MIN_IMAGE_SIZE, false);
                canvas.drawBitmap(scaledBitmap, scaledBitmap.getWidth() * (count % 2), scaledBitmap.getHeight() * (count / 2), null);
            }
            // set bitmap
            setImageBitmap(canvasBitmap);
        }
    }
}

xml

<com.example.MergeImageView
    android:id="@+id/iv_thumb"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

Приклад

List<String> urls = new ArrayList<>();
String picassoTag = null;
// add your urls
((MergeImageView)findViewById(R.id.iv_thumb)).
        createMergedBitmap(MainActivity.this, urls,picassoTag);

1

це моє рішення:

    public Bitmap Blend(Bitmap topImage1, Bitmap bottomImage1, PorterDuff.Mode Type) {

        Bitmap workingBitmap = Bitmap.createBitmap(topImage1);
        Bitmap topImage = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);

        Bitmap workingBitmap2 = Bitmap.createBitmap(bottomImage1);
        Bitmap bottomImage = workingBitmap2.copy(Bitmap.Config.ARGB_8888, true);

        Rect dest = new Rect(0, 0, bottomImage.getWidth(), bottomImage.getHeight());
        new BitmapFactory.Options().inPreferredConfig = Bitmap.Config.ARGB_8888;
        bottomImage.setHasAlpha(true);
        Canvas canvas = new Canvas(bottomImage);
        Paint paint = new Paint();

        paint.setXfermode(new PorterDuffXfermode(Type));

        paint.setFilterBitmap(true);
        canvas.drawBitmap(topImage, null, dest, paint);
        return bottomImage;
    }

використання:

imageView.setImageBitmap(Blend(topBitmap, bottomBitmap, PorterDuff.Mode.SCREEN));

або

imageView.setImageBitmap(Blend(topBitmap, bottomBitmap, PorterDuff.Mode.OVERLAY));

та результати:

Режим накладання: Режим накладання

Екранний режим: Екранний режим


Це добре. Але якщо ви хочете відобразити два зображення поруч, яке рішення?
маніяк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.