这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能。

首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件:

activity_main.xml

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/surface_view"

android:layout_width="match_parent"

android:layout_height="match_parent" />

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

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"/>

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"/>

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自定义相机实现定时拍照功能相关推荐

  1. Android自定义相机实现定时拍照

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml <F ...

  2. android 自定义相机,Android自定义相机实现定时拍照功能

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml andro ...

  3. Android开发(Jetpack) 学习CameraX 自定义相机实现

    目录 一.CameraX和Camera2 二.CameraX的引入 三.自定义拍照 四.自定义视频录制 五.XML 配置 一.CameraX和Camera2 CameraX 是一个 Jetpack 库 ...

  4. android文字自动滚动,Android TextView文字横向自动滚动(跑马灯)

    TextView实现文字滚动需要以下几个要点: 1.文字长度长于可显示范围:android:singleLine="true" 2.设置可滚到,或显示样式:android:elli ...

  5. android notification自动消失,Android开发 -- 状态栏通知Notification、NotificationManager详解...

    本想自己写一个的,但是看到这篇之后,我想还是转过来吧,实在是非常的详细: 在Android系统中,发一个状态栏通知还是很方便的.下面我们就来看一下,怎么发送状态栏通知,状态栏通知又有哪些参数可以设置? ...

  6. android 导航自动切换,Android导航抽屉切换图标向右

    吃鸡游戏 我为EndDrawerToggle该类编写了一个与您的设置非常相似的设置- DrawerLayout带末端对齐的抽屉View,AppCompatActivity带有自定义Toolbar的支持 ...

  7. android设置自动亮度,Android亮度调节的几种实现方法

    最近在做一个App的设置项,亮度调节.真正做时,发现Android亮度调节比预想要复杂一些.其实目前网上已有不少这方面的资料,但有些博文具有一定误导性.在此将这块内容按照自己理解整理一下. 整体上看, ...

  8. android 键盘 自动消失,android 键盘状态,获取键盘显示和隐藏

    要设置弹出键盘是否覆盖Activity的view,或者软键盘的显示隐藏状态,需要用到Activity的一个属性: android:windowSoftInputMode 该属性在AndroidMani ...

  9. android edittext自动获取焦点,Android取消EditText自动获取默认焦点

    Android取消EditText自动获取默认焦点 发布时间:2020-10-02 14:08:30 来源:脚本之家 阅读:142 作者:ganchuanpu 最近在通讯录新建联系人=中,一进入一个页 ...

最新文章

  1. 关于S/4HANA里Sales Office 和Sales Organization那些事儿
  2. 20 道 Spring Boot 面试题
  3. 了解vue里的Runtime Only和Runtime+Compiler
  4. php多进程实现 亲测
  5. 【转】mac os、linux及unix之间的关系
  6. spring boot 异常汇总
  7. inotify监听文件夹的变动
  8. 201621123058《java程序设计》第二周学习总结
  9. 搭建卷积神经网络时loss计算方式的选择
  10. “约见”面试官系列之常见面试题第五篇说说vuex登录信息(建议收藏)
  11. 今天的一下子跳出来了的超级玛丽
  12. unity3d android debug log,调试 – 如何在连接到设备时看到MonoDevelop Unity中的Debug.Log输出?...
  13. 【BZOJ】【3671】【NOI2014】随机数生成器
  14. python引用参数在哪里_参数在Python中是否通过引用传递
  15. Spring Security三种认证
  16. 当我们点击一个文本域在IE下会发生的事件
  17. 《安富莱嵌入式周报》第259期:2022.03.28--2022.04.03
  18. 1.5时钟控制的触发器(钟控JK、钟控T触发器)
  19. Packet Tracer 思科模拟器入门教程 之十一 路由器静态路由配置
  20. 穆迪分析宣布推出云服务,助力银行实现监管合规

热门文章

  1. ActiveMQ –经纪人网络解释–第3部分
  2. JavaFX自定义控件– Nest Thermostat第1部分
  3. Orika:将JAXB对象映射到业务/域对象
  4. 在Activiti中执行自定义查询
  5. 如何编写更好的POJO服务
  6. Spring JDBC数据库连接池设置
  7. Spring和JSF集成:动态导航
  8. 玩! 框架+ Google Guice
  9. JavaFX移动应用程序最佳实践,第2部分
  10. pb90代码如何连接sql2008r2_如何使用 HTTP Headers 来保护你的 Web 应用