当前位置: 代码迷 >> Android >> 使用android自带的动画片机制很卡时可以考虑使用SurfaceView来实现动画
  详细解决方案

使用android自带的动画片机制很卡时可以考虑使用SurfaceView来实现动画

热度:47   发布时间:2016-04-28 05:35:12.0
使用android自带的动画机制很卡时可以考虑使用SurfaceView来实现动画
如果当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);
  相关解决方案