Android: рисование холста в ImageView

Я новичок в программировании для Android, и я пытаюсь понять это;

В моем макете у меня есть TextView, ImageView и Button, все на вертикально ориентированном LinearLayout.

Я хочу иметь возможность динамически рисовать круги в ImageView, не нарушая остальную часть моего макета (текстовое представление/кнопку). Я пытаюсь создать холст и использую функцию drawcircle внутри холста, чтобы установить местоположение круга. А затем каким-то образом нарисуйте этот холст на моем изображении. Я не могу заставить это работать, есть ли в этом хитрость? Или мой метод в корне неверен? Как мне рисовать круги в ImageView, не воссоздавая весь мой макет?

Спасибо!


person sil    schedule 07.02.2011    source источник


Ответы (5)


У меня была такая же проблема, и я пришел к выводу, что перезапись onDraw не будет работать, по крайней мере, в общем случае. мой блог объясняет причины. Что сработало очень хорошо для меня, так это следующее:

  1. Создайте новое растровое изображение и прикрепите к нему новый холст.
  2. Нарисуйте растровое изображение на холсте.
  3. Нарисуйте все остальное, что вы хотите, на холсте.
  4. Прикрепите холст к ImageView.

Вот фрагмент кода для этого:

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;

ImageView myImageView = ...
Bitmap myBitmap = ...
Paint myRectPaint = ...
int x1 = ...
int y1 = ...
int x2 = ...
int y2 = ...

//Create a new image bitmap and attach a brand new canvas to it
Bitmap tempBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), Bitmap.Config.RGB_565);
Canvas tempCanvas = new Canvas(tempBitmap);

//Draw the image bitmap into the cavas
tempCanvas.drawBitmap(myBitmap, 0, 0, null);

//Draw everything else you want into the canvas, in this example a rectangle with rounded edges
tempCanvas.drawRoundRect(new RectF(x1,y1,x2,y2), 2, 2, myPaint);

//Attach the canvas to the ImageView
myImageView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap));
person Nantoka    schedule 11.06.2012
comment
Просто предложение, поскольку я столкнулся с той же проблемой. Вместо создания нового BitmapDrawable мы также можем использовать функцию myImageView.setImageBitmap(tempBitmap)! - person balachandarkm; 05.12.2014

Я думаю, что лучшим подходом было бы создание пользовательского ImageView и переопределение метода onDraw. Что-то типа:

public class CustomView extends ImageView {

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

public CustomView(Context context, AttributeSet attrst) {
    super(context, attrst);
}

public CustomView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

MyBitmapFactory bitMapFac = null;
public void setBitmapFactory(MyBitmapFactory bitMapFac)
{
    this.bitMapFac = bitMapFac;
}

@Override
public void onDraw(Canvas canvas) {

    canvas.drawColor(Color.TRANSPARENT);
    /*instantiate a bitmap and draw stuff here, it could well be another
    class which you systematically update via a different thread so that you can get a fresh updated
    bitmap from, that you desire to be updated onto the custom ImageView. 
   That will happen everytime onDraw has received a call i.e. something like:*/
    Bitmap myBitmap = bitMapFac.update(); //where update returns the most up  to date Bitmap
    //here you set the rectangles in which you want to draw the bitmap and pass the bitmap        
    canvas.drawBitmap(myBitMap, new Rect(0,0,400,400), new Rect(0,0,240,135) , null);
    super.onDraw(canvas);
    //you need to call postInvalidate so that the system knows that it  should redraw your custom ImageView
    this.postInvalidate();
}
}

Было бы неплохо реализовать некоторую логику, которая проверяет, есть ли свежее растровое изображение для получения с помощью метода update(), чтобы код внутри onDraw не выполнялся каждый раз и создавал дополнительную нагрузку на систему.

А затем используйте свой собственный вид везде, где вам это нужно. Самый простой способ — объявить его непосредственно внутри Activity_layout.xml как таковой:

   <com.mycustomviews.CustomView
        android:id="@+id/customView"
        android:layout_centerInParent="true"
        android:layout_height="135dp"
        android:layout_width="240dp"
       android:background="@android:color/transparent"/>

И затем доступ находится в вашем коде, как и в любом другом представлении, с помощью:

   customView = (CustomView) findViewById(R.id.customView);
person Lys    schedule 15.09.2015

Если у вас есть XML-файл с макетом, в котором все элементы расположены вертикально.

Вы можете добиться желаемого, создав в своем пакете класс, который расширяет представление классов и переопределяет его метод onDraw. нарисуйте в нем круг, как хотите.

затем вместо добавления imageView в макет добавьте это свое собственное представление в макет xml. например, следующее

‹ Линейный макет >

 < TextView> < /TextView>

  < Button> < /Button>

  <com.prac.MyView> </ com.prac.MyView>

‹ /Линейный макет>

Проверьте следующую ссылку для 2D-графики. Это отличный учебник для чтения.
http://organicandroid.blogspot.com/2010/08/starting-to-play-with-graphics.html
Надеюсь, это поможет :)

person Rohit Sharma    schedule 07.02.2011

Есть несколько способов сделать то, что вы хотите, но использование ImageView так, как вы описываете, не является одним из них. Одна из возможностей состоит в том, чтобы ImageView отображал анимированный Drawable. Затем вы можете сосредоточиться на том, чтобы ваша реализация Drawable рисовала круги. Другой способ — создавать новое растровое изображение каждый раз, когда вы хотите, чтобы изображение менялось, и настраивать ImageView для отображения нового растрового изображения. Однако обычный способ сделать это — создать собственный подкласс View. Пример проекта API Demos содержит пример пользовательского представления, и вы можно найти много учебников с Google.

person Ted Hopp    schedule 07.02.2011

person    schedule
comment
а что, если я хочу удалить холст после setImageBitmap? - person Rosario Vivas; 22.04.2016