40 Stimmen

Android: Zeichnen eines Canvas auf ein ImageView

Ich bin neu in der Android-Programmierung und was ich versuche zu verstehen, ist folgendes;

In meinem Layout habe ich ein TextView, ImageView und Button, alle in einem vertikal orientierten LinearLayout.

Ich möchte in der Lage sein, Kreise dynamisch im ImageView zu zeichnen, ohne den Rest meines Layouts (TextView/Button) zu stören. Ich versuche eine Leinwand zu erstellen und die drawcircle-Funktion innerhalb der Leinwand zu verwenden, um den Standort des Kreises festzulegen. Und dann diese Leinwand auf irgend eine Weise in meinen ImageView zu zeichnen. Ich kann das nicht zum Laufen bringen, gibt es einen Trick dafür? Oder ist meine Methode grundsätzlich falsch? Wie würde ich Kreise zeichnen, um den ImageView herum, ohne mein gesamtes Layout neu zu erstellen?

Danke!

34voto

Nantoka Punkte 4044

Ich hatte dieselbe Herausforderung und kam zu dem Schluss, dass das Überschreiben von onDraw zumindest im Allgemeinen nicht funktioniert. Mein Blog erklärt die Gründe. Was für mich sehr gut funktioniert hat, ist folgendes:

  1. Erstellen Sie ein neues Bild-Bitmap und fügen Sie ihm eine brandneue Leinwand hinzu.
  2. Zeichnen Sie das Bild-Bitmap in die Leinwand.
  3. Zeichnen Sie alles andere, was Sie wollen, in die Leinwand.
  4. Fügen Sie die Leinwand dem ImageView hinzu.

Hier ist ein Code-Schnipsel dafür:

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 = ...

//Erstellen Sie ein neues Bild-Bitmap und fügen Sie ihm eine brandneue Leinwand hinzu
Bitmap tempBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), Bitmap.Config.RGB_565);
Canvas tempCanvas = new Canvas(tempBitmap);

//Zeichnen Sie das Bild-Bitmap in die Leinwand
tempCanvas.drawBitmap(myBitmap, 0, 0, null);

//Zeichnen Sie alles andere, was Sie wollen, in die Leinwand, in diesem Beispiel ein Rechteck mit abgerundeten Ecken
tempCanvas.drawRoundRect(new RectF(x1,y1,x2,y2), 2, 2, myPaint);

//Fügen Sie die Leinwand dem ImageView hinzu
myImageView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap));

33voto

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

9voto

Lys Punkte 558

Ich denke, dass ein besserer Ansatz darin bestehen würde, eine benutzerdefinierte ImageView zu erstellen und die onDraw-Methode zu überschreiben. Etwas wie:

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

Es wäre eine gute Idee, eine Logik zu implementieren, die überprüft, ob es eine frische Bitmap gibt, die über die update()-Methode abgerufen werden kann, damit der Code innerhalb von onDraw nicht bei jedem Mal ausgeführt wird und das System belastet.

Und dann verwenden Sie Ihre benutzerdefinierte Ansicht, wo immer Sie sie brauchen. Der einfachste Weg wäre, sie direkt innerhalb der activity_layout.xml zu deklarieren, wie folgt:

Und dann greifen Sie darauf in Ihrem Code wie auf eine andere Ansicht zu, indem Sie verwenden:

   customView = (CustomView) findViewById(R.id.customView);

0voto

Rohit Sharma Punkte 13497

Wenn Sie ein XML mit Layout haben, in dem alle Ihre Elemente in vertikaler Ausrichtung angeordnet sind.

Sie können erreichen, was Sie möchten, indem Sie eine Klasse in Ihrem Paket erstellen, die die Klasse View erweitert und ihre onDraw-Methode überschreibt. Zeichnen Sie darin einen Kreis, wie Sie möchten.

Statt ein ImageView im Layout hinzuzufügen, fügen Sie Ihre eigene Ansicht im XML-Layout hinzu, wie folgt:

< LinearLayout >

 < TextView> < /TextView>

  < Button> < /Button>

< /LinearLayout>

Überprüfen Sie den folgenden Link für 2D-Grafiken. Es ist ein großartiges Tutorial zum Lesen.
http://organicandroid.blogspot.com/2010/08/starting-to-play-with-graphics.html
Hoffentlich hilft das : )

0voto

Ted Hopp Punkte 227177

Es gibt ein paar Möglichkeiten, um das zu erreichen, was du möchtest, aber die Verwendung eines ImageView auf die von dir beschriebene Weise gehört nicht dazu. Eine Möglichkeit besteht darin, dass das ImageView eine animierte Drawable anzeigt. Sie können sich dann darauf konzentrieren, dass Ihre Drawable-Implementierung die Kreise zeichnet. Eine andere Möglichkeit besteht darin, jedes Mal, wenn Sie möchten, dass sich das Bild ändert, eine neue Bitmap zu erstellen und das ImageView so einzustellen, dass es die neue Bitmap anzeigt. Der übliche Weg, dies zu tun, besteht jedoch darin, eine benutzerdefinierte View-Teilklasse zu erstellen. Das API Demos Beispielprojekt hat ein Beispiel für eine benutzerdefinierte Ansicht, und Sie können viele Tutorials mit Google finden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X