Graphics

Android graphics are powered by a custom 2D graphics library and OpenGL ES 1.0 for high performance 3D graphics. The most common 2D graphics APIs can be found in the drawable package. OpenGL APIs are available from the Khronos OpenGL ES package, plus some Android OpenGL utilities.

안드로이드 그래픽은 커스텀 2D 그래픽 라이브러리와 고사양의 3D 그래픽을 위한 OpenGL ES 1.0에 의해 구동된다. 가장 일반적인 2D 그래픽 API들은 drawable 패키지에서 찾을 수 있다. OpenGL API는 Khronos OpenGL ES 패키지로부터 유용하게 되었으며, 더불어 약간의 안드로이드 OpenGL 유틸리티들이 추가되었다.

When starting a project, it's important to consider exactly what your graphical demands will be. Varying graphical tasks are best accomplished with varying techniques. For example, graphics and animations for a rather static application should be implemented much differently than graphics and animations for an interactive game or 3D rendering.

프로젝트를 시작할 때, 여러분의 그래픽에 대한 요구demand가 무엇인지를 정확하게 고려하는 것이 중요하다. 많은 그래픽 작업들은 많은 기술들을 사용하여 이루어진다. 예를 들어 다소 정적인 애플리케이션에 대한 그래픽과 애니메이션은 인터랙티브 게임이나 3D 렌더링에 대한 그래픽과 애니메이션과는 매우 다르게 구현되어야 한다.

Here, we'll discuss a few of the options you have for drawing graphics on Android, and which tasks they're best suited for.

여기서 우리는 여러분이 안드로이드상에서 그래픽을 그리기 위해 가질 수 있는 몇 가지 옵션과 그것들이 어떤 작업에 가장 잘 맞는지에 대해 논의할 것이다.

If you're specifically looking for information on drawing 3D graphics, this page won't help a lot. However, the information below, on Drawing with a Canvas (and the section on SurfaceView), will give you a quick idea of how you should draw to the View hierarchy. For more information on Android's 3D graphic utilities (provided by the OpenGL ES API), read 3D with OpenGL and refer to other OpenGL documentation.

만약 여러분이 특별히 3D 그래픽을 그리는 것에 대한 정보를 찾고 있다면, 이 페이지는 그다지 도움을 주지 못할 것이다. 하지만 캔버스를 사용해서 “드로잉하기(on Drawing with a Canvas)”에 있는 정보는 여러분에게 뷰 계층구조에 드로잉drawing 하는 방법에 대한 빠른 아이디어를 제공할 것이다. OpenGL ES API에서 제공되는 안드로이드 3D 그래픽 유틸리티에 대한 더 많은 정보에 대해서는 “OpenGL을 사용하는 3D(3D with OpenGL)”를 읽고, 다른 OpenGL 문서들을 참고하라.

Consider your Options

When drawing 2D graphics, you'll typically do so in one of two ways:

2D 그래픽을 그릴 때, 여러분은 보통 다음의 두 가지 방법 중 하나로 그것을 할 것이다.

  1. Draw your graphics or animations into a View object from your layout. In this manner, the drawing (and any animation) of your graphics is handled by the system's normal View hierarchy drawing process you simply define the graphics to go inside the View.
  2. Draw your graphics directly to a Canvas. This way, you personally call the appropriate class's draw() method (passing it your Canvas), or one of the Canvas draw...() methods (like drawPicture()). In doing so, you are also in control of any animation.
  1. 여러분 레이아웃의 뷰 오브젝트에 여러분의 그래픽 또는 애니메이션을 그리기. 이런 방식으로 여러분의 그래픽을 그리는 것은 시스템의 일반적인 뷰 계층구조의 드로잉 절차에 의해 처리된다 - 여러분은 간단히 그 뷰 안으로 그래픽이 들어가도록 정의한다.
  2. 캔버스Canvas에 직접적으로 여러분의 그래픽을 그리기. 이 방법은 여러분이 개인적으로 적절한 클래스의 draw() 메쏘드(그것에 여러분의 캔버스(Canvas)를 전달함), 또는 (drawPicture()와 같은) 캔버스 draw...() 메쏘드들 중의 하나를 호출하는 것이다. 그렇게 함으로써 여러분은 임의의 애니메이션 또한 제어하게 된다.

Option "a," drawing to a View, is your best choice when you want to draw simple graphics that do not need to change dynamically and are not part of a performance-intensive game. For example, you should draw your graphics into a View when you want to display a static graphic or predefined animation, within an otherwise static application. Read Simple Graphics Inside a View.

옵션 “a”의 뷰에 그리기는 여러분이 동적으로 바꿀 필요가 없고 성능 집약적인 게임에 속하지 않는 간단한 그래픽을 그릴 때 최선의 선택이다. 예를 들어 다른 정적 애플리케이션 안에서 정적 그래픽이나 미리 정의된 애니메이션을 표현하길 원할 때, 여러분은 뷰안에서 여러분의 그래픽을 드로잉해야 한다. “뷰 안에서의 간단한 그래픽Simple Graphics Inside a View”를 읽어보기 바란다.

Option "b," drawing to a Canvas, is better when you're application needs to regularly re-draw itself. Basically, any video game should be drawing to the Canvas on its own. However, there's more than one way to do this:

옵션 “b”의 캔버스에 그리기는, 여러분의 애플리케이션이 규칙적으로 스스로를 다시 그려야 할 필요가 있을 때 더 좋다. 기본적으로 모든 비디오 게임은 그것 자신의 캔버스Canvas에 드로잉되어야 한다. 하지만 이것을 하는 데에는 한 가지 이상의 방법이 있다.

  • In the same thread as your UI Activity, wherein you create a custom View component in your layout, call invalidate() and then handle the onDraw() callback..
  • Or, in a separate thread, wherein you manage a SurfaceView and perform draws to the Canvas as fast as your thread is capable (you do not need to request invalidate()).
  • 여러분의 액티비티와 동일한 쓰레드에서 여러분의 레이아웃 내에 커스텀 뷰를 생성하고, invalidate()를 호출하고, 그런 다음 onDraw() 콜백을 처리한다.
  • 또는 별도의 쓰레드에서 거기에서 여러분은 서피스뷰SurfaceViw를 관리하고, 여러분의 쓰레드가 수용할 수 있는 한 빠르게 캔버스에 그리기를 수행한다.

...Begin by reading Draw with a Canvas.

“캔버스를 사용해서 그리기Draw with a Canvas” 를 읽는 것에서 시작하라.

Simple Graphics Inside a View

If you'll be drawing some simple graphics (images, shapes, colors, pre-defined animations, etc.), then you should probably just draw to the background of a View or to the content of an ImageView in your layout. In this case, you can skip the rest of this document and learn how to draw graphics and animations in the 2D Graphics document.

만약 여러분이 약간의 간단한 그래픽(이미지, 모양(shape), 컬러, 미리 정의된 애니메이션 등)을 드로잉하게 된다면, 여러분은 아마도 단지 뷰의 백그라운드에 그리거나, 또는 여러분의 레이아웃 내의 이미지뷰ImageView의 컨텐트에 그릴 것이다. 이런 경우, 여러분은 이 문서의 나머지 부분을 건너 뛰고, 2D 그래픽 문서에 있는 그래픽과 애니메이션을 그리는 방법을 배워라.

Draw with a Canvas

When you're writing an application in which you would like to perform specialized drawing and/or control the animation of graphics, you should do so by drawing through a Canvas. A Canvas works for you as a pretense, or interface, to the actual surface upon which your graphics will be drawn it holds all of your "draw" calls. Via the Canvas, your drawing is actually performed upon an underlying Bitmap, which is placed into the window.

여러분이 전문화된 드로잉 및/또는 그래픽 애니메이션에 대한 제어를 수행하는 애플리케이션을 작성할 때, 여러분은 캔버스를 통해 드로잉함으로써 그것을 해야 한다. 캔버스는 여러분의 그래픽이 그려지는 실제 표면에 대한 하나의 프리텐스pretense 또는 인터페이스로써, 여러분을 위한 작업을 수행한다 ? 그것은 여러분이 사용할 모든 “draw” 호출을 보유한다. 캔버스Canvas를 통해 여러분이 드로잉하는 것은 그 아래 놓여 있는 비트맵(Bitmap) 위에서 실제로 수행되며, 그 비트맵은 윈도우 안에 위치하게 된다.

In the event that you're drawing within the onDraw() callback method, the Canvas is provided for you and you need only place your drawing calls upon it. You can also acquire a Canvas from SurfaceHolder.lockCanvas(), when dealing with a SurfaceView object. (Both of these scenarios are discussed in the following sections.) However, if you need to create a new Canvas, then you must define the Bitmap upon which drawing will actually be performed. The Bitmap is always required for a Canvas. You can set up a new Canvas like this:

여러분이 만약 onDraw() 콜백 메쏘드 내에서 드로잉을 할 경우, 여러분을 위한 캔버스가 제공되며 여러분은 그 캔버스 위에 여러분의 드로잉 호출들을 놓으면 된다. 여러분이 서피스뷰SurfaceView 오브젝트를 다룰 때, SurfaceHolder.lock Canvas()로부터 캔버스를 또한 얻을 수 있다(이러한 모든 시나리오는 이후 섹션에서 논의된다). 하지만 여러분이 새로운 캔버스를 만들어야 할 필요가 있다면, 드로잉이 그 위에서 실제로 수행되는 비트맵을 정의해야 한다. 비트맵은 항상 캔버스를 위해 필요하다. 다음과 같이 새로운 캔버스를 만들 수도 있다.

Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);

Now your Canvas will draw onto the defined Bitmap. After drawing upon it with the Canvas, you can then carry your Bitmap to another Canvas with one of the Canvas.drawBitmap(Bitmap,...) methods. It's recommended that you ultimately draw your final graphics through a Canvas offered to you by View.onDraw() or SurfaceHolder.lockCanvas() (see the following sections).

이제 여러분의 캔버스는 정의된 비트맵 위에 그릴 것이다. 그 캔버스를 사용해서 그 위에 드로잉을 한 이후, 여러분은 Canvas.drawBitmap(Bitmap,…) 메쏘드들 중 하나를 사용해서 여러분의 비트맵을 또 다른 캔버스로 이동시킬 수 있다. View.onDraw()나 SurfaceHolder.lockCanvas()에 의해 여러분에게 제공되는 캔버스를 통해 최종 그래픽을 드로잉하는 것이 권장된다(이후의 섹션들을 보라).

The Canvas class has its own set of drawing methods that you can use, like drawBitmap(...), drawRect(...), drawText(...), and many more. Other classes that you might use also have draw() methods. For example, you'll probably have some Drawable objects that you want to put on the Canvas. Drawable has its own draw() method that takes your Canvas as an arguement.

캔버스 클래스는 drawBitmap(…), drawRect(…), drawText(…) 등과 같이 여러분이 사용할 수 있는 그것 자신의 드로잉 메쏘드 집합을 가지고 있다. 여러분이 사용할 지도 모를 다른 클래스들 역시 draw() 메쏘드들을 가지고 있다. 예를 들어 아마도 여러분은 캔버스 위에 놓고 싶은 약간의 드로어블Drawable 오브젝트를 가질 수 있다. 드로어블Drawable은 아규먼트로 여러분의 캔버스를 가지는 그것 자신의 draw() 메쏘드를 가지고 있다.

On a View

If you're application does not require a significant amount of processing or frame-rate speed (perhaps for a chess game, a snake game, or another slowly-animated application), then you should consider creating a custom View component and drawing with a Canvas in View.onDraw(). The most convenient aspect of doing so is that the Android framework will provide you with a pre-defined Canvas to which you will place your drawing calls.

만약 여러분의 애플리케이션이 많은 양의 프로세싱이나 프레임-레이트frame-rate 속도(아마도 체스 게임, 스네이크(snake) 게임, 또는 느리게 애니메이션되는 애플리케이션에 적합한)를 요구하지 않는다면, 여러분은 커스텀 뷰 컴포넌트를 생성하고 View.onDraw()에서 캔버스를 사용해 드로잉하는 것을 고려해야 한다. 그렇게 하는 것의 가장 편리한 측면은 안드로이드 프레임워크가 여러분의 드로잉 호출을 위치시키는 미리 정의된 캔버스를 여러분에게 제공할 것이라는데 있다.

To start, extend the View class (or descendent thereof) and define the onDraw() callback method. This method will be called by the Android framework to request that your View draw itself. This is where you will perform all your calls to draw through the Canvas, which is passed to you through the onDraw() callback.

이를 위해 우선, 뷰 클래스(또는 그것으로부터 파생된 것)를 확장extend하고 onDraw() 콜백 메쏘드를 정의하라. 이 메쏘드는 여러분의 뷰가 스스로를 그리도록 하기 위해 안드로이드 프레임워크에 의해 호출될 것이다. 이곳은 캔버스를 통해 그리기 위해 여러분이 모든 호출을 수행할 곳이며, 캔버스는 onDraw() 콜백을 통해 여러분에게 파라미터로 전달된다.

The Android framework will only call onDraw() as necessary. Each time that your application is prepared to be drawn, you must request your View be invalidated by calling invalidate(). This indicates that you'd like your View to be drawn and Android will then call your onDraw() method (though is not guaranteed that the callback will be instantaneous).

안드로이드 프레임워크는 필요할 때만 onDraw()를 호출할 것이다. 여러분의 애플리케이션이 그려질 준비가 될 때마다, 여러분은 invalidate()를 호출함으로써 여러분의 뷰가 무효화되도록 요청해야 한다. 이것은 여러분이 뷰가 그려지길 원한다는 것을 나타내며, 그러면 안드로이드는 여러분의 onDraw() 메쏘드를 호출할 것이다(콜백이 즉시 될 것이라고 보장되지는 않더라도).

Inside your View component's onDraw(), use the Canvas given to you for all your drawing, using various Canvas.draw...() methods, or other class draw() methods that take your Canvas as an argument. Once your onDraw() is complete, the Android framework will use your Canvas to draw a Bitmap handled by the system.

여러분의 뷰 컴포넌트의 onDraw()안에서, 여러분의 모든 드로잉을 위해 여러분에게 제공되는 캔버스를 사용하라. 여러분은 다양한 Canvas.draw...()메쏘드들 또는 아규먼트로 여러분의 캔버스를 가지는 다른 클래스의 draw() 메쏘드들을 사용한다. 일단 여러분의 onDraw()가 완료되면, 안드로이드 프레임워크는 시스템에 의해 취급되는 비트맵을 그리기 위해 여러분의 캔버스를 사용할 것이다.

Note: In order to request an invalidate from a thread other than your main Activity's thread, you must call postInvalidate().

Note: 여러분이 메인 액티비티의 쓰레드가 아닌 다른 쓰레드로부터 무효화invalidate를 요청하기 위해서는 postInvalidate()를 호출해야 한다.

Also read Building Custom Components for a guide to extending a View class, and 2D Graphics: Drawables for information on using Drawable objects like images from your resources and other primitive shapes.

또한 뷰 클래스를 확장하는 것에 대한 가이드에 대해서는 “커스텀 컴포넌트 만들기”를 읽어라. 그리고 여러분의 리소스와 다른 기본 형상primitive shapes에 이미지와 같은 드로어블Drawable 오브젝트를 사용하는 정보에 대해서는 “2차원 그래픽”의 “드로어블Drawables”을 읽어라.

For a sample application, see the Snake game, in the SDK samples folder: <your-sdk-directory>/samples/Snake/.

샘플 애플리케이션에 대해서는, SDK 샘플 폴더(<your-sdk-directory>/samples/Snake/)에 있는 스네이크 게임을 보라.

On a SurfaceView

The SurfaceView is a special subclass of View that offers a dedicated drawing surface within the View hierarchy. The aim is to offer this drawing surface to an application's secondary thread, so that the application isn't required to wait until the system's View hierarchy is ready to draw. Instead, a secondary thread that has reference to a SurfaceView can draw to its own Canvas at its own pace.

서피스뷰SurfaceView는 뷰 계층구조 내에서 드로잉 전용 공간surface를 제공하는 뷰에 대한 특수한 서브클래스이다. 그 목적은 시스템의 뷰 계층구조가 그릴 준비가 될 때까지 애플리케이션이 기다리지 않도록 하기 위해, 애플리케이션의 보조secondary 쓰레드에게 이러한 드로잉 공간을 제공하는데 있다. 서피스뷰SurfaceView에 레퍼런스를 가지고 있는 보조 쓰레드는 자신의 속도로 자신의 캔버스에 드로잉을 할 수 있다.

To begin, you need to create a new class that extends SurfaceView. The class should also implement SurfaceHolder.Callback. This subclass is an interface that will notify you with information about the underlying Surface, such as when it is created, changed, or destroyed. These events are important so that you know when you can start drawing, whether you need to make adjustments based on new surface properties, and when to stop drawing and potentially kill some tasks. Inside your SurfaceView class is also a good place to define your secondary Thread class, which will perform all the drawing procedures to your Canvas.

이를 위해 우선, 여러분은 서피스뷰SurfaceView를 확장하는 새로운 클래스를 생성하는 것이 필요하다. 이 클래스는 또한 SurfaceHolder.Callback을 구현해야만 한다. 이 서브클래스는 기반이 되는 서피스surface가 생성되고, 변경되고, 소멸될 때 기반이 되는 서피스surface에 대한 정보를 여러분에게 알려주는 인터페이스이다. 이러한 이벤트들은 여러분이 언제 드로잉을 시작할 것인지, 여러분이 새로운 서피스 속성들에 기반한 조정을 해야할 필요가 있는지 여부, 그리고 여러분이 언제 드로잉을 중단할 지와 잠재적으로 태스크를 강제 종료시킬 지를 여러분이 알 수 있도록 한다는 점에서 중요하다. 여러분의 서피스뷰SurfaceView 클래스 내부는 또한 여러분이 보조 쓰레드 클래스를 정의하기 좋은 장소이다. 그것은 여러분의 캔버스에 모든 드로잉 절차를 수행할 것이다.

Instead of handling the Surface object directly, you should handle it via a SurfaceHolder. So, when your SurfaceView is initialized, get the SurfaceHolder by calling getHolder(). You should then notify the SurfaceHolder that you'd like to receive SurfaceHolder callbacks (from SurfaceHolder.Callback) by calling addCallback() (pass it this). Then override each of the SurfaceHolder.Callback methods inside your SurfaceView class.

서피스Surface 오브젝트를 직접적으로 처리하는 대신에, 여러분은 Surface Holder를 통해 그것을 처리해야만 한다. 그러므로 여러분의 서피스뷰SurfaceView가 초기화 될 때, getHolder()를 호출해서 SurfaceHolder를 얻어라. 그리고 나서 여러분은 addCallback()(this를 파라미터로 전달하라)을 호출해서 (SurfaceHolder.Callback으로부터) SurfaceHolder 콜백을 수신하고자 한다는 것을 SurfaceHolder에 알려줘야 한다. 그리고 여러분의 서피스뷰SurfaceView 클래스 내의 각각의 SurfaceHolder.Callback 메쏘드들을 오버라이드하라.

In order to draw to the Surface Canvas from within your second thread, you must pass the thread your SurfaceHandler and retrieve the Canvas with lockCanvas(). You can now take the Canvas given to you by the SurfaceHolder and do your necessary drawing upon it. Once you're done drawing with the Canvas, call unlockCanvasAndPost(), passing it your Canvas object. The Surface will now draw the Canvas as you left it. Perform this sequence of locking and unlocking the canvas each time you want to redraw.

여러분의 보조 쓰레드 내에서 서피스Surface 캔버스에 그리기 위해, 그 쓰레드에 SurfaceHandler를 전달하고 lockCanvas()를 사용해서 캔버스를 가져와야 한다. 이제 여러분은 SurfaceHolder에 의해 제공된 캔버스를 보유할 수 있으며, 그 위에 여러분에게 필요한 드로잉을 할 수 있다. 일단 여러분이 캔버스를 사용해서 드로잉하는 것을 마쳤다면, unlockCanvasAndPost()를 호출하고 그것에 여러분의 캔버스 오브젝트를 파라미터로 전달하라. 서피스Surface는 이제 여러분이 캔버스에 남겨둔 대로 그 캔버스를 그릴 것이다. 여러분이 다시 그리고 싶을 때마다 캔버스를 lock하고 unlock하는 이 절차를 수행하라.

Note: On each pass you retrieve the Canvas from the SurfaceHolder, the previous state of the Canvas will be retained. In order to properly animate your graphics, you must re-paint the entire surface. For example, you can clear the previous state of the Canvas by filling in a color with drawColor() or setting a background image with drawBitmap(). Otherwise, you will see traces of the drawings you previously performed.

Note: 여러분이 SurfaceHolder로부터 캔버스를 가져오는 각 패스pass에서, 캔버스의 이전 상태는 계속 유지된다. 여러분의 그래픽을 적절하게 애니메이션하기 위해, 여러분은 전체 서피스surface를 다시 그려야 한다. 예를 들어 여러분은 drawColor()를 사용해서 하나의 색으로 채우거나 또는 drawBitmap()을 사용해서 배경 이미지를 설정함으로써, 캔버스의 이전 상태를 깨끗하게 지울 수 있다. 그렇지 않은 경우라면, 여러분은 이전에 수행했던 드로잉 흔적을 볼 것이다.

For a sample application, see the Lunar Landar game, in the SDK samples folder: <your-sdk-directory>/samples/LunarLander/. Or, browse the source in the Sample Code section.

샘플 애플리케이션에 대해서는, SDK samples 폴더 <your-sdk-directory>/samples/LunarLander/ 에 있는 Lunar Landar 게임을 보거나 또는 Sample Code 섹션에 있는 소스를 찾아보라.

↑ Go to top