Подтвердить что ты не робот

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

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

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

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

Спасибо!

4b9b3361

Ответ 1

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

  • Создайте новое растровое изображение и прикрепите к нему новый холст.
  • Нарисуйте растровое изображение изображения в холсте.
  • Нарисуйте все остальное, что вы хотите, на холст.
  • Прикрепите холст к 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));

Ответ 2

     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);

Ответ 3

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

Ответ 4

Если у вас есть xml с макетом со всеми вашими элементами, расположенными в вертикальной ориентации.

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

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

<LinearLayout>

 < TextView> < /TextView>

  < Button> < /Button>

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

</LinearLayout>

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

Ответ 5

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