java - ejecutar - Mostrar GIF animado
ejecutar gif en java (29)
@PointerNull dio una buena solución, pero no es perfecta. No funciona en algunos dispositivos con archivos grandes y muestra animaciones GIF con buggy con marcos delta en la versión pre ICS. Encontré la solución sin estos errores. Es una biblioteca con decodificación nativa para https://github.com/koral--/android-gif-drawable : https://github.com/koral--/android-gif-drawable .
Quiero mostrar imágenes GIF animadas en mi aplicación. Como descubrí la manera difícil, Android no es compatible con GIF animado de forma nativa.
Sin embargo, puede mostrar animaciones usando AnimationDrawable :
Desarrollar> Guías> Imágenes y gráficos> Resumen de dibujos
El ejemplo utiliza la animación guardada como marcos en los recursos de la aplicación, pero lo que necesito es mostrar el gif animado directamente.
Mi plan es dividir el GIF animado en cuadros y agregar cada cuadro como dibujable a AnimationDrawable.
¿Alguien sabe cómo extraer marcos de GIF animados y convertir cada uno de ellos en Drawable ?
Algo que hice para mostrar gifs en aplicaciones. Extendí ImageView para que la gente pueda usar sus atributos libremente. Puede mostrar gifs de url o del directorio de activos. La biblioteca también facilita la extensión de las clases para heredarla y extenderla para que admita 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
Ejemplo de uso:
Desde 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) {
}
});
Configurando el gif programáticamente:
mGifView.setGifResource("asset:gif1");
Algunas reflexiones sobre el ejemplo de BitmapDecode ... Básicamente, utiliza la antigua clase de películas pero sin rasgos distintivos de android.graphics. En las versiones de API recientes, debe desactivar la aceleración de hardware, como se describe aquí . De lo contrario, fue segregarme.
<activity
android:hardwareAccelerated="false"
android:name="foo.GifActivity"
android:label="The state of computer animation 2014">
</activity>
Aquí está el ejemplo de BitmapDecode abreviado con solo la parte GIF. Tienes que hacer tu propio Widget (Ver) y dibujarlo por ti mismo. No es tan poderoso 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();
}
}
}
}
En este excelente tutorial se pueden encontrar otros 2 métodos, uno con ImageView y otro con WebView. El método ImageView utiliza la licencia de android-gifview licencia Apache de Google Code.
Android realmente puede decodificar y mostrar GIF animados, usando la clase android.graphics.Movie.
Esto no está demasiado documentado, pero está en la referencia del SDK . Además, se usa en ejemplos en ApiDemos en el ejemplo de BitmapDecode con alguna bandera animada.
Creo que la mejor biblioteca para manejar archivos gif es https://github.com/koral--/android-gif-drawable
Lo usé y tengo éxito y esta biblioteca está dedicada a GIF''S; pero donde, como picasso y glide, son marcos de imágenes de propósito general ; Así que creo que los desarrolladores de esta biblioteca se han concentrado por completo en archivos gif.
En primer lugar, el navegador de Android debe soportar GIF animados. Si no es así, entonces es un error! Echa un vistazo a los rastreadores de problemas.
Si está mostrando estos GIF animados fuera de un navegador, podría ser una historia diferente. Para hacer lo que estás pidiendo se requeriría una biblioteca externa que admita la decodificación de GIF animados.
El primer punto de contacto sería mirar la API de Java2D o JAI (Java Advanced Imaging), aunque me sorprendería mucho si Android Dalvik admitiera esas bibliotecas en su aplicación.
Encontré una manera muy fácil, con un ejemplo de trabajo agradable y simple aquí.
Antes de ponerlo en funcionamiento, hay algunas cosas que hacer en el código.
EN EL SIGUIENTE
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceStated);
setContentView(new MYGIFView());
}
}
solo reemplaza
setContentView(new MYGIFView());
en
setContentView(new MYGIFView(this));
Y EN
public GIFView(Context context) {
super(context);
Proporcione su propio archivo de animación gif
is = context.getResources().openRawResource(R.drawable.earth);
movie = Movie.decodeStream(is);
}
SUSTITUYA LA PRIMERA LINEA EN
public MYGIFView(Context context) {
Según el nombre de la clase ...
Después de hacer estos pequeños cambios, debería funcionar como para mí ...
espero que esto ayude
Formas de mostrar GIF animado en Android:
- Clase de pelicula Como se mencionó anteriormente, es bastante buggy.
- WebView. Es muy simple de usar y por lo general funciona. Pero a veces comienza a comportarse mal, y siempre está en algunos dispositivos oscuros que no tiene. Además, no puede usar varias instancias en ningún tipo de vistas de lista, porque hace cosas a su memoria. Aún así, podría considerarlo como un enfoque primario.
- Código personalizado para decodificar gifs en mapas de bits y mostrarlos como Drawable o ImageView. Mencionaré dos bibliotecas:
https://github.com/koral--/android-gif-drawable - el decodificador se implementa en C, por lo que es muy eficiente.
https://code.google.com/p/giffiledecoder : el decodificador se implementa en Java, por lo que es más fácil trabajar con él. Aún razonablemente eficiente, incluso con archivos grandes.
También encontrarás muchas bibliotecas basadas en la clase GifDecoder. También es un decodificador basado en Java, pero funciona al cargar el archivo completo en la memoria, por lo que solo es aplicable a archivos pequeños.
Hay dos opciones para cargar gifs animados en nuestras aplicaciones de Android
1) Usando docs para cargar el gif en un 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) Usando un html para cargar el gif en un WebView
Crea el html con la dirección al 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:
Cargue este 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");
Heres es un ejemplo completo de estas dos opciones .
He tenido éxito con la solución propuesta en este artículo , una clase llamada GifMovieView
, que presenta una View
que luego se puede mostrar o agregar a un ViewGroup
específico. Vea los otros métodos presentados 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 de usar la Clase de Movie
Android "sombreada"). A continuación, estará mejor configurando el fondo a un color sólido dentro de su GIF animado.
La manera fácil de mostrar GIF animados directamente desde la URL al diseño de su aplicación es usar la clase WebView.
Paso 1: En tu maquetación XML
<WebView
android:id="@+id/webView"
android:layout_width="50dp"
android:layout_height="50dp"
/>
Paso 2: En tu actividad
WebView wb;
wb = (WebView) findViewById(R.id.webView);
wb.loadUrl("https://.......);
Paso 3: En tu Manifest.XML haz permiso de internet
<uses-permission android:name="android.permission.INTERNET" />
Paso 4: En caso de que quieras hacer que tu fondo GIF sea transparente y que GIF se ajuste a tu diseño
wb.setBackgroundColor(Color.TRANSPARENT);
wb.getSettings().setLoadWithOverviewMode(true);
wb.getSettings().setUseWideViewPort(true);
Manera más fácil - Se puede considerar el siguiente código
Podemos tomar ventaja de Imageview setImageResource, refiérase al siguiente código para obtener el mismo.
El siguiente código se puede usar para mostrar la imagen como GIF en caso de que tenga la imagen dividida múltiple de GIF. Simplemente divida el gif en png individual desde una herramienta en línea y ponga la imagen en el dibujo como en el siguiente orden
image_1.png, image_2.png, etc.
Tener el controlador para cambiar la imagen dinámicamente.
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);
//
}
});
}
Me fue muy difícil tener un gif animado trabajando en Android. Solo tuve dos siguientes trabajando:
- WebView
- Ion
WebView funciona bien y es muy fácil, pero el problema es que hace que la vista se vuelva más lenta y que la aplicación no responda por un segundo. A mi no me gusto eso. Así que he intentado diferentes enfoques (NO TRABAJÓ):
- ImageViewEx está en desuso!
- picasso no cargó gif animado
- android-gif-drawable se ve muy bien, pero causó algunos problemas de NDK alámbricos en mi proyecto. Esto causó que mi biblioteca NDK local dejara de funcionar y no pude arreglarlo
Tuve algunos de ida y vuelta con Ion
; Finalmente, lo tengo funcionando, y es muy rápido :-)
Ion.with(imgView)
.error(R.drawable.default_image)
.animateGif(AnimateGifMode.ANIMATE)
.load("file:///android_asset/animated.gif");
Póngalo en una vista web, tiene que ser capaz de mostrarlo correctamente, ya que el navegador predeterminado admite archivos gif. (Froyo +, si no me equivoco)
Prueba esto, debajo del archivo de visualización de código gif en la barra de progreso
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 dibujable)
Aquí pongo black_gif.gif (en la carpeta dibujable), puedes poner tu 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);
}
}
Puede usar la biblioteca GifAnimationDrawable que se encuentra en este enlace, https://github.com/Hipmob/gifanimateddrawable , y que convierte cualquier gif a AnimationDrawable. Disfrutar :)
Resolví el problema dividiendo las animaciones GIF en marcos antes de guardarlo en el teléfono, por lo que no tendría que lidiar con él en Android.
Luego descargo todos los marcos en el teléfono, creo Drawable desde él y luego creo AnimationDrawable - muy similar al ejemplo de mi pregunta
Resolví esto dividiendo gif en marcos y usé animación estándar de Android
Similar a lo que dijo @Leonti, pero con un poco más de profundidad:
Lo que hice para resolver el mismo problema fue abrir GIMP, ocultar todas las capas excepto una, exportarla como su propia imagen y luego ocultar esa capa y mostrar la siguiente, etc., hasta que tuviera archivos de recursos individuales para cada una . Entonces podría usarlos como marcos en el archivo XML AnimationDrawable.
Solo quería agregar que la clase de Movie ahora está en desuso.
Esta clase fue desaprobada en el nivel de API P.
Se recomienda utilizar este
Dibujable para dibujar imágenes animadas (como GIF).
Use ImageViewEx , una biblioteca que hace que usar un gif sea tan fácil como usar un ImageView
.
Utilizar fresco Aquí está cómo hacerlo:
http://frescolib.org/docs/animations.html
Aquí está el repo con la muestra:
https://github.com/facebook/fresco/tree/master/samples/animation
¡Cuidado con el fresco no admite contenido de envoltura!
también poner (main / asset / htmls / name.gif) [con este html ajustar al tamaño]
<html style="margin: 0;">
<body style="margin: 0;">
<img src="name.gif" style="width: 100%; height: 100%" />
</body>
</html>
declare en su Xml por ejemplo como este (main / res / layout / name.xml): [usted define 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 ponga el siguiente código dentro 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 quieres cargar dinámicamente tienes que cargar la vista web con 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 cargar gif con imágenes estáticas para obtener más información visite https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html
Eso es todo, espero que ayudes.
Glide
Image Loader Library 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.
Lo que Glide tiene pero Picasso no.
La capacidad de cargar animaciones GIF en un simple ImageView podría ser la característica más interesante de Glide. Y sí, no puedes hacer eso con Picasso. Algunos enlaces importantes-
Glide 4.6
1. cargar gif
GlideApp.with(context)
.load(R.raw.gif) // or url
.into(imageview);
2. Para obtener 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);
}
});
ACTUALIZAR:
Utilice deslizamiento:
dependencies {
compile ''com.github.bumptech.glide:glide:4.0.0''
}
uso:
Glide.with(context).load(GIF_URI).into(new GlideDrawableImageViewTarget(IMAGE_VIEW));
ver docs
Solo para la API de Android (Android Pie) 28 y +
utilizar 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 de Drawable y creado por ImageDecoder.decodeDrawable
ImageDecoder.decodeDrawable
que requería la instancia de ImageDecoder.Source
creada por ImageDecoder.createSource
.
ImageDecoder.createSource
solo puede tomar origen como nombre, ByteBuffer, File, resourceId, URI, ContentResolver para crear un objeto de origen y lo 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 admite cambio de tamaño, marco y manipulación de color
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());
}
}
}
}