Using Layout resources in a LiveWallpaper on Android - android

When you create a LiveWallpaper in Android 2.2+ you get a canvas (or whatever the 3D equivalent is) to draw on. I'd like to draw some elements using the built-in Android UI tools rather than building everything from scratch using canvas commands or a loading a pre-rendered UI bitmap.
Converting a single View to a Bitmap works fine. i.e. this works great:
// For example this works:
TextView view = new TextView(ctx);
view.layout(0, 0, 200, 100);
view.setText("test");
Bitmap b = Bitmap.createBitmap( 200, 100, Bitmap.Config.ARGB_8888);
Canvas tempC = new Canvas(b);
view.draw(tempC);
c.drawBitmap(b, 200, 100, mPaint);
But, converting a LinearLayout with children causes problems. You only get the LinearLayout itself and none of it's children. For example, if I set the LinearLayout to have a white background I get a nicely rendered white box, but none of the TextView children are in the Bitmap. I've also tried using DrawingCache with similar results.
The code I'm using is the cube example with the only changes being an extra draw command. The LinearLayout works fine as a toast or as a regular view (i.e. everything nicely shows up), on the LiveWallpaper all I get is the LinearLayout's background rendered.
inflater = (LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = (LinearLayout) inflater.inflate(com.example.android.livecubes.R.layout.testLinearLayout, null);
layout.layout(0, 0, 400, 200);
Bitmap b = Bitmap.createBitmap( 400, 200, Bitmap.Config.ARGB_8888);
Canvas tempC = new Canvas(b);
layout.draw(tempC);
c.drawBitmap(b, 10, 200, mPaint);
Does anyone know if you need to do anything special to get the children rendered properly to my bitmap? i.e. do I need to somehow do something special to make the layout render the rest of the children? Should I write a function to recursively do something to all the children?
I could composite everything myself but, since the display is fairly static (i.e. I draw this once and keep a copy of the bitmap to draw on the background) this seems easier on me and still pretty efficient.
Edit:
While digging a bit more into the state of the Layout it looks as though the layout is not progressing down the view tree (i.e. the LinearLayout gets its layout computed when I call layout() but the children have a null (0x0) size). According to the Romain Guy's post in 2008 android developer post. You have to wait for the layout pass or force the layout yourself. The problem is how can I wait for a layout pass from a wall paper engine for a LinearLayout that is not attached to the root view group? And how can I manually layout each child element if layout requires you to set the left, top, right, bottom when I don't know what these should be.
I've tried calling forceLayout on the children but it doesn't seem to help either. I'm not sure how the layout framework works behind the scenes (besides that it does a two pass layout). Is there a way to manually make it do the layout pass, i.e. right now? Since it's not an Activity I don't think a lot of the normal background stuff is happening quite the way I'd like.

Live Wallpapers were very specifically designed to NOT use standard UI widgets. However it is possible to use them anyway. You will have to force a layout pass yourself by first calling measure() on the View, then layout(). You can find more information in my presentation.

Here's an example of a view group, button and imageview laid out and displayed in a Live Wallpapers. You can also work around the null window token bug and add views directly via WindowManager if you set the the Window type to 0. You have to catch the exception it throws and the results are somewhat erratic but it works for the most part.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class UIWidgetWallpaper extends WallpaperService
{
private final String TAG = getClass().getSimpleName();
final static int pixFormat = PixelFormat.RGBA_8888;
protected ImageView imageView;
protected WindowManager windowManager;
protected LayoutParams layoutParams;
protected WidgetGroup widgetGroup;
protected SurfaceHolder surfaceHolder;
protected Button button;
#Override
public Engine onCreateEngine()
{
Log.i( TAG, "onCreateEngine" );
return new UIWidgetWallpaperEngine();
}
public class WidgetGroup extends ViewGroup
{
private final String TAG = getClass().getSimpleName();
public WidgetGroup( Context context )
{
super( context );
Log.i( TAG, "WidgetGroup" );
setWillNotDraw( true );
}
#Override
protected void onLayout( boolean changed, int l, int t, int r, int b )
{
layout( l, t, r, b );
}
}
public class UIWidgetWallpaperEngine extends Engine implements Callback
{
private final String TAG = getClass().getSimpleName();
#Override
public void onCreate( SurfaceHolder holder )
{
Log.i( TAG, "onCreate" );
super.onCreate( holder );
surfaceHolder = holder;
surfaceHolder.addCallback( this );
imageView = new ImageView( getApplicationContext() );
imageView.setClickable( false );
imageView.setImageResource( R.drawable.icon );
widgetGroup = new WidgetGroup( getApplicationContext() );
widgetGroup.setBackgroundDrawable( getWallpaper() );
widgetGroup.setLayoutParams( new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) );
widgetGroup.setAddStatesFromChildren( true );
holder.setFormat( pixFormat );
LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT );
imageParams.weight = 1.0f;
imageParams.gravity = Gravity.CENTER;
widgetGroup.addView( imageView, imageParams );
button = new Button( getApplicationContext() );
button.setText( "Test Button" );
LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT );
buttonParams.weight = 1.0f;
buttonParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
widgetGroup.addView( button, buttonParams );
}
#Override
public void surfaceChanged( SurfaceHolder holder, int format, int width, int height )
{
Log.i( TAG, "surfaceChanged: " );
synchronized( surfaceHolder )
{
Canvas canvas = surfaceHolder.lockCanvas();
widgetGroup.layout( 0, 0, width, height );
imageView.layout( 0, 0, width / 2, height );
button.layout( width / 2, height - 100, width, height );
widgetGroup.draw( canvas );
surfaceHolder.unlockCanvasAndPost( canvas );
}
}
#Override
public void surfaceCreated( SurfaceHolder holder )
{
}
#Override
public void surfaceDestroyed( SurfaceHolder holder )
{
}
}
}

Related

Getting the width/height of a layout in Android

I'm wondering how to measure the dimensions of a view. In my case it is aan Absolute Layout. I've read the answers concerning those questions but I still don't get it.
This is my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AbsoluteLayout layoutbase = (AbsoluteLayout) findViewById(R.id.layoutbase);
drawOval();
}
public void drawOval(){ //, int screenWidth, int screenHeight){
AbsoluteLayout layoutbase = (AbsoluteLayout) findViewById(R.id.layoutbase);
int screenWidth = layoutbase.getWidth();
int screenHeight = layoutbase.getHeight();
Log.i("MyActivity", "screenWidth: " + screenWidth + ", screenHeight: " +screenHeight);
Coordinates c = new Coordinates(BUTTONSIZE,screenWidth,screenHeight);
...some code ...
((ViewGroup) layoutbase ).addView(mybutton, new AbsoluteLayout.LayoutParams(BUTTONSIZE, BUTTONSIZE, c.mX, c.mY));
mybutton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
showText(mybutton);
}
});
}
public void showText(View button){
int x = findViewById(LAYOUT).getWidth();
int y = findViewById(LAYOUT).getHeight();
Toast message = Toast.makeText(this, "x: " + x , Toast.LENGTH_SHORT);
message.show();
}
The getWidth() command works great in showText() but it does not in drawOval(). I know it looks a bit different there but I also used the int x = findViewById(LAYOUT).getWidth(); version in drawOval(), and x/y are always 0. I don't really understand why there seems to be no width/height at that earlier point. Even if I actually draw a Button on the Absolute Layout, getWidth() returns 0. Oviously I want to measure the sizes in drawOval().
I think will help you.
LinearLayout headerLayout = (LinearLayout)findviewbyid(R.id.headerLayout);
ViewTreeObserver observer = headerLayout .getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
int headerLayoutHeight= headerLayout.getHeight();
int headerLayoutWidth = headerLayout.getWidth();
headerLayout .getViewTreeObserver().removeGlobalOnLayoutListener(
this);
}
});
}
getWidth() is giving you 0 because onCreate is called before layout actually happens. Due to views being able to have dynamic positions and sizes based on attributes or other elements (fill_parent for example) there's not a fixed size for any given view or layout. At runtime there is a point in time (actually it can happen repeatedly depending on many factors) where everything is actually measured and laid out. If you really need the height and width, you'll have to get them later as you've discovered.
This specially deal with Dimensions so
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
This may help you in managing dimensions.
Note: This returns the display dimensions in pixels - as expected. But the getWidth() and getHeight() methods are deprecated. Instead you can use:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
as also Martin Koubek suggested.
If your goal is to simply draw an oval on the screen, then consider creating your own custom View rather than messing around with AbsoluteLayout. Your custom View must override onDraw(android.graphics.Canvas), which will be called when the view should render its content.
Here is some extremely simple sample code that might help get you started:
public class MainActivity extends Activity {
private final Paint mPaint = new Paint();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
// create a nested custom view class that can draw an oval. if the
// "SampleView" is not specific to the Activity, put the class in
// a new file called "SampleView.java" and make the class public
// and non-static so that other Activities can use it.
private static class SampleView extends View {
public SampleView(Context context) {
super(context);
setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.CYAN);
// smoothen edges
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(4.5f);
// set alpha value (opacity)
mPaint.setAlpha(0x80);
// draw oval on canvas
canvas.drawOval(new RectF(50, 50, 20, 40), mPaint);
}
}
}
This give you screen resolution:
WindowManager wm = (WindowManager)context.getSystemService(context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point outSize = new Point();
display.getSize(outSize);
kabuko's answer is correct, but could be a little more clear, so let me clarify.
getWidth() and getHeight() are (correctly) giving you 0 because they have not been drawn in the layout when you call them. try calling the two methods on the button after addView() (after the view has been drawn and is present in the layout) and see if that gives you the expected result.
See this post for more information.

How do a create a landscape version of my view without actually being in landscape mode?

I am trying to make a view controller that is fixed in portrait mode, but that has a landscape version that can "fade in" over the top. What this means is that I need to be able to have a version of the screen that is the correct size for landscape, and is rotated 90 (or 270 depending) degrees. On iPhone this was easy, but I'm struggling with Android. I've got a custom view containing the view I want rotated, but I can't seem to size the child view correctly, or get the rotation to line up correctly. Is there an easier way? Alternatively, what am I doing wrong here?
#Override
protected void onDraw(Canvas canvas) {
if (getChildCount() == 1) {
canvas.save();
canvas.rotate(90, canvas.getWidth() / 2, canvas.getHeight() / 2);
// I have no idea what my pivot point should be
View child = getChildAt(0);
Bitmap bitmap = // bitmap of child
Paint paint = new Paint();
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.restore();
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (getChildCount() == 1) {
View child = getChildAt(0);
child.layout(top, left, bottom, right);
}
}
What is not helpful is suggesting actually changing the orientation of the view controller. I need it to stay in portrait mode in order to show the portrait version at the same time with a partial alpha transparency.
To be clear, I need to be able to interact with the view in its rotated coordinates, so I need to be able to press buttons, use a scrollview, etc.
API Level 11 introduces setRotationX/Y for Views, which seems to be exactly what you're looking for.
Supposing Honeycomb is not you target API version, here's what I found out after a few hours toying with this (definitely more challenging than my current project!):
Rendering is certainly doable (and relatively easy)
It's a massive hack and you shouldn't be doing it in the first place
Basically, the main issue is not rendering but processing events. Since Android has no idea that the view is sideways (you just rendered it that way), the view will respond to the area bounded by original pre-rotation coordinates. Therefore, no clicking (well, unless you have a square button that just has the text sideways!).
Really, you should probably look into backporting the Honeycomb changes.
With that said and with a large disclaimer that there might be a multitude of cases where this won't work, here's a sample app:
package com.side;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
public class TestActivity extends Activity {
private class SidewaysGroup extends ViewGroup{
public SidewaysGroup(Context context) {
super(context);
}
#Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
Log.i("Sideways", "Parent size: " + getWidth() + "x" + getHeight() + ", child size: " + child.getWidth() + "x" + child.getHeight());
// Create a new canvas for the child (there's probably a way to use the original canvas but I couldn't figure out the transformations)
Canvas childCanvas = new Canvas();
Bitmap childBitmap = Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888);
childCanvas.setBitmap(childBitmap);
boolean ret = super.drawChild(childCanvas, child, drawingTime);
Matrix matrix = new Matrix();
// rotate at the bottom left corner
matrix.postRotate(90f, 0, childBitmap.getHeight());
// after the rotation we are one `height` further down than we should be
matrix.postTranslate(0, -childBitmap.getHeight());
canvas.drawBitmap(childBitmap, matrix, new Paint());
return ret;
}
#Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
if(changed && getChildCount()==1)
{
final View child = getChildAt(0);
// This is breaking the flow (measuring would be done twice) - should be moved to onMeasure or measure() itself
// notice that it inverts the dimensions
child.measure(MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(
getMeasuredWidth(), MeasureSpec.AT_MOST));
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
}
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView verticalView = new TextView(this);
verticalView.setText("This is the vertical text");
verticalView.setGravity(Gravity.CENTER);
verticalView.setTextSize(50f);
verticalView.setTextColor(Color.parseColor("#88ffffff")); // add a bit of transparency to the text
SidewaysGroup group = new SidewaysGroup(this);
Button horizontalButton= new Button(this);
horizontalButton.setText("This is the horizontal button");
horizontalButton.setGravity(Gravity.CENTER);
horizontalButton.setTextSize(50f);
horizontalButton.setBackgroundDrawable(null);
horizontalButton.setTextColor(Color.WHITE);
horizontalButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.i("Sideways", "Button click");
}
});
group.addView(horizontalButton);
RelativeLayout mainLayout = new RelativeLayout(this);
RelativeLayout.LayoutParams relparams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
relparams.addRule(RelativeLayout.CENTER_IN_PARENT);
mainLayout.addView(verticalView, relparams);
mainLayout.addView(group, relparams);
setContentView(mainLayout);
mainLayout.requestLayout();
}
}
Focusing and translating events are left as an exercise to the reader :)
Do You want to scroll in both views (Vertical and Horizontal?)
If not, maybe you can take a screenshot of the vertical text (see here ) then do an actual rotation of your layout (i know you didn't want that but I don't understand why, if the vertical view is just needed as an overlay) and then use the screenshot of the vertical screen as an simple transparent bitmap overlay...
From your comments it sounds like you want this:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:id="#+id/linearlayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" />
</LinearLayout>
<LinearLayout
android:id="#+id/linearlayout2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
</LinearLayout>
</FrameLayout>
but I can't see how or why you would want this

Android Views Are Not As Tall As Specified

I am using RelativeLayout to position views at precise locations on the screen. This works as expected when using a view that say, draws a rectangle. But when using Android views like EditText, they are drawn shorter than specified by about 8 units. Clicking outside of the drawn EditText (but within the parameters specified by RelativeLayout) will, in fact, hit the EditText.
Here is some code to illustrate what I mean:
package com.DrawDemo;
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;
import android.widget.EditText;
import android.widget.RelativeLayout;
public class DrawDemo extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
RelativeLayout l = new RelativeLayout(this);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(100,100);
lp.leftMargin = 50;
lp.topMargin = 50;
DemoView demoview = new DemoView(this);
l.addView(demoview, lp);
EditText editText = new EditText(this);
l.addView(editText, lp);
setContentView(l);
}
private class DemoView extends View
{
public DemoView(Context context)
{
super(context);
}
#Override protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
canvas.drawPaint(paint);
}
}
}
If you execute this, you will notice that the EditText is noticeably shorter than the rectangle. I've tried mucking with onMeasure, setMinimumXXX, and just about everything else I can think of. So far, the only thing that works with some level of success is to just add 8 or so pixels to the height (8 seems to work better than trying a percentage of the height).
Next task will be to step into the source but was wondering if somebody has already solved this.
Thanks.
It's just because of the actual EditText background image that's used. Buttons are the same way, for some reason Google decided to draw the 9-patch background images with some extra transparent padding pixels. Really, the only solution, if it's a problem, would be to draw your own 9-patch, or modify the existing Android 9-patch to remove the extra pixels.

Android Drawing

I'm quite new to android, but basically I want to set up a program so that when the user clicks on an imageview, a dot is drawn where they click. I have tried many times but just don't seem to be able to get it to work, and help would be much appreciated.So far I have
package com.smallbore.smallbore;
import android.app.Activity;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class targetenter extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.targetenter);
ImageView v = (ImageView) findViewById(R.id.imageView1);
v.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
TextView t1 = (TextView) findViewById(R.id.textView2);
TextView t2 = (TextView) findViewById(R.id.textView3);
t1.setText("X: "+arg1.getX());
t2.setText("Y: "+arg1.getY());
int x = (int)arg1.getX();
int y = (int)arg1.getY();
int width = 50;
int height = 50;
ShapeDrawable mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
ImageView v = (ImageView) findViewById(R.id.imageView1)
v.setImageDrawable(mDrawable);
return false;
}
});
};
}
To draw the dots, you'll probably have to use a custom View and override onTouchEvent and onDraw. onTouchEvent will give you the x,y coordinates of the touch event and in onDraw you can draw a circle at this point to the canvas that the framework provides to this method. If you want to clear previous dots, you only need to keep track of the last x,y coordinates. Otherwise, you'll need to keep a running list (ArrayList or something like that).
In your shoes, I'd probably subclass ImageView so that I get the image drawing stuff for free. Call super.onDraw(canvas) inside the overridden onDraw method, and then draw your dots (canvas.drawCircle).
The Android SDK contains a pretty good example : http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/DrawPoints.html
You just need to make SampleView handling click event, and get it displaying the image in SampleView.onDraw method.

ANDROID: Custom view implemtation

I have a custom view. When will android call draw() on it? After it calls onMeasure and onLayout?
'package global.domination.pack;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.Log;
import android.view.View;
public class TileView extends View {
// rules about what can be and is on this tile
boolean bLand;
boolean bSea;
boolean bAir;
boolean bOccupied;
Character _character;
// this tile's coordinates
int nX;
int nY;
// bitmaps used for drawing this tile
Bitmap _originalBitmap;
Bitmap _finalBitmap;
// this constructor initializes all variables (creates the tile)
public TileView(Context context, boolean isLand, boolean isSea, boolean isAir, boolean isOccupied, int x_Coordinate, int y_Coordinate, Bitmap bitmap) {
super(context);
//Initialize variables and set tile graphic.
bLand = isLand;
bSea = isSea;
bAir = isAir;
bOccupied = isOccupied;
nX = x_Coordinate;
nY = y_Coordinate;
_originalBitmap = bitmap;
_character = null;
_finalBitmap = bitmap;
}
/* This method is called by parent view when it
* wants to know this view's drawing preferences
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// set this tiles dimensions
this.setMeasuredDimension(50, 50);
}
/* This method is called by parent view when it wants
* this view to draw itself.
*/
#Override
protected void onDraw(Canvas canvas) {
// attempt to draw the _finalBitmap (tile graphic with character graphic)
try{
canvas.drawBitmap(_finalBitmap, 0, 0, null);
}
catch(RuntimeException rtException){
Log.e("EXCEPTION", "ERROR DRAWING FINAL BITMAP" + rtException.getMessage() , rtException);
}
}
}
'
Are you overriding the onMeasure() of the ViewGroups? If so you need to remember to call measure() on you child views.
onMeasure() is always called whenever a view have to measure dimensions of its own and child views.
If you are going to implement the viewgroup then its child view's onDraw() method will be called whenever a viewgroup has to dispatch draw event to all its childs after onLayout().
Here is a image link which may help you understanding view lifecycle flow:
For brief description you may read the official doc.

Categories

Resources