Mostrar GIF animado
-
01-10-2019 - |
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 ?
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 ??p>
He encontrado una manera muy fácil, con un bonito y el ejemplo de trabajo simple aquí
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:
- WebView
- 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ó):
- ImageViewEx es obsoleto!
- Picasso no se cargó de animación GIF
- 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. Algunos enlaces importantes -
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:
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");
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
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());
}
}
}
}