如果当View tree很复杂,结构很深的时候, 使用动画的时候会发现即使开了硬件加速还是有些卡,这是因为android系统自带的动画是在UI线程来处理的, 而且每次需要重绘整个View tree,虽然你可以指定重新绘制的区域,不过这样比较麻烦,
SurfaceView中View的绘制不是在UI线程中,所以可以避免上面的问题。我们只要做到SurfaceView背景能够透明就行了。在需要的地方盖一层SurfaceView, 做动画时显示出来。下面是示例代码。
package com.example.myapp;import android.content.Context;import android.content.res.Resources;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.PixelFormat;import android.graphics.Region;import android.util.AttributeSet;import android.view.Surface.OutOfResourcesException;import android.view.SurfaceHolder;import android.view.SurfaceView;public class ZenClockSurface extends SurfaceView implements SurfaceHolder.Callback { private DrawClock drawClock; public ZenClockSurface(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); getHolder().addCallback(this); } public ZenClockSurface(Context context) { super(context); getHolder().addCallback(this); } public ZenClockSurface(Context context, AttributeSet attrs) { super(context, attrs); getHolder().addCallback(this); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { drawClock = new DrawClock(getHolder(), getResources()); drawClock.setRunning(true); drawClock.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { boolean retry = true; drawClock.setRunning(false); while (retry) { try { drawClock.join(); retry = false; } catch (InterruptedException e) { } } } class DrawClock extends Thread { private boolean runFlag = false; private SurfaceHolder surfaceHolder; private Bitmap picture; private Matrix matrix; private Paint painter; public DrawClock(SurfaceHolder surfaceHolder, Resources resources) { this.surfaceHolder = surfaceHolder; picture = BitmapFactory.decodeResource(resources, R.drawable.ic_launcher); matrix = new Matrix(); this.painter = new Paint(); this.painter.setStyle(Paint.Style.FILL); this.painter.setAntiAlias(true); this.painter.setFilterBitmap(true); } public void setRunning(boolean run) { runFlag = run; } @Override public void run() { Canvas canvas; while (runFlag) { matrix.preRotate(1.0f, picture.getWidth() / 2, picture.getHeight() / 2); canvas = null; try { canvas = surfaceHolder.lockCanvas(null); synchronized (surfaceHolder) { float[] f = new float[9]; matrix.getValues(f); float y = f[Matrix.MTRANS_Y]; matrix.postTranslate(0, 10); canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR); canvas.drawBitmap(picture, matrix, this.painter); float[] f1 = new float[9]; matrix.getValues(f1); float y1 = f1[Matrix.MTRANS_Y]; if (y1 >= 800) { matrix.setTranslate(0, 0); } } } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (canvas != null) { surfaceHolder.unlockCanvasAndPost(canvas); } } } } }}
调用的activity
package com.example.myapp;import android.app.Activity;import android.graphics.PixelFormat;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.View;import android.view.ViewGroup;import android.webkit.WebView;import android.widget.LinearLayout;import android.widget.ScrollView;public class MyActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ZenClockSurface sfvTrack = (ZenClockSurface)findViewById(R.id.zenClockSurface1); sfvTrack.setZOrderOnTop(true); // necessary SurfaceHolder sfhTrack = sfvTrack.getHolder(); sfhTrack.setFormat(PixelFormat.TRANSLUCENT); WebView webview = (WebView) findViewById(R.id.webview); webview.getSettings().setJavaScriptEnabled(true); webview.loadUrl("http://m.vip.com"); }}
布局。
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/RelativeLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/red" android:orientation="vertical" > <WebView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/webview"></WebView> <com.example.myapp.ZenClockSurface android:id="@+id/zenClockSurface1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerHorizontal="true" android:layout_centerVertical="true"/></RelativeLayout>
使SurfaceView透明是下面这几句
ZenClockSurface sfvTrack = (ZenClockSurface)findViewById(R.id.zenClockSurface1);
sfvTrack.setZOrderOnTop(true); // necessary
SurfaceHolder sfhTrack = sfvTrack.getHolder();
sfhTrack.setFormat(PixelFormat.TRANSLUCENT);
这句是清屏。 canvas.drawColor(0,android.graphics.PorterDuff.Mode.CLEAR);