Understanding 2D Drawing in Android

Understanding 2D Drawing in Android

Android comes along with strong open-source API libraries which support customized 2D and 3D graphics in addition to animations.

The Android framework APIs as well makes available a set of 2D-drawing APIs which gives you room to customize graphics onto a canvas or to alter current Views to change their appearance and feel.

When drawing 2D graphics, you will characteristically do that in two ways. API makes available 2D drawing APIs for simple animation that does not have any need for key alterations changes. These two ways of carrying this out using API are:

To draw to a View

To draw on a Canvas

Drawing a circle to View

Drawing to view is a preferred option when your UI does not require dynamic alterations in the application. The most suitable aspect of doing so is that the Android framework will make available for you a pre-defined Canvas to which you will put your drawing calls.

This can be fulfilled merely simply by extending the View category and define an onDraw() callback technique.

Inside your View constituent’s onDraw(), Make use of the Canvas offered to you for everyone of drawing, make use of lot of Canvas.draw…() techniques (Ex: canvas.drawCircle(x / 2, y / 2, radius, paint);). onDraw() is a callback technique called when the view is at first drawn.

Drawing to a Canvas

This is the preferred option when your application requires to constantly re-draw itself. Applications like video games ought to be drawing to the Canvas by itself. Although, there are other ways this could be achieved.

The example below illustrates in a straightforward way the code showing how to draw a circle as mentioned earlier.

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(new MyView(this));
}
public class MyView extends View {

public MyView(Context context) {
   super(context);
   // TODO Auto-generated constructor stub
}

@Override
protected void onDraw(Canvas canvas) {
  // TODO Auto-generated method stub
  super.onDraw(canvas);
  int x = getWidth();
  int y = getHeight();
  int radius;
  radius = 100;
  Paint paint = new Paint();
  paint.setStyle(Paint.Style.FILL);
  paint.setColor(Color.WHITE);
  canvas.drawPaint(paint);
  
  // Use Color.parseColor to define HTML colors
  paint.setColor(Color.parseColor("#CD5C5C"));
  canvas.drawCircle(x / 2, y / 2, radius, paint);
}
}
}

 How to draw 2D Objects on a canvas

To draw 2D graphics in a place in your application that requires to constantly re draw itself, the best option for you is to draw on a canvas. A Canvas functions for you as an interface, to the real surface on which your graphics will be drawn.

If you are required to produce a fresh Canvas, then you ought to specify the bitmap on which drawing will in reality be out. The Bitmap is at all times needed for a Canvas.

The code below illustrates the way to draw a rectangle in a canvas as specified above.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/rect">
</LinearLayout>

 

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.Menu;
import android.widget.LinearLayout;

public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Paint paint = new Paint();
paint.setColor(Color.parseColor("#CD5C5C"));
Bitmap bg = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bg);
canvas.drawRect(50, 50, 200, 200, paint);
LinearLayout ll = (LinearLayout) findViewById(R.id.rect);
ll.setBackgroundDrawable(new BitmapDrawable(bg));
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
   getMenuInflater().inflate(R.menu.activity_main, menu);
   return true;
}
}

 

Drawables

Android provides a customized 2D graphics files for drawing shapes and images. The android.graphics.drawable file is the location where the regular categories used for drawing in two-dimensions can be found.

We have provided here the fundamentals of making use of Drawable objects to draw graphics and how to make use of a few subclasses of the Drawable category.

A Drawable is a common abstraction for “something that can be drawn.” You’ll find out that the Drawable category extends to define a lot of particular forms of drawable graphics, which consists of BitmapDrawable, ShapeDrawable, PictureDrawable, LayerDrawable, and many others. You can as well extend these to specify your own customized Drawable objects that act in particular ways.

There are three ways to specify and initiate a Drawable: Through the utilization of an image saved in your project resources; through the use of an XML file that specifies the Drawable features; or the of standard category constructors.

Generating from resource images

An easy way to incorporate graphics to your application is by referring to an image file from your project resources.

The file types that are supported are PNG ( which is the most preferred option), JPG ( which is an acceptable option) and GIF ( which should not be used at all). This method would clearly be preferred for application icons, logos, or other graphics like those made use of in a game.

To make use of an image resource, you merely require to incorporate your file to the res/drawable/ directory of your project.

You can the refer it from your code or your XML layout. Whichever one you choose it is termed making use of a resource ID, which is the file name without the extension of the file type extension like my_image.png is referenced as my_image.

Example code

The code below illustrate the way to create an Image View that makes use of an image from drawable resources and incorporate it to the layout.

LinearLayout mLinearLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a LinearLayout in which to add the ImageView
mLinearLayout = new LinearLayout(this);
// Instantiate an ImageView and define its properties
ImageView i = new ImageView(this);
i.setImageResource(R.drawable.my_image);
i.setAdjustViewBounds(true); // set the ImageView bounds to match the Drawable's dimension
i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
// Add the ImageView to the layout and set the layout as the content view
mLinearLayout.addView(i);
setContentView(mLinearLayout);
}

In other scenarios, you may want to take care of your image resource as a Drawable object. To be able to achieve this, build a Drawable from the resource such as:

Resources res = mContext.getResources();

Drawable myImage = res.getDrawable(R.drawable.my_image);

Every singular resource in your project can sustain just a unique state, irrespective of the number of various objects you may initiate for it.

For instance, if you initiate two Drawable objects from an equivalent image resource, then alter a property (like the alpha) for one of the Drawables, then it will as well affect the other.

Thus anytime you are handling a lot of examples of an image resource, rather than unswervingly changing the Drawable, you ought to carry out a tween animation.

Example XML

The XML code below illustrates how to add a resource Drawable to an ImageView in the XML layout (with a few red tint merely to offer fun).

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="#55ff0000"
android:src="@drawable/my_image"/>

 Creating from resource XML

You ought to have at this stage be able to create a User Interface. Therefore you should know the strength and flexibility intrinsic in specifying objects in XML.

This is transferred from Views to Drawables. If there is a Drawable object that you’d wish to produce, which is not at first reliant on variables specified by your application code or user interaction, then specifying the Drawable in XML is an excellent option.

Even if you expect your Drawable to alter its features during the user’s experience with your application, you ought to take into consideration the specification of the object in XML, as you can at all times alter properties immediately it is initiated.

Immediately you’ve specified your Drawable in XML, store the file in the res/drawable/directory of your project and after that retrieve and initiate the object by calling Resources.getDrawable(), transferring to it the resource ID of your XML file.

Any Drawable subcategory that supports the inflate() technique can be specified in XML and started by your application. Each Drawable that supports XML inflation makes use of particular XML characteristics that assist you to define the object properties. See the category documentation for every Drawable subcategory for information on how to specify it in XML.

Example

Below are a few XML that specifies a TransitionDrawable:

<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/image_expand">
<item android:drawable="@drawable/image_collapse">
</transition>

With this XML stored in the file res/drawable/expand_collapse.xml, the code will kick off the TransitionDrawable and set it as the content of an ImageView:

Resources res = mContext.getResources();
TransitionDrawable transition = (TransitionDrawable)
res.getDrawable(R.drawable.expand_collapse);
ImageView image = (ImageView) findViewById(R.id.toggle_image);
image.setImageDrawable(transition);
At this point the transition can be run forward (for 1 second) with:
transition.startTransition(1000);

 Shape Drawable

Anytime you intend to draw a few 2D graphics dynamically, a ShapeDrawable object will possibly be what you need to achieve this.

A ShapeDrawable, allows you c to draw as a program primeval shapes and design them in any way you can think of.

A ShapeDrawable is an expansion of Drawable, that allows you to make use of it anywhere a Drawable is should be used like for the background of a View, set with setBackgroundDrawable().

Of course, you can as well draw your shape as its own customized View, to be incorporated to your layout no matter the way it pleases you.

Due to the fact that ShapeDrawable possess its own draw() technique, you can produce a subcategory of View that draws the ShapeDrawable during the View.onDraw() technique

See below the main expansion of the View category that draw a ShapeDrawable as a View:

public class CustomDrawableView extends View {
private ShapeDrawable mDrawable;

public CustomDrawableView(Context context) {
super(context);
int x = 10;
int y = 10;
int width = 300;
int height = 50;

mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}

protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}

In the constructor, a ShapeDrawable is specified as an OvalShape. It’s then offered a color and the limits of the shape are set. If you do not set the limits, then the shape will not be drawn, while if you fail to set the color, it will change to black color by default.

With the customized View specified, it can be drawn in any form that pleases you. With the sample above, we can draw the shape as a program in an Activity:

CustomDrawableView mCustomDrawableView;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
}

If you wish to draw this customized drawable from the XML layout rather than from the Activity, then the CustomDrawable category ought to override the View (Context, characteristic Set) constructor which is invoked during the start of a View through inflation from XML. After this incorporate a CustomDrawable factor to the XML, such as:

<com.example.shapedrawable.CustomDrawableView
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>

The ShapeDrawable category such as a lot of other Drawable types in the android.graphics.draw+able package permits you to specify a lot of properties of the drawable with public techniques.

A few properties you may wish to alter are alpha transparency, color filter, dither, opacity and color.

You can as well specify primordial drawable shapes with the use of XML.

Nine-patchDrawable graphic

A NinePatchDrawable graphic is a bitmap image that can be stretched, which Android will routinely adjust contain the contents of the View in which you have put in it as the background.

One instance that shows the use of a NinePatch is the backgrounds used by typical Android buttons — buttons ought to stretch to contain strings of varying lengths.

The Draw 9-patch tool presents an exceptionally practical way to build your NinePatch pictures, with the use of a WYSIWYG graphics editor. It even increases warnings if the area you’ve specified for the extendable region is at risk of producing drawing artifacts due to the pixel duplication.

Example XML

Below is a few instance of sample layout XML that shows how to add a NinePatch image to a group of buttons. The NinePatch image is stored in the form res/drawable/my_button_background.9.png

<Button id="@+id/tiny"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:text="Tiny"
android:textSize="8sp"
android:background="@drawable/my_button_background"/>

<Button id="@+id/big"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:text="Biiiiiiig text!"
android:textSize="30sp"
android:background="@drawable/my_button_background"/>

Observe that the width and height are set to “wrap_content” to see to it that the button fit precisely about the text.

OTHER INTERESTING POSTS:

Add a Comment