Pregunta

Quiero mostrar imágenes GIF animados en mi aplicacion. Como ya he encontrado la manera dura Android no admite GIF animado de forma nativa.

Sin embargo, puede mostrar animaciones utilizando AnimationDrawable :

Desarrollar> Guías> Imágenes y Gráficos> dibujables general

La animación ejemplo utiliza guardado como fotogramas de recursos de la aplicación, pero lo que necesito es para mostrar GIF animados directamente.

Mi plan es romper GIF animado a los marcos y añadir cada fotograma como dibujable a AnimationDrawable.

¿Alguien sabe cómo extraer fotogramas de GIF animados y convertir cada uno de ellos en Disponibles ?

¿Fue útil?

Solución

Android en realidad puede decodificar y mostrar archivos GIF animados, usando la clase android.graphics.Movie.

Esto no es demasiado documentada, pero se encuentra en SDK Referencia . Por otra parte, se utiliza en Las muestras en ApiDemos en ejemplo BitmapDecode con alguna bandera animados.

Otros consejos

ACTUALIZACIÓN:

El uso de planeo:

dependencies {
  implementation 'com.github.bumptech.glide:glide:4.0.0'
}

uso:

Glide.with(context).load(GIF_URI).into(new GlideDrawableImageViewTarget(IMAGE_VIEW));

docs

también poner (activos / main / htmls / name.gif) [html con este ajuste al tamaño]

<html style="margin: 0;">
<body style="margin: 0;">
<img src="name.gif" style="width: 100%; height: 100%" />
</body>
</html>

declarar en el XML, por ejemplo, como esto (principal / res / layout / nombre.xml): [definir el tamaño, por ejemplo]

<WebView
android:layout_width="70dp"
android:layout_height="70dp"
android:id="@+id/webView"
android:layout_gravity="center_horizontal" />

en su actividad pone el código siguiente en el interior de onCreate

web = (WebView) findViewById(R.id.webView); 
web.setBackgroundColor(Color.TRANSPARENT); //for gif without background
web.loadUrl("file:///android_asset/htmls/name.html");

si desea cargar dinámicamente tiene que cargar la vista web con los datos:

// or "[path]/name.gif" (e.g: file:///android_asset/name.gif for resources in asset folder), and in loadDataWithBaseURL(), you don't need to set base URL, on the other hand, it's similar to loadData() method.
String gifName = "name.gif";
String yourData = "<html style=\"margin: 0;\">\n" +
        "    <body style=\"margin: 0;\">\n" +
        "    <img src=" + gifName + " style=\"width: 100%; height: 100%\" />\n" +
        "    </body>\n" +
        "    </html>";
// Important to add this attribute to webView to get resource from outside.
webView.getSettings().setAllowFileAccess(true);

// Notice: should use loadDataWithBaseURL. BaseUrl could be the base url such as the path to asset folder, or SDCard or any other path, where your images or the other media resides related to your html
webView.loadDataWithBaseURL("file:///android_asset/", yourData, "text/html", "utf-8", null);
// Or if you want to load image from SD card or where else, here is the idea.
String base = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
webView.loadDataWithBaseURL(base + '/', yourData, "text/html", "utf-8", null);

sugerencia: es mejor gif carga con imágenes estáticas para obtener más información del cheque https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

Eso es todo, espero que les ayuda.

Me solucionó el problema mediante la división gif animaciones en tramas antes de guardarlo en el teléfono, así que no tendría que tratar con él en Android.

Luego descargar cada cuadro en el teléfono, crear Disponibles de ella y luego crear AnimationDrawable - muy similar al ejemplo de mi pregunta

He encontrado una manera muy fácil, con un bonito y el ejemplo de trabajo simple aquí

pantalla animada widget de

Antes de conseguir que funcione hay que hacer chages hacer en el código

En los siguientes

    @Override
    public void onCreate(Bundle savedInstanceState){    
        super.onCreate(savedInstanceStated);   
        setContentView(new MYGIFView());
    }    
}

basta con sustituir

setContentView(new MYGIFView());

en

setContentView(new MYGIFView(this));

Y EN

public GIFView(Context context) {
    super(context);

Proporcionar su propio archivo de animación GIF

    is = context.getResources().openRawResource(R.drawable.earth);
    movie = Movie.decodeStream(is);
}

Reemplazar la primera línea en

public MYGIFView(Context context) {

de acuerdo con el nombre de la clase ...

Una vez hecho esto pequeños cambios que debería funcionar en cuanto a mí ...

espero que esto ayuda

maneras de mostrar GIF animados en Android:

    clase
  • Película. Como se mencionó anteriormente, es bastante buggy.
  • WebView. Es muy simple de usar y general funciona. Pero a veces empieza a comportarse mal, y siempre es en algunos dispositivos oscuros que no tienen. Además, no se puede utilizar varias instancias en cualquier tipo de vistas de lista, ya que hace las cosas a su memoria. Aún así, es posible considerarlo como un enfoque primario.
  • El código personalizado para decodificar gifs en mapas de bits y mostrarlos como Disponibles o ImageView. Voy a mencionar dos bibliotecas:

https://github.com/koral--/android-gif-drawable - decodificador está implementado en C, por lo que es muy eficiente.

https://code.google.com/p/giffiledecoder - decodificador se implementa en Java, por lo que es más fácil trabajar con ellos. Siendo razonablemente eficiente, incluso con archivos de gran tamaño.

También encontrará muchas bibliotecas basadas en la clase GifDecoder. Eso también es un decodificador basado en Java, pero funciona cargando el archivo en la memoria, por lo que es aplicable a archivos pequeños.

Yo tenía un momento muy difícil para haber animado gif trabaja en Android. Sólo había dos siguientes de trabajo:

  1. WebView
  2. Ion

WebView funciona bien y realmente sencillo, pero el problema es que hace la vista cargas más lento y la aplicación sería responder durante un segundo o menos. A mi no me gusto eso. Así que he intentado diferentes enfoques (no funcionó):

  1. ImageViewEx es obsoleto!
  2. Picasso no se cargó de animación GIF
  3. android-gif-dibujable se ve muy bien, pero causó algunos problemas NDK cableadas en mi proyecto. Es la causa de mi biblioteca local NDK dejan de funcionar, y yo no era capaz de arreglarlo

Yo tenía un poco de un lado a otro con Ion; Por último, tengo que trabajar, y es muy rápido: -)

Ion.with(imgView)
  .error(R.drawable.default_image)
  .animateGif(AnimateGifMode.ANIMATE)
  .load("file:///android_asset/animated.gif");

Glide

Imagen cargador Biblioteca para Android, recomendado por Google.

  • Glide es bastante similar a Picasso, pero esto es mucho más rápido que Picasso.
  • Glide consume menos memoria que Picasso.

¿Qué tiene que Glide, pero no lo hace Picasso

Una capacidad de carga de animación GIF a un simple ImageView podría ser la característica más interesante de deslizamiento. Y sí, no se puede hacer eso con Picasso. introducir descripción de la imagen aquí Algunos enlaces importantes -

  1. https://github.com/bumptech/glide
  2. http://inthecheesefactory.com/blog/ conseguir-a-saber-glide recomendadas por google / es

ImageViewEx , una biblioteca que hace uso de un gif tan fácil como usar un ImageView.

Probar, abajo gif visualización del código en progressbar

loading_activity.xml (en la carpeta Layout)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff" >

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:indeterminate="true"
        android:indeterminateDrawable="@drawable/custom_loading"
        android:visibility="gone" />

</RelativeLayout>

custom_loading.xml (en la carpeta estirable)

Aquí pongo black_gif.gif (en la carpeta estirable), puede poner su propio gif aquí

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/black_gif"
    android:pivotX="50%"
    android:pivotY="50%" />

LoadingActivity.java (en la carpeta res)

public class LoadingActivity extends Activity {

    ProgressBar bar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_loading);
        bar = (ProgressBar) findViewById(R.id.progressBar);
        bar.setVisibility(View.VISIBLE);

    }

}

Nadie ha mencionado la Ion o biblioteca Glide . que funcionan muy bien.

Es más fácil de manejar en comparación con una vista Web.

he tenido éxito con la solución propuesta dentro de este artículo , una clase llamada GifMovieView, lo que hace un View que luego puede ser representada o añadido a una ViewGroup específico. Echa un vistazo a los otros métodos que se presentan en las partes 2 y 3 del artículo especificado.

El único inconveniente de este método es que el antialiasing en la película no es tan bueno (debe ser un efecto secundario del uso de la "sombra" Movie Android Clase). Usted es entonces mejor establecer el fondo a un color sólido dentro de su GIF animado.

Algunas reflexiones sobre el ejemplo BitmapDecode ... Básicamente se utiliza la antigua, sino más bien monótono clase de película de android.graphics. En las versiones recientes de API que necesita para desactivar la aceleración de hardware, como se describe aquí . Se violación de segmento para mí lo contrario.

<activity
            android:hardwareAccelerated="false"
            android:name="foo.GifActivity"
            android:label="The state of computer animation 2014">
</activity>

Aquí está el ejemplo BitmapDecode acortada con sólo la parte GIF. Usted tiene que hacer su propio Widget (Ver) y sacar por sí mismo. No es tan potente como un ImageView.

import android.app.Activity;
import android.content.Context;
import android.graphics.*;
import android.os.*;
import android.view.View;

public class GifActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new GifView(this));
    }

    static class GifView extends View {
        Movie movie;

        GifView(Context context) {
            super(context);
            movie = Movie.decodeStream(
                    context.getResources().openRawResource(
                            R.drawable.some_gif));
        }
        @Override
        protected void onDraw(Canvas canvas) {   
            if (movie != null) {
                movie.setTime(
                    (int) SystemClock.uptimeMillis() % movie.duration());
                movie.draw(canvas, 0, 0);
                invalidate();
            }
        }
    }
}

2 otros métodos, uno con ImageView otro con WebView se puede encontrar en este tutorial bien. El método utiliza el ImageView Apache licencia android-gifview de Google Code.

@PointerNull dio buena solución, pero no es perfecto. No funciona en algunos dispositivos con archivos de gran tamaño y mostrar la animación GIF con errores con marcos delta en versión pre ICS. He encontrado esta solución sin errores. Es biblioteca con decodificación nativa de DRAWABLE:. de Koral android-gif-dibujable

Glide 4.6

1. Para cargar gif

GlideApp.with(context)
            .load(R.raw.gif) // or url
            .into(imageview);

2. Para conseguir el objeto de archivo

GlideApp.with(context)
                .asGif()
                .load(R.raw.gif) //or url
                .into(new SimpleTarget<GifDrawable>() {
                    @Override
                    public void onResourceReady(@NonNull GifDrawable resource, @Nullable Transition<? super GifDrawable> transition) {

                        resource.start();
                      //resource.setLoopCount(1);
                        imageView.setImageDrawable(resource);
                    }
                });

ponerlo en una vista Web, tiene que ser capaz de visualizar correctamente, ya que los archivos de los soportes del navegador por defecto gif. (Froyo +, si no me equivoco)

Hay dos opciones para cargar gifs animados en nuestras aplicaciones de Android

1) Utilizando Glide para cargar el gif en una ImageView.

    String urlGif = "https://cdn.dribbble.com/users/263558/screenshots/1337078/dvsd.gif";
    //add Glide implementation into the build.gradle file.
    ImageView imageView = (ImageView)findViewById(R.id.imageView);
    Uri uri = Uri.parse(urlGif);
    Glide.with(getApplicationContext()).load(uri).into(imageView);

2) El uso de un html para cargar el gif en una WebView

Crea el html con la dirección en el archivo .gif:

<html style="margin: 0;">
<body style="margin: 0;">
<img src="https://..../myimage.gif" style="width: 100%; height: 100%" />
</body>
</html>

almacenar este archivo en el directorio de activos:

introducir descripción de la imagen aquí

La carga de este código HTML en la vista Web de su aplicación:

    WebView webView =  (WebView)findViewById(R.id.webView);
    webView = (WebView) findViewById(R.id.webView);
    webView.loadUrl("file:///android_asset/html/webpage_gif.html");

ejemplo completo de estas dos opciones: .

introducir descripción de la imagen aquí

Para única API androide (Pie Android) 28 y +

uso AnimatedImageDrawable como

// ImageView from layout
val ima : ImageView = findViewById(R.id.img_gif)
// create AnimatedDrawable 
val decodedAnimation = ImageDecoder.decodeDrawable(
        // create ImageDecoder.Source object
        ImageDecoder.createSource(resources, R.drawable.tenor))
// set the drawble as image source of ImageView
ima.setImageDrawable(decodedAnimation)
// play the animation
(decodedAnimation as? AnimatedImageDrawable)?.start()

código XML, añadir un ImageView

<ImageView
    android:id="@+id/img_gif"
    android:background="@drawable/ic_launcher_background" <!--Default background-->
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    android:layout_width="200dp"
    android:layout_height="200dp" />

AnimatedImageDrawable es un hijo del Disponibles y creado por ImageDecoder.decodeDrawable

ImageDecoder.decodeDrawable que requiere aún más la instancia de ImageDecoder.Source creado por ImageDecoder.createSource.

ImageDecoder.createSource sólo puede tener origen como un nombre, ByteBuffer, Archivo, resourceId, URI, ContentResolver para crear objeto de origen y la utiliza para crear AnimatedImageDrawable como Drawable (llamada polimórfica)

static ImageDecoder.Source  createSource(AssetManager assets, String fileName)
static ImageDecoder.Source  createSource(ByteBuffer buffer)
static ImageDecoder.Source  createSource(File file)
static ImageDecoder.Source  createSource(Resources res, int resId)
static ImageDecoder.Source  createSource(ContentResolver cr, Uri uri)

Nota: También puede crear Bitmap usando ImageDecoder # decodeBitmap .

Salida:

AnimatedDrawable también es compatible con el cambio de tamaño, el marco y la manipulación del color

Creo que la mejor biblioteca de archivos gif mango es éste: por Koral

utilizado y tengo éxito y esta biblioteca está dedicada a GIF'S; pero donde como el Picasso y deslizamiento son propósito general marco de la imagen; así que creo que los desarrolladores de esta biblioteca se han concentrado por completo en archivos gif

Uso Fresco. He aquí cómo hacerlo:

http://frescolib.org/docs/animations.html

Aquí está el repositorio con la muestra:

https://github.com/facebook/fresco/tree/master/ muestras / animación

Cuidado del fresco no soporta contenido de envoltura!

En primer lugar el navegador de Android debería apoyar GIF animados. Si no lo hace, entonces es un error! Echar un vistazo a los gestores de incidencias.

Si está mostrando estos archivos GIF animados fuera de un navegador que podría ser una historia diferente. Para hacer lo que estamos pidiendo que requeriría biblioteca externa que soporta la decodificación de archivos GIF animados.

El primer punto de contacto sería mirar Java2D o API JAI (Java Advanced Imaging), aunque yo estaría muy sorprendido si Android Dalvik apoyaría esas bibliotecas en su aplicación.

Al igual que lo que dijo @Leonti, pero con un poco más de profundidad:

Lo que hice para resolver el mismo problema fue abrir el GIMP, ocultar todas las capas excepto uno, exportarlo como su propia imagen, y luego ocultar esa capa y mostrar la siguiente, etc., hasta que tuve archivos de recursos individuales para cada uno. Entonces podría utilizarlos como cuadros en el archivo XML AnimationDrawable.

resuelvo esto gif división en marcos y uso estándar androide animación

Algo que hice para mostrar gifs de aplicaciones. Extendí ImageView que la gente pueda utilizar libremente sus atributos. Puede mostrar gifs de URL o desde el directorio de activos. La biblioteca también hace que sea fácil para extender las clases para heredar de ella y extenderlo a soportar diferentes métodos para inicializar el gif.

https://github.com/Gavras/GIFView

Hay una pequeña guía en la página de GitHub.

También fue publicado en Android Arsenal:

https://android-arsenal.com/details/1/4947

Uso ejemplo:

A partir de XML:

<com.whygraphics.gifview.gif.GIFView xmlns:gif_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/main_activity_gif_vie"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:scaleType="center"
        gif_view:gif_src="url:http://pop.h-cdn.co/assets/16/33/480x264/gallery-1471381857-gif-season-2.gif" />

En la actividad:

    GIFView mGifView = (GIFView) findViewById(R.id.main_activity_gif_vie);

    mGifView.setOnSettingGifListener(new GIFView.OnSettingGifListener() {
                @Override
                public void onSuccess(GIFView view, Exception e) {
                    Toast.makeText(MainActivity.this, "onSuccess()", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onFailure(GIFView view, Exception e) {

        }
});

Configuración de la programación gif:

mGifView.setGifResource("asset:gif1");

La manera más fácil - Se puede considerar el siguiente código

puede tomar ventaja de Imageview setImageResource, consulte a continuación el código de la misma.

El debajo de código se puede utilizar para mostrar la imagen como gif en caso si tiene la imagen de división múltiple de gif. Simplemente dividir el GIF en PNG individuo de una herramienta en línea y la imagen puesto en el dibujable como el siguiente orden

image_1.png, image_2.png, etc.

Tener el controlador para cambiar la imagen de forma dinámica.

int imagePosition = 1;
    Handler handler = new Handler();
        Runnable runnable = new Runnable() {
            public void run() {
                updateImage();
            }
        };




    public void updateImage() {

                appInstance.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        int resId = getResources().getIdentifier("image_" + imagePosition, "drawable", appInstance.getPackageName());
                        gifImageViewDummy.setImageResource(resId);
                        imagePosition++;
    //Consider you have 30 image for the anim
                        if (imagePosition == 30) {
//this make animation play only once
                            handler.removeCallbacks(runnable);

                        } else {
    //You can define your own time based on the animation
                            handler.postDelayed(runnable, 50);
                        }

//to make animation to continue use below code and remove above if else
// if (imagePosition == 30)
//imagePosition = 1;
// handler.postDelayed(runnable, 50);
// 
                    }
                });
              }

La forma más fácil de visualización animada GIF directamente de URL para su diseño de aplicación es el uso de la clase WebView.

Paso 1: En su diseño XML

<WebView
android:id="@+id/webView"
android:layout_width="50dp"
android:layout_height="50dp"
/>

Paso 2: En su actividad

WebView wb;
wb = (WebView) findViewById(R.id.webView);
wb.loadUrl("https://.......);

Paso 3: En su Manifest.xml permiso maquillaje de Internet

<uses-permission android:name="android.permission.INTERNET" />

Paso 4: En caso de que quiera hacer su fondo GIF transparente y hacer GIF ajuste a su diseño

wb.setBackgroundColor(Color.TRANSPARENT);
wb.getSettings().setLoadWithOverviewMode(true);
wb.getSettings().setUseWideViewPort(true);

Sólo quería añadir que la clase película ahora es obsoleto.

  

Esta clase está desfasada y en el nivel API p

Se recomienda utilizar este

AnimatedImageDrawable

  

Disponibles para la elaboración de imágenes animadas (como GIF).

Es posible usar la biblioteca GifAnimationDrawable que se encuentra en este enlace - https://github.com/Hipmob/gifanimateddrawable, y que convierten cualquier gif a AnimationDrawable. Disfrutar:)

public class Test extends GraphicsActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new SampleView(this));
  }

  private static class SampleView extends View {
    private Bitmap mBitmap;
    private Bitmap mBitmap2;
    private Bitmap mBitmap3;
    private Bitmap mBitmap4;
    private Drawable mDrawable;

    private Movie mMovie;
    private long mMovieStart;

    // Set to false to use decodeByteArray
    private static final boolean DECODE_STREAM = true;

    private static byte[] streamToBytes(InputStream is) {
      ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
      byte[] buffer = new byte[1024];
      int len;
      try {
        while ((len = is.read(buffer)) >= 0) {
          os.write(buffer, 0, len);
        }
      } catch (java.io.IOException e) {
      }
      return os.toByteArray();
    }

    public SampleView(Context context) {
      super(context);
      setFocusable(true);

      java.io.InputStream is;
      is = context.getResources().openRawResource(R.drawable.icon);

      BitmapFactory.Options opts = new BitmapFactory.Options();
      Bitmap bm;

      opts.inJustDecodeBounds = true;
      bm = BitmapFactory.decodeStream(is, null, opts);

      // now opts.outWidth and opts.outHeight are the dimension of the
      // bitmap, even though bm is null

      opts.inJustDecodeBounds = false; // this will request the bm
      opts.inSampleSize = 4; // scaled down by 4
      bm = BitmapFactory.decodeStream(is, null, opts);

      mBitmap = bm;

      // decode an image with transparency
      is = context.getResources().openRawResource(R.drawable.icon);
      mBitmap2 = BitmapFactory.decodeStream(is);

      // create a deep copy of it using getPixels() into different configs
      int w = mBitmap2.getWidth();
      int h = mBitmap2.getHeight();
      int[] pixels = new int[w * h];
      mBitmap2.getPixels(pixels, 0, w, 0, 0, w, h);
      mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h,
          Bitmap.Config.ARGB_8888);
      mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h,
          Bitmap.Config.ARGB_4444);

      mDrawable = context.getResources().getDrawable(R.drawable.icon);
      mDrawable.setBounds(150, 20, 300, 100);

      is = context.getResources().openRawResource(R.drawable.animated_gif);

      if (DECODE_STREAM) {
        mMovie = Movie.decodeStream(is);
      } else {
        byte[] array = streamToBytes(is);
        mMovie = Movie.decodeByteArray(array, 0, array.length);
      }
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawColor(0xFFCCCCCC);

      Paint p = new Paint();
      p.setAntiAlias(true);

      canvas.drawBitmap(mBitmap, 10, 10, null);
      canvas.drawBitmap(mBitmap2, 10, 170, null);
      canvas.drawBitmap(mBitmap3, 110, 170, null);
      canvas.drawBitmap(mBitmap4, 210, 170, null);

      mDrawable.draw(canvas);

      long now = android.os.SystemClock.uptimeMillis();
      if (mMovieStart == 0) { // first time
        mMovieStart = now;
      }
      if (mMovie != null) {
        int dur = mMovie.duration();
        if (dur == 0) {
          dur = 1000;
        }
        int relTime = (int) ((now - mMovieStart) % dur);
        mMovie.setTime(relTime);
        mMovie.draw(canvas, getWidth() - mMovie.width(), getHeight()
            - mMovie.height());
        invalidate();
      }
    }
  }
}

class GraphicsActivity extends Activity {
  // set to true to test Picture
  private static final boolean TEST_PICTURE = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public void setContentView(View view) {
    if (TEST_PICTURE) {
      ViewGroup vg = new PictureLayout(this);
      vg.addView(view);
      view = vg;
    }

    super.setContentView(view);
  }
}

class PictureLayout extends ViewGroup {
  private final Picture mPicture = new Picture();

  public PictureLayout(Context context) {
    super(context);
  }

  public PictureLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  public void addView(View child) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child);
  }

  @Override
  public void addView(View child, int index) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index);
  }

  @Override
  public void addView(View child, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, params);
  }

  @Override
  public void addView(View child, int index, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index, params);
  }

  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int count = getChildCount();

    int maxHeight = 0;
    int maxWidth = 0;

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
    }

    maxWidth += getPaddingLeft() + getPaddingRight();
    maxHeight += getPaddingTop() + getPaddingBottom();

    Drawable drawable = getBackground();
    if (drawable != null) {
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    }

    setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
        resolveSize(maxHeight, heightMeasureSpec));
  }

  private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
      float sy) {
    canvas.save();
    canvas.translate(x, y);
    canvas.clipRect(0, 0, w, h);
    canvas.scale(0.5f, 0.5f);
    canvas.scale(sx, sy, w, h);
    canvas.drawPicture(mPicture);
    canvas.restore();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
    mPicture.endRecording();

    int x = getWidth() / 2;
    int y = getHeight() / 2;

    if (false) {
      canvas.drawPicture(mPicture);
    } else {
      drawPict(canvas, 0, 0, x, y, 1, 1);
      drawPict(canvas, x, 0, x, y, -1, 1);
      drawPict(canvas, 0, y, x, y, 1, -1);
      drawPict(canvas, x, y, x, y, -1, -1);
    }
  }

  @Override
  public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    location[0] = getLeft();
    location[1] = getTop();
    dirty.set(0, 0, getWidth(), getHeight());
    return getParent();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = super.getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        child.layout(childLeft, childTop,
            childLeft + child.getMeasuredWidth(),
            childTop + child.getMeasuredHeight());

      }
    }
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top