5

当您在 Android 2.2+ 中创建 LiveWallpaper 时,您会得到一个画布(或任何 3D 等效物)来绘制。我想使用内置的 Android UI 工具绘制一些元素,而不是使用画布命令或加载预渲染的 UI 位图从头开始构建所有内容。

将单个视图转换为位图可以正常工作。即这很好用:

// 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);

但是,使用子元素转换 LinearLayout 会导致问题。你得到 LinearLayout 本身,没有它的孩子。例如,如果我将 LinearLayout 设置为具有白色背景,我会得到一个渲染良好的白色框,但位图中没有 TextView 子项。我也尝试过使用具有类似结果的 DrawingCache。

我使用的代码是立方体示例,唯一的变化是一个额外的绘制命令。LinearLayout 可以作为吐司或常规视图正常工作(即一切都很好地显示),在 LiveWallpaper 上我得到的只是 LinearLayout 的背景渲染。

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);

有谁知道您是否需要做任何特别的事情才能让孩子正确呈现到我的位图上?即我是否需要以某种方式做一些特别的事情来使布局呈现其余的孩子?我应该编写一个函数来递归地对所有孩子做某事吗?

我可以自己合成所有内容,但是,由于显示是相当静态的(即我绘制一次并保留位图的副本以在背景上绘制),这对我来说似乎更容易并且仍然非常有效。

编辑: 虽然对布局的状态进行了深入研究,但它看起来好像布局没有沿着视图树向下推进(即,LinearLayout 在我调用 layout() 时计算其布局,但子级的大小为 null (0x0) )。根据 Romain Guy 在 2008 年android developer post 的帖子。您必须等待布局通过或自己强制布局。问题是如何等待来自墙纸引擎的布局传递,用于未附加到根视图组的 LinearLayout?如果布局需要您设置左、上、右、下,而我不知道这些应该是什么,我该如何手动布局每个子元素。

我试过对孩子们调用 forceLayout ,但它似乎也没有帮助。我不确定布局框架在幕后是如何工作的(除了它做了两遍布局)。有没有办法手动让它做布局通过,即现在?因为它不是一个活动,所以我认为很多正常的背景事情都不会像我想要的那样发生。

4

2 回答 2

10

动态壁纸经过专门设计,不使用标准 UI 小部件。但是,无论如何都可以使用它们。您必须先在视图上调用 measure(),然后再调用 layout(),从而强制自己传递布局。您可以在我的演示文稿中找到更多信息。

于 2011-02-15T07:53:21.817 回答
3

这是在动态壁纸中布局和显示的视图组、按钮和图像视图的示例。如果将 Window 类型设置为 0,您还可以解决空窗口令牌错误并直接通过 WindowManager 添加视图。您必须捕获它抛出的异常,结果有些不稳定,但它在大多数情况下都有效。

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

            }

    }
于 2012-11-15T20:17:07.837 回答