Using layout resources in Android LiveWallpaper

When you create a LiveWallpaper in Android 2.2+, you get a canvas (or, what is the same as the 3D equivalent) to draw. I would like to draw some elements using the built-in tools of the Android user interface, rather than building everything from scratch using canvas commands or loading a previously displayed bitmap of the user interface.

Converting a single image to a bitmap works fine. those. this works fine:

// 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 LinearLayout with children is causing problems. You get only LinearLayout and not one of them. For example, if I set LinearLayout to a white background, I get a beautifully rendered white square, but none of the TextView children are in the bitmap. I also tried using DrawingCache with similar results.

The code I use is an example of a cube, with the only changes being an additional drawing command. LinearLayout works great as a toast or as a normal view (i.e., everything is well displayed), on the LiveWallpaper all I get is the rendered LinearLayout background.

 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 something special so that children display correctly in my bitmap? that is, do I need to somehow do something special so that the layout displays the rest of the children? Do I have to write a function to do something recursively for all children?

I could assemble everything myself, but since the display is quite static (i.e. I draw once and save a copy of the bitmap to draw on the background), it seems easier and still quite effective.

Edit: Although digging is a bit more in the layout state, it seems that the layout does not progress down the view tree (i.e. LinearLayout gets its layout computed when calling layout (), but the children have zero size (0x0)). According to Romain Guy in 2008, Android developer post . You must wait for the layout to go through or force the layout yourself. The problem is, how can I wait for the layout to transition from the wallpaper for LinearLayout, which is not tied to the root view group? And how can I manually split each child if the layout requires you to set left, top, right, bottom when I don't know what it should be.

I tried calling forceLayout for children, but it doesn't seem to help either. I'm not sure how the layout structure works behind the scenes (except that it does a two-pass layout). Is there a way to manually do this to skip the layout, that is, right now? Since this is not an event, I do not think that many normal background things happen exactly as we would like.

+5
source share
2 answers

Live wallpapers have been specifically designed to NOT use standard user interface widgets. However, they can be used in any case. You will need to make the layout skip itself, first calling measure () in the view, and then layout (). You can find more information in my presentation .

+8
source

Here is an example of a view group, button, and image laid out and displayed in Live Wallpapers. You can also bypass the zero-window marker error and add views directly through the WindowManager if you set the Window type to 0. You should catch the exception that it throws and the results are somewhat unstable, 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 ) { } } } 
+3
source

Source: https://habr.com/ru/post/920275/


All Articles