自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件:
两个TextView是用来显示提示信息和倒计时的秒数的
相关教程:Android开发从相机或相册获取图片裁剪
Android启动相机拍照并返回图片
接下来是mainActivity中的具体实现以及详细注释:
package com.dhsr.pujiejia.ui; import java.io.File; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; import com.example.pujiejiaapp.R; @SuppressLint({ "NewApi", "SdCardPath" }) public class CameraActivity extends Activity implements Runnable { // 预览图片范围 private SurfaceView surfaceView; private TextView tv_time; // 倒计时拍摄 private int cameratime = 4; private Camera camera; private boolean preview = false; // 文件名字 private String filename; // 文件名字的带的时间戳 private String timeString; // 格式化时间 private SimpleDateFormat dateFormat; // 日期对象 private Date date; // 控制线程 boolean stopThread = false; private File file; String photo; private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { int what = msg.what; switch (what) { case 222: tv_time.setText("" + cameratime); if ("0".equals(tv_time.getText().toString())) { tv_time.setText("拍摄成功!"); takePhoto(); } break; } }; }; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); CameraActivity.this.setFinishOnTouchOutside(false); // 初始化数据 findView(); surfaceView.getHolder().addCallback(new SufaceListener()); /* 下面设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前 */ surfaceView.getHolder() .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.getHolder().setFixedSize(200, 200); // 设置分辨率 } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); // 开启线程 new Thread(this).start(); } private final class SufaceListener implements SurfaceHolder.Callback { /** * surface改变 */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /** * surface创建 */ @Override public void surfaceCreated(SurfaceHolder holder) { try { for (int i = 0; i
核心代码详解:
1.创建SurfaceView时,surfaceCreated()方法中
for (int i = 0; i
此部分代码为打开相机时默认打开前置摄像头CameraInfo.CAMERA_FACING_BACK为默认打开后置摄像头,CameraInfo.CAMERA_FACING_FRONT前置摄像头
2.照片拍摄takePhoto()方法中:
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); timeString = formatDate(); filename = "/data/data/com.example.pujiejiaapp/images/" + timeString + ".jpg"; photo = timeString + ".jpg"; File file = new File(filename); boolean createNewFile = file.createNewFile(); FileOutputStream outStream = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 60, outStream);
此部分代码为将拍摄到的图片保存为以bitmap格式保存在指定的目录下
3.开子线程用于倒计时拍摄
public void run() { while (!stopThread) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } cameratime--; mHandler.sendEmptyMessage(222); if (cameratime <= 0) { break; } } }
希望大家理解核心代码的详细注释,欢迎提供意见,希望能给大家带来帮助,谢谢!