Android: рисование холста в ImageView
Я новичок в программировании на Android, и я пытаюсь понять это:
В моем макете у меня есть TextView, ImageView и Button, все на вертикально ориентированном LinearLayout.
Я хочу иметь возможность динамически рисовать круги в ImageView, не нарушая остальную часть моего макета (textview/button). Я пытаюсь создать холст и использовать функцию drawcircle внутри canvas, чтобы установить местоположение круга. И затем каким-то образом нарисуйте этот холст на мое изображение. Я не могу заставить это работать, есть ли уловка? Или мой метод принципиально неправильный? Как я могу рисовать круги в ImageView без повторного создания всего моего макета?
Спасибо!
Ответы
Ответ 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.