我想在应用程序中显示GIF动画图像。正如我所发现的那样,Android本身并不支持GIF动画。
但是,它可以使用AnimationDrawable显示动画:
该示例使用在应用程序资源中另存为帧的动画,但是我需要直接显示动画gif。
我的计划是将动画GIF分解为帧,并将每个帧作为可绘制对象添加到AnimationDrawable中。
有谁知道如何从GIF动画中提取帧并将其转换为Drawable?
我想在应用程序中显示GIF动画图像。正如我所发现的那样,Android本身并不支持GIF动画。
但是,它可以使用AnimationDrawable显示动画:
该示例使用在应用程序资源中另存为帧的动画,但是我需要直接显示动画gif。
我的计划是将动画GIF分解为帧,并将每个帧作为可绘制对象添加到AnimationDrawable中。
有谁知道如何从GIF动画中提取帧并将其转换为Drawable?
Answers:
Android实际上可以使用android.graphics.Movie类解码并显示动画GIF。
没有太多文档记录,但是在SDK Reference中。此外,它在BitmapDecode示例的ApiDemos的Samples中使用了一些动画标记。
setLayerType(LAYER_TYPE_SOFTWARE)
在视图上。但是它仍然仅适用于某些gif和某些设备。
Paint p = new Paint(); p.setAntiAlias(true); setLayerType(LAYER_TYPE_SOFTWARE, p);
工作了!
更新:
使用滑行:
dependencies {
implementation 'com.github.bumptech.glide:glide:4.0.0'
}
用法:
Glide.with(context).load(GIF_URI).into(new GlideDrawableImageViewTarget(IMAGE_VIEW));
也放(main / assets / htmls / name.gif)[用这个html调整大小]
<html style="margin: 0;">
<body style="margin: 0;">
<img src="name.gif" style="width: 100%; height: 100%" />
</body>
</html>
在您的Xml中声明这样的示例(main / res / layout / name.xml):[例如,您定义大小]
<WebView
android:layout_width="70dp"
android:layout_height="70dp"
android:id="@+id/webView"
android:layout_gravity="center_horizontal" />
在您的活动中,将下一个代码放在onCreate内
web = (WebView) findViewById(R.id.webView);
web.setBackgroundColor(Color.TRANSPARENT); //for gif without background
web.loadUrl("file:///android_asset/htmls/name.html");
如果要动态加载,则必须使用数据加载Webview:
// 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);
建议:最好将gif与静态图片一起加载以获取更多信息,请检查https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html
就是这样,希望您能对您有所帮助。
我通过将gif动画拆分为帧来解决该问题,然后再将其保存到手机中,因此无需在Android中处理它。
然后我将每个帧下载到手机上,从中创建Drawable,然后创建AnimationDrawable-与我的问题中的示例非常相似
我找到了一种非常简单的方法,这里有一个简单易用的示例
在开始工作之前,代码中需要做一些改动
在下面的
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceStated);
setContentView(new MYGIFView());
}
}
只需更换
setContentView(new MYGIFView());
在
setContentView(new MYGIFView(this));
和在
public GIFView(Context context) {
super(context);
提供自己的gif动画文件
is = context.getResources().openRawResource(R.drawable.earth);
movie = Movie.decodeStream(is);
}
替换第一行
public MYGIFView(Context context) {
根据班级的名字...
完成这些小的更改后,它应该对我来说...
希望这个帮助
在Android上显示动画GIF的方法:
https://github.com/koral--/android-gif-drawable-解码器以C语言实现,因此非常高效。
https://code.google.com/p/giffiledecoder-解码器是用Java实现的,因此使用起来更容易。即使有大文件,仍然相当有效。
您还会发现许多基于GifDecoder类的库。这也是基于Java的解码器,但是它通过将整个文件加载到内存中来工作,因此它仅适用于小文件。
我很难让动画gif在Android中工作。我只有以下两个工作:
WebView可以正常工作并且很容易,但是问题在于它使视图加载速度变慢,并且应用程序可能在一秒钟左右就没有响应。我不喜欢那样 所以我尝试了不同的方法(不工作):
我有一些来回交流Ion
; 最后,我可以正常使用了,而且速度非常快:-)
Ion.with(imgView)
.error(R.drawable.default_image)
.animateGif(AnimateGifMode.ANIMATE)
.load("file:///android_asset/animated.gif");
滑行4.6
1.加载gif
GlideApp.with(context)
.load(R.raw.gif) // or url
.into(imageview);
2.获取文件对象
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);
}
});
Glide
Google推荐的Android图像加载程序库。
滑翔机拥有什么,但毕加索却没有
将GIF动画加载到简单ImageView的功能可能是Glide最有趣的功能。是的,您无法使用毕加索做到这一点。 一些重要的链接-
使用ImageViewEx,这是一个使使用gif像使用gif一样容易的库ImageView
。
试试看,下面的代码在进度栏中显示gif文件
loading_activity.xml(在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(在可绘制文件夹中)
我在这里放了black_gif.gif(在可绘制文件夹中),你可以在这里放自己的gif
<?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(位于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);
}
}
关于BitmapDecode示例的一些想法...基本上,它使用了来自android.graphics 的古老而又毫无特色的Movie类。在最新的API版本上,您需要关闭硬件加速,如此处所述。否则对我来说是断断续续的。
<activity
android:hardwareAccelerated="false"
android:name="foo.GifActivity"
android:label="The state of computer animation 2014">
</activity>
这是仅使用GIF部分简化的BitmapDecode示例。您必须制作自己的小部件(视图)并自己绘制。不如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种方法,一种是ImageView,另一种是WebView 。ImageView方法使用来自Google Code 的Apache许可的android-gifview。
@PointerNull提供了很好的解决方案,但这并不完美。它在某些带有大文件的设备上不起作用,并且在ICS之前的版本上显示带有增量帧的错误的Gif动画。我找到了没有此错误的解决方案。它是具有对drawable的本地解码的库:koral的android-gif-drawable。
由于默认的浏览器支持gif文件,因此必须将其放入WebView中才能正确显示。(Froyo +,如果我没记错的话)
有两种方法可以将动画gif加载到我们的Android应用中
1)使用Glide将gif加载到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)使用html将gif加载到 WebView
使用.gif文件的地址创建html:
<html style="margin: 0;">
<body style="margin: 0;">
<img src="https://..../myimage.gif" style="width: 100%; height: 100%" />
</body>
</html>
将此文件存储到资产目录中:
将此html加载到应用程序的WebView中:
WebView webView = (WebView)findViewById(R.id.webView);
webView = (WebView) findViewById(R.id.webView);
webView.loadUrl("file:///android_asset/html/webpage_gif.html");
// 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()
XML代码,添加一个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
是Drawable的子级,由 ImageDecoder.decodeDrawable
ImageDecoder.decodeDrawable
这进一步需要由ImageDecoder.Source
创建的实例ImageDecoder.createSource
。
ImageDecoder.createSource
只能使用source作为名称,ByteBuffer,File,resourceId,URI,ContentResolver来创建源对象,并使用它来创建AnimatedImageDrawable
为Drawable
(多态调用)
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)
注意:您也可以Bitmap
使用ImageDecoder#decodeBitmap创建。
输出:
使用壁画。方法如下:
http://frescolib.org/docs/animations.html
这是带有示例的仓库:
https://github.com/facebook/fresco/tree/master/samples/animation
当心壁画不支持包装内容!
在src文件夹下创建一个名为“ Utils”的程序包,并创建一个名为“ GifImageView”的类
public class GifImageView extends View {
private InputStream mInputStream;
private Movie mMovie;
private int mWidth, mHeight;
private long mStart;
private Context mContext;
public GifImageView(Context context) {
super(context);
this.mContext = context;
}
public GifImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GifImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
if (attrs.getAttributeName(1).equals("background")) {
int id = Integer.parseInt(attrs.getAttributeValue(1).substring(1));
setGifImageResource(id);
}
}
private void init() {
setFocusable(true);
mMovie = Movie.decodeStream(mInputStream);
mWidth = mMovie.width();
mHeight = mMovie.height();
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
long now = SystemClock.uptimeMillis();
if (mStart == 0) {
mStart = now;
}
if (mMovie != null) {
int duration = mMovie.duration();
if (duration == 0) {
duration = 1000;
}
int relTime = (int) ((now - mStart) % duration);
mMovie.setTime(relTime);
mMovie.draw(canvas, 0, 0);
invalidate();
}
}
public void setGifImageResource(int id) {
mInputStream = mContext.getResources().openRawResource(id);
init();
}
public void setGifImageUri(Uri uri) {
try {
mInputStream = mContext.getContentResolver().openInputStream(uri);
init();
} catch (FileNotFoundException e) {
Log.e("GIfImageView", "File not found");
}
}
}
现在在MainActivity文件中定义GifImageView:src / activity / MainActivity.class
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GifImageView gifImageView = (GifImageView) findViewById(R.id.GifImageView);
gifImageView.setGifImageResource(R.drawable.smartphone_drib);
}
}
现在,UI零件文件:res / layout / activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:gravity="center"
android:background="#111E39"
tools:context=".Activity.MainActivity">
<com.android.animatedgif.Utils.GifImageView
android:id="@+id/GifImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
资源代码:Android示例
首先,Android浏览器应支持动画GIF。如果不是,那就是一个错误!看看问题追踪器。
如果要在浏览器外部显示这些动画GIF,则可能是另一回事。要执行您要的操作,将需要支持动画GIF解码的外部库。
首先要看的是Java2D或JAI(Java高级映像)API,但如果Android Dalvik支持您的App中的那些库,我会感到非常惊讶。
类似于@Leonti所说的,但更深一些:
为了解决相同的问题,我要做的是打开GIMP,隐藏除第一层以外的所有层,将其导出为自己的图像,然后隐藏该层并取消隐藏下一层,依此类推,直到每个层都有单独的资源文件为止。然后,我可以将它们用作AnimationDrawable XML文件中的框架。
我通过在框架中分割gif并使用标准的android动画解决了这个问题
我为在应用程序中显示gif所做的事情。我扩展了ImageView,以便人们可以自由使用它的属性。它可以显示url或资产目录中的gif。该库还使扩展类从其继承和扩展以支持不同的方法来初始化gif变得容易。
https://github.com/Gavras/GIFView
github页面上有一些指南。
它也发布在Android Arsenal上:
https://android-arsenal.com/details/1/4947
使用示例:
从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" />
在活动中:
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) {
}
});
以编程方式设置gif:
mGifView.setGifResource("asset:gif1");
最简单的方法-可以考虑以下代码
我们可以利用Imageview setImageResource,同样参考下面的代码。
如果您有多个gif分割图像,则以下代码可用于显示类似gif的图像。只需通过在线工具将gif分割成单独的png,然后将图像放入可绘制对象中,如下所示
image_1.png,image_2.png等
让处理程序动态更改图像。
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);
//
}
});
}
直接从URL到应用布局显示动画GIF的简单方法是使用WebView类。
步骤1: 在布局XML中
<WebView
android:id="@+id/webView"
android:layout_width="50dp"
android:layout_height="50dp"
/>
步骤2:在您的活动中
WebView wb;
wb = (WebView) findViewById(R.id.webView);
wb.loadUrl("https://.......);
步骤3:在您的Manifest.XML中,获得Internet权限
<uses-permission android:name="android.permission.INTERNET" />
步骤4:如果您想使GIF背景透明,并使GIF适合您的布局
wb.setBackgroundColor(Color.TRANSPARENT);
wb.getSettings().setLoadWithOverviewMode(true);
wb.getSettings().setUseWideViewPort(true);
您可以使用在此链接中找到的GifAnimationDrawable库-https: //github.com/Hipmob/gifanimateddrawable,它将任何gif转换为AnimationDrawable。请享用 :)
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());
}
}
}
}