Android: рисование холста в ImageView - PullRequest
31 голосов
/ 07 февраля 2011

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

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

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

Спасибо!

Ответы [ 5 ]

31 голосов
/ 11 июня 2012

У меня была такая же проблема, и я пришел к выводу, что перезапись 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));
26 голосов
/ 14 февраля 2015
     ImageView imageView=(ImageView) findViewById(R.id.image);
        Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);    
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.BLACK);
        canvas.drawCircle(50, 50, 10, paint);
        imageView.setImageBitmap(bitmap);
5 голосов
/ 15 сентября 2015

Я думаю, что лучшим подходом было бы создание пользовательского 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);
0 голосов
/ 07 февраля 2011

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

0 голосов
/ 07 февраля 2011

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

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

, затем вместо добавления imageView в макет добавьте этот собственный вид в макет XML.

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

...