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 too
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 )
{
}
}
}