Android自定义相机实现定时拍照功能
发布时间 - 2026-01-10 22:42:42 点击率:次这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能。

首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件:
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:layout_marginBottom="10dp" android:src="@drawable/capture"/> <TextView android:id="@+id/count_down" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:gravity="center" android:textSize="80sp"/> </RelativeLayout> </FrameLayout>
MainActivity.java
package com.jackie.timercamera;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback,
View.OnClickListener, Camera.PictureCallback {
private SurfaceView mSurfaceView;
private ImageView mIvStart;
private TextView mTvCountDown;
private SurfaceHolder mHolder;
private Camera mCamera;
private Handler mHandler = new Handler();
private int mCurrentTimer = 10;
private boolean mIsSurfaceCreated = false;
private boolean mIsTimerRunning = false;
private static final int CAMERA_ID = 0; //后置摄像头
// private static final int CAMERA_ID = 1; //前置摄像头
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initEvent();
}
@Override
protected void onPause() {
super.onPause();
stopPreview();
}
private void initView() {
mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
mIvStart = (ImageView) findViewById(R.id.start);
mTvCountDown = (TextView) findViewById(R.id.count_down);
}
private void initEvent() {
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mIvStart.setOnClickListener(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsSurfaceCreated = true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsSurfaceCreated = false;
}
private void startPreview() {
if (mCamera != null || !mIsSurfaceCreated) {
Log.d(TAG, "startPreview will return");
return;
}
mCamera = Camera.open(CAMERA_ID);
Camera.Parameters parameters = mCamera.getParameters();
int width = getResources().getDisplayMetrics().widthPixels;
int height = getResources().getDisplayMetrics().heightPixels;
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null) {
//设置预览分辨率
parameters.setPreviewSize(size.width, size.height);
//设置保存图片的大小
parameters.setPictureSize(size.width, size.height);
}
//自动对焦
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
parameters.setPreviewFrameRate(20);
//设置相机预览方向
mCamera.setDisplayOrientation(90);
mCamera.setParameters(parameters);
try {
mCamera.setPreviewDisplay(mHolder);
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
mCamera.startPreview();
}
private void stopPreview() {
//释放Camera对象
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters) {
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) {
result = size;
}
}
}
}
return result;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:
if (!mIsTimerRunning) {
mIsTimerRunning = true;
mHandler.post(timerRunnable);
}
break;
}
}
private Runnable timerRunnable = new Runnable() {
@Override
public void run() {
if (mCurrentTimer > 0) {
mTvCountDown.setText(mCurrentTimer + "");
mCurrentTimer--;
mHandler.postDelayed(timerRunnable, 1000);
} else {
mTvCountDown.setText("");
mCamera.takePicture(null, null, null, MainActivity.this);
playSound();
mIsTimerRunning = false;
mCurrentTimer = 10;
}
}
};
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
FileOutputStream fos = new FileOutputStream(new File
(Environment.getExternalStorageDirectory() + File.separator +
System.currentTimeMillis() + ".png"));
//旋转角度,保证保存的图片方向是对的
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix matrix = new Matrix();
matrix.setRotate(90);
bitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
}
/**
* 播放系统拍照声音
*/
public void playSound() {
MediaPlayer mediaPlayer = null;
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int volume = audioManager.getStreamVolume( AudioManager.STREAM_NOTIFICATION);
if (volume != 0) {
if (mediaPlayer == null)
mediaPlayer = MediaPlayer.create(this,
Uri.parse("file:///system/media/audio/ui/camera_click.ogg"));
if (mediaPlayer != null) {
mediaPlayer.start();
}
}
}
}
有两点需要注意:对于Camera来说,默认是横屏的,所以预览的时候和图片保存的时候都是横屏的,需要调整角度。
设置相机预览方法:
//设置相机预览方向 mCamera.setDisplayOrientation(90);
保存图片的时候调整角度:
效果图如下:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Android相机定时拍照
# Android定时拍照
# Android相机拍照
# Android自定义相机聚焦和显示框
# Android自定义相机Camera实现手动对焦的方法示例
# android 7自定义相机预览及拍照功能
# Android开源库自定义相机模块
# Android 自定义相机及分析源码
# Android 用 camera2 API 自定义相机
# Android中关于自定义相机预览界面拉伸问题
# Android自定义相机实现自动对焦和手动对焦
# Android自定义相机界面的实现代码
# Android自定义相机、预览区域裁剪
# 自定义
# 都是
# 这篇
# 需要注意
# 大家多多
# 倒计时
# 自动对焦
# 有两点
# 博客
# util
# AppCompatActivity
# app
# support
# Log
# widget
# io
# File
# view
# SurfaceHolder
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何使用查询构建器?(Query Builder高级用法)
linux写shell需要注意的问题(必看)
个人摄影网站制作流程,摄影爱好者都去什么网站?
,网页ppt怎么弄成自己的ppt?
悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音
EditPlus中的正则表达式 实战(1)
制作旅游网站html,怎样注册旅游网站?
如何在橙子建站中快速调整背景颜色?
如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程
Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑
Laravel怎么发送邮件_Laravel Mail类SMTP配置教程
如何快速生成高效建站系统源代码?
如何在Windows环境下新建FTP站点并设置权限?
网站建设保证美观性,需要考虑的几点问题!
b2c电商网站制作流程,b2c水平综合的电商平台?
Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
Android仿QQ列表左滑删除操作
如何在阿里云ECS服务器部署织梦CMS网站?
Laravel如何配置和使用缓存?(Redis代码示例)
Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转
Laravel Asset编译怎么配置_Laravel Vite前端构建工具使用
如何用5美元大硬盘VPS安全高效搭建个人网站?
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
如何正确选择百度移动适配建站域名?
Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧
如何快速重置建站主机并恢复默认配置?
Laravel如何处理异常和错误?(Handler示例)
Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程
千库网官网入口推荐 千库网设计创意平台入口
开心动漫网站制作软件下载,十分开心动画为何停播?
Win11怎么修改DNS服务器 Win11设置DNS加速网络【指南】
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
如何自定义建站之星模板颜色并下载新样式?
google浏览器怎么清理缓存_谷歌浏览器清除缓存加速详细步骤
微信推文制作网站有哪些,怎么做微信推文,急?
如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】
网页设计与网站制作内容,怎样注册网站?
JS实现鼠标移上去显示图片或微信二维码
python中快速进行多个字符替换的方法小结
Thinkphp 中 distinct 的用法解析
标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?
文字头像制作网站推荐软件,醒图能自动配文字吗?
Laravel如何使用Passport实现OAuth2?(完整配置步骤)
智能起名网站制作软件有哪些,制作logo的软件?
如何在阿里云香港服务器快速搭建网站?
Laravel队列由Redis驱动怎么配置_Laravel Redis队列使用教程
悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤
黑客入侵网站服务器的常见手法有哪些?
南京网站制作费用,南京远驱官方网站?

