zoukankan      html  css  js  c++  java
  • 2.2.2 构建时间推移摄影应用程序

        我们都已经看过时间推移摄影的完美范例。他是在一段时间内拍摄多张照片的过程。它可能是每分钟,每小时甚至每周拍摄一张照片。通过查看一系列时间推移的照片,可以了解事物如何随时间而变化。一个可能的示例是观察一幢建筑物如何建造,另一个可能的示例是记录一朵花如何成长和盛开的。

       由于已经构建了一个基于定时器的Camera应用程序,因此将它更新成一个时间推移应用程序十分的简单。

       首先需要改变一些实例变量并加入一个常量。

    1   ...
    2   public class TimelapseSnapShot extends Activity implements OnClickListener,SurfaceHolder.Callback,Camera.PictureCallback{
    3     private SurfaceView cameraView;
    4     private SurfaceHolder surfaceHolder;
    5     private Camera camera;

       需要将Button重命名为startStopButton,因为它现在将处理两个动作,同时将对其余的变量名执行几个细小的更新。

    1     private Button startStopButton;
    2     private TextView countdownTextView;
    3     private Handler timerUpdateHandler;
    4     private boolean timerRunning=false;

       与前述的示例一样,currentTime整数将用于累加两次照相之间的时间量,而不是从总延迟递减。将一个称为SECONDS_BETWEEN_PHOTOS的常量设置为60.正如其名称所暗示的那样,该常量将用于设定拍摄照片之间等待的时间。

    1     private int currentTime=0;
    2     public static final int SECONDS_BETWEEN_PHOTOS=60;//一分鐘

       onCreate方法大体上保持相同——只是将引用新的变量名称。

     1     @Override
     2     protected void onCreate(Bundle savedInstanceState) {
     3         super.onCreate(savedInstanceState);
     4         setContentView(R.layout.snapshot);
     5         cameraView=(SurfaceView) findViewById(R.id.CameraView);
     6         
     7         surfaceHolder=cameraView.getHolder();
     8         surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
     9         surfaceHolder.addCallback(this);
    10         
    11         countdownTextView=(TextView) findViewById(R.id.CountDownTextView);
    12         startStopButton=(Button) findViewById(R.id.CountDownButton);
    13         startStopButton.setOnClickListener(this);
    14         
    15         timerUpdateHandler=new Handler();
    16     }

        将一个基于定时器的应用程序转换成一个时间推移应用程序的批量更改将出现onClick方法中,这是在按钮按下时由Handler安排的在Runnable方法中发生的操作。

        onClick方法首先检查时间推移进程目前是否在运行(以前是否已经按下按钮),如果还没有运行,那么将它设置为运行,并以Runnable(此处描述了该对象)作为参数调用这个Handler的post方法。

        如果时间推移进程正在运行,那么按下该按钮意味着停止他,从而调用该Handler(即timerUpdateHandler)上的removeCallbacks方法。这将清除作为参数传递的Runnable上所有等待的调用。

     1     @Override
     2     public void onClick(View v) {
     3         if(!timerRunning){
     4             startStopButton.setText("Stop");
     5             timerRunning=true;
     6             timerUpdateHandler.post(timerUpdateTask);
     7         }else{
     8             startStopButton.setText("Start");
     9             timerRunning=false;
    10             timerUpdateHandler.removeCallbacks(timerUpdateTask);
    11         }
    12     }

        当处理一个Handler以执行计划时,我们将拥有一个Runnable对象,该Handler将在到达指定时间时调用它。该Handler的run方法首先检查currentTime整数是否小于想要在拍摄照片之间等待的秒数。如果currentTime超过等待时间,那么会通知Camera应用程序拍照,并将currentTime设置回0,使其继续累加。

       每次发生这些情况之后,只须使用currentTime更新TextView,并安排一个在下一秒指向自身的调用。

     1     private Runnable timerUpdateTask=new Runnable() {
     2         
     3         @Override
     4         public void run() {
     5             if(currentTime<SECONDS_BETWEEN_PHOTOS){
     6                 currentTime++;
     7             }else{
     8                 camera.takePicture(null, null, TimelapseSnapShot.this);
     9                 currentTime=0;
    10             }
    11             timerUpdateHandler.postDelayed(timerUpdateTask, 1000);
    12             countdownTextView.setText(""+currentTime);
    13         }
    14     };

        当然,此示例的res/layout/timelapsesnapshot.xml界面和AndroidManifest.xml与倒计时计时器的版本相同。

        下面附上完整的项目代码:

      1 package com.nthm.androidtest;
      2 
      3 import java.io.FileNotFoundException;
      4 import java.io.IOException;
      5 import java.io.OutputStream;
      6 import java.util.Iterator;
      7 import java.util.List;
      8 import android.app.Activity;
      9 import android.content.ContentValues;
     10 import android.content.res.Configuration;
     11 import android.hardware.Camera;
     12 import android.net.Uri;
     13 import android.os.Bundle;
     14 import android.os.Handler;
     15 import android.provider.MediaStore.Images.Media;
     16 import android.view.SurfaceHolder;
     17 import android.view.SurfaceView;
     18 import android.view.View;
     19 import android.view.View.OnClickListener;
     20 import android.widget.Button;
     21 import android.widget.TextView;
     22 
     23 public class TimelapseSnapShot extends Activity implements OnClickListener,SurfaceHolder.Callback,Camera.PictureCallback{
     24     private SurfaceView cameraView;
     25     private SurfaceHolder surfaceHolder;
     26     private Camera camera;
     27     private Button startStopButton;
     28     private TextView countdownTextView;
     29     private Handler timerUpdateHandler;
     30     private boolean timerRunning=false;
     31     private int currentTime=0;
     32     public static final int SECONDS_BETWEEN_PHOTOS=60;//一分鐘
     33     
     34     @Override
     35     protected void onCreate(Bundle savedInstanceState) {
     36         super.onCreate(savedInstanceState);
     37         setContentView(R.layout.timelapsesnapshot);
     38         cameraView=(SurfaceView) findViewById(R.id.CameraView);
     39         
     40         surfaceHolder=cameraView.getHolder();
     41         surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
     42         surfaceHolder.addCallback(this);
     43         
     44         countdownTextView=(TextView) findViewById(R.id.CountDownTextView);
     45         startStopButton=(Button) findViewById(R.id.CountDownButton);
     46         startStopButton.setOnClickListener(this);
     47         
     48         timerUpdateHandler=new Handler();
     49     }
     50     @Override
     51     public void onClick(View v) {
     52         if(!timerRunning){
     53             startStopButton.setText("Stop");
     54             timerRunning=true;
     55             timerUpdateHandler.post(timerUpdateTask);
     56         }else{
     57             startStopButton.setText("Start");
     58             timerRunning=false;
     59             timerUpdateHandler.removeCallbacks(timerUpdateTask);
     60         }
     61     }
     62     private Runnable timerUpdateTask=new Runnable() {
     63         
     64         @Override
     65         public void run() {
     66             if(currentTime<SECONDS_BETWEEN_PHOTOS){
     67                 currentTime++;
     68             }else{
     69                 camera.takePicture(null, null, TimelapseSnapShot.this);
     70                 currentTime=0;
     71             }
     72             timerUpdateHandler.postDelayed(timerUpdateTask, 1000);
     73             countdownTextView.setText(""+currentTime);
     74         }
     75     };
     76     @Override
     77     public void onPictureTaken(byte[] data, Camera camera) {
     78         Uri imageFileUri=getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues());
     79         try {
     80             OutputStream imageFileOS=getContentResolver().openOutputStream(imageFileUri);
     81             imageFileOS.write(data);
     82             imageFileOS.flush();
     83             imageFileOS.close();
     84         } catch (FileNotFoundException e) {
     85             e.printStackTrace();
     86         }catch (IOException e) {
     87             e.printStackTrace();
     88         }
     89         camera.startPreview();
     90     }
     91     @Override
     92     public void surfaceCreated(SurfaceHolder holder) {
     93         camera=Camera.open();
     94     try {
     95         camera.setPreviewDisplay(holder);
     96         Camera.Parameters parameters=camera.getParameters();
     97         if(this.getResources().getConfiguration().orientation!=Configuration.ORIENTATION_LANDSCAPE){
     98             //这是一个众所周知但未文档化的特性
     99             parameters.set("orientation", "portrait");
    100             //对于Android 2.2及其以上版本
    101             camera.setDisplayOrientation(90);
    102             //对于Android 2.0及其以上版本取消注释
    103             parameters.setRotation(90);
    104         }
    105         //用于Android 2.0 和更高版本的效果
    106         List<String> colorEffects=parameters.getSupportedColorEffects();
    107         Iterator<String> cei=colorEffects.iterator();
    108         while(cei.hasNext()){
    109             String currentEffect=cei.next();
    110             if(currentEffect.equals(Camera.Parameters.EFFECT_SOLARIZE)){
    111                 parameters.setColorEffect(currentEffect);
    112             }
    113         }
    114         //结束Android 2.0 和更高版本的效果
    115         camera.setParameters(parameters);
    116         } catch (IOException e) {
    117             camera.release();
    118         }
    119     }
    120 
    121     @Override
    122     public void surfaceChanged(SurfaceHolder holder, int format, int width,
    123             int height) {
    124         camera.startPreview();
    125     }
    126 
    127     @Override
    128     public void surfaceDestroyed(SurfaceHolder holder) {
    129         camera.stopPreview();
    130         camera.release();
    131     }
    132 }

        timelapsesnapshot.xml布局代码

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     android:layout_width="match_parent"
     3     android:layout_height="match_parent"
     4     android:orientation="vertical"
     5     >
     6 <FrameLayout 
     7     android:id="@+id/FrameLayout01"
     8     android:layout_width="wrap_content"
     9     android:layout_height="wrap_content"
    10     >
    11     <SurfaceView 
    12         android:id="@+id/CameraView"
    13         android:layout_width="match_parent"
    14         android:layout_height="match_parent"
    15         />
    16     <LinearLayout 
    17         android:id="@+id/LinearLayout01"
    18         android:layout_width="wrap_content"
    19         android:layout_height="wrap_content"
    20         android:orientation="horizontal"
    21         >
    22         <TextView 
    23          android:id="@+id/CountDownTextView"
    24          android:layout_width="match_parent"
    25          android:layout_height="wrap_content"
    26          android:text="10"
    27          android:textSize="100dip"
    28          android:layout_gravity="center_vertical|center_horizontal|center"/>
    29         <Button 
    30          android:id="@+id/CountDownButton"
    31          android:layout_width="wrap_content"
    32          android:layout_height="wrap_content"
    33          android:text="Start Time"/>
    34     </LinearLayout>
    35 </FrameLayout>
    36 </LinearLayout>
  • 相关阅读:
    山东农户靠养殖山鸡致富,年纯收入达6万
    3个小鲜肉依托网购创业,现公司市值达477亿美元
    为什么劝你别去创业?大抵逃不掉这 101 个问题
    Python自动化运维一之psutil
    Python自动化运维一之psutil
    Python自动化运维一之psutil
    Python自动化运维一之psutil
    Gradle task简单使用
    Gradle task简单使用
    Gradle task简单使用
  • 原文地址:https://www.cnblogs.com/ZSS-Android/p/3929710.html
Copyright © 2011-2022 走看看