Использование ресурсов Layout в LiveWallpaper на Android - PullRequest
5 голосов
/ 14 ноября 2010

Когда вы создаете LiveWallpaper в Android 2.2+, вы получаете холст (или любой другой 3D-эквивалент) для рисования.Я хотел бы нарисовать некоторые элементы, используя встроенные инструменты Android UI, а не создавать все с нуля, используя команды canvas или загрузку предварительно отрисованного растрового изображения 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 (), но дочерние элементы имеют нулевой размер (0x0)).Согласно сообщению Ромена Гая в 2008 году пост разработчика Android .Вы должны дождаться прохождения макета или принудительно выполнить макет самостоятельно.Проблема заключается в том, как я могу ждать проход макета из механизма обоев для LinearLayout, который не присоединен к корневой группе представлений?И как я могу вручную разметить каждый дочерний элемент, если разметка требует, чтобы вы установили левый, верхний, правый, нижний, когда я не знаю, какими они должны быть.

Я пытался вызвать forceLayout для дочерних элементов, нопохоже, это тоже не поможет.Я не уверен, как фреймворк работает за кулисами (кроме того, что он делает двухпроходный макет).Есть ли способ сделать это вручную, то есть прямо сейчас?Поскольку это не «Действие», я не думаю, что многие обычные фоновые события происходят именно так, как мне хотелось бы.

Ответы [ 2 ]

9 голосов
/ 15 февраля 2011

Живые обои были специально разработаны, чтобы НЕ использовать стандартные виджеты пользовательского интерфейса.Однако их можно использовать в любом случае.Вы должны будете принудительно передать макет, сначала вызвав measure () в представлении, затем layout ().Вы можете найти больше информации в моей презентации .

3 голосов
/ 16 ноября 2012

Вот пример группы представлений, кнопок и изображений, выложенных и отображенных в живых обоях.Вы также можете обойти ошибку маркера нулевого окна и добавлять представления непосредственно через WindowManager, если вы установили тип окна на 0. Вы должны отловить исключение, которое оно выдает, и результаты несколько ошибочны, но это работает по большей части.*

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

            }

    }
...