Android自定义view--SurfaceView实现墨迹天气的风车效果



 Android自定义view--SurfaceView实现墨迹天气的风车效果


SurfaceView也是继承自View,它和我们以前接触到的View(Button、TextView等)最大的不同是,SurfaceView可以有一个单独的线程进行绘制,这个线程区别于UI线程(主线程),因此SurfaceView绘制并不占用主线程资源


    SurfaceView实现通常是自定义,继承SurfaceView并实现SurfaceHolder.Callback接口。使用SurfaceView,所有的绘图工作必须得在Surface 被创建之后才能开始,所以Callback 中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界。


实现SurfaceHolder.Callback接口需要重写的方法:

   //在surface的大小发生改变时激发
 (1)public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}

    //在创建时激发,一般在这里调用画图的线程。
 (2)public void surfaceCreated(SurfaceHolder holder){}

    //销毁时激发,一般在这里将画图的线程停止、释放。    

  (3)public void surfaceDestroyed(SurfaceHolder holder) {}

    

SurfaceHolder有几个重要方法:

// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
(1)、abstract Canvas lockCanvas();
// 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。
// 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。
(2)、abstract Canvas lockCanvas(Rect dirty);
// 结束锁定画图,并提交改变。

(3)、abstract void unlockCanvasAndPost(Canvas canvas);

//给SurfaceView当前的持有者一个回调对象。

(4)、abstract void addCallback(SurfaceHolder.Callback callback);

下面使用SurfaceView实现墨迹天气的风车效果:

  1. public class WindmillView extends SurfaceView implements  
  2.         SurfaceHolder.Callback, Runnable {  
  3.   
  4.     private SurfaceHolder holder;  
  5.   
  6.     private boolean isRunning = true;  
  7.   
  8.       
  9.   
  10.     /** 
  11.      * 屏幕的像素 
  12.      */  
  13.     private int screenWidth;  
  14.     private int screenHeiht;  
  15.   
  16.     private Bitmap windPoint;  
  17.   
  18.     /** 
  19.      * 风车图片 
  20.      */  
  21.     private Bitmap Windmill;  
  22.   
  23.     /** 
  24.      * 背景图片 
  25.      */  
  26.     private Bitmap viewBg;  
  27.   
  28.     public WindmillView(Context context) {  
  29.         super(context);  
  30.         this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,  
  31.                 LayoutParams.MATCH_PARENT));  
  32.         holder = getHolder();  
  33.         holder.addCallback(this);  
  34.         holder.setFormat(PixelFormat.RGBA_8888); // 顶层绘制SurfaceView设成透明  
  35.         getViewSize(context);  
  36.         LoadWindmillImage();  
  37.   
  38.     }  
  39.   
  40.     private void LoadWindmillImage() {  
  41.         viewBg = BitmapFactory.decodeResource(getResources(), R.drawable.bg_na);  
  42.         Windmill = BitmapFactory.decodeResource(getResources(),  
  43.                 R.drawable.na_windmill);  
  44.         windPoint = BitmapFactory.decodeResource(getResources(),  
  45.                 R.drawable.na_point);  
  46.         float percent = percentumW();  
  47.         Log.v("icers", screenWidth + "");  
  48.   
  49.         int _witdh = (int) (250 / percent);//250是风车基点左侧像素  
  50.         Log.v("icers", _witdh + "");  
  51.         Windmill = Bitmap.createScaledBitmap(Windmill, _witdh * 2, _witdh * 2,  
  52.                 true);  
  53.   
  54.     }  
  55.   
  56.   
  57.     // 获取屏幕的分辨率  
  58.     private void getViewSize(Context context) {  
  59.         DisplayMetrics metrics = new DisplayMetrics();  
  60.         WindowManager windowManager = (WindowManager) context  
  61.                 .getSystemService(Context.WINDOW_SERVICE);  
  62.         windowManager.getDefaultDisplay().getMetrics(metrics);  
  63.         this.screenHeiht = metrics.heightPixels;  
  64.         this.screenWidth = metrics.widthPixels;  
  65.   
  66.         Log.d("Windmill""Windmill:"+screenHeiht+"|"+screenWidth);  
  67.     }  
  68.   
  69.     /** 
  70.      * 获取背景图和风车的比率 ,从而根据这个比例改变各个手机上面的风车图片大小 
  71.      *  
  72.      *  
  73.      * @return 
  74.      */  
  75.     private float percentumW() {  
  76.         float bg_width = viewBg.getWidth();  
  77.         return  bg_width/screenWidth ;  
  78.     }  
  79.     /** 
  80.      * 获取背景图和风车的比率 ,从而根据这个比例改变各个手机上面的风车图片大小 
  81.      *  
  82.      *  
  83.      * @return 
  84.      */  
  85.     private float percentumH() {  
  86.         float bg_height = viewBg.getHeight();  
  87.         return  bg_height/(screenHeiht);  
  88.     }  
  89.   
  90.     @Override  
  91.     public void run() {  
  92.   
  93.         float rotate = 0;// 旋转角度变量  
  94.   
  95.         while (isRunning) {  
  96.             Log.i("icer""Running");  
  97.             Canvas canvas = null;  
  98.             synchronized (this) {  
  99.                 try {  
  100.                     canvas = holder.lockCanvas();  
  101.                     if (canvas != null) {  
  102.                         Paint paint = new Paint();  
  103.                         paint.setAntiAlias(true);  
  104.   
  105.                         // 对图片抗锯齿  
  106.                         paint.setFilterBitmap(true);  
  107.                         RectF rect = new RectF(00, screenWidth, screenHeiht  
  108.                                 );  
  109.                         canvas.drawBitmap(viewBg, null, rect, paint);  
  110.                         Matrix matrix = new Matrix();  
  111.                         matrix.postRotate((rotate += 2) % 360f,  
  112.                                 Windmill.getWidth() / 2,  
  113.                                 Windmill.getHeight() / 2);  
  114.                           
  115.                         int _dy = (int) (500 /percentumH()); //500是风车基点到背景定点的像素  
  116.                         matrix.postTranslate(0, (_dy - (Windmill.getHeight()/2)));  
  117.                         canvas.drawBitmap(Windmill, matrix, paint);  
  118.   
  119.                         int _dx = (int) (250 / percentumW());//250是风车基点左侧像素  
  120.                         canvas.drawBitmap(windPoint,_dx-windPoint.getWidth()/2,_dy-windPoint.getHeight()/2,paint);  
  121.                         Thread.sleep(3);  
  122.                     }  
  123.                 } catch (InterruptedException e) {  
  124.                     // TODO Auto-generated catch block  
  125.                     e.printStackTrace();  
  126.                 } finally {  
  127.                     if (canvas != null) {  
  128.                         holder.unlockCanvasAndPost(canvas);  
  129.                     }  
  130.                 }  
  131.   
  132.             }  
  133.   
  134.         }  
  135.   
  136.     }  
  137.   
  138.     public void setRunning(boolean state) {  
  139.         isRunning = state;  
  140.   
  141.     }  
  142.   
  143.     @Override  
  144.     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {  
  145.         // TODO Auto-generated method stub  
  146.   
  147.     }  
  148.   
  149.     @Override  
  150.     public void surfaceCreated(SurfaceHolder arg0) {  
  151.   
  152.         new Thread(this).start();  
  153.     }  
  154.   
  155.     @Override  
  156.     public void surfaceDestroyed(SurfaceHolder arg0) {  
  157.         // TODO Auto-generated method stub  
  158.         isRunning = false;  
  159.   
  160.     }  
  161.   
  162. }  


  1. @Override  
  2.    protected void onCreate(Bundle savedInstanceState) {  
  3.        super.onCreate(savedInstanceState);  
  4.          
  5.        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  6.        requestWindowFeature(Window.FEATURE_NO_TITLE);  
  7.        WindmillView view=new WindmillView(this);  
  8.     setContentView(view);  
  9.    }  


    整个过程:继承SurfaceView并实现SurfaceHolder.Callback接口 ----> SurfaceView.getHolder()获得SurfaceHolder对象---->SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布----> Canvas绘画 ---->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值