Android自定義相機(jī)實(shí)現(xiàn)定時(shí)拍照功能
這篇博客為大家介紹Android自定義相機(jī),并且實(shí)現(xiàn)倒計(jì)時(shí)拍照功能。
首先自定義拍照會(huì)用到SurfaceView控件顯示照片的預(yù)覽區(qū)域,以下是布局文件:
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) { //設(shè)置預(yù)覽分辨率 parameters.setPreviewSize(size.width, size.height); //設(shè)置保存圖片的大小 parameters.setPictureSize(size.width, size.height); } //自動(dòng)對焦 parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); parameters.setPreviewFrameRate(20); //設(shè)置相機(jī)預(yù)覽方向 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")); //旋轉(zhuǎn)角度,保證保存的圖片方向是對的 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(); } /** * 播放系統(tǒng)拍照聲音 */ 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(); } } } }
有兩點(diǎn)需要注意:對于Camera來說,默認(rèn)是橫屏的,所以預(yù)覽的時(shí)候和圖片保存的時(shí)候都是橫屏的,需要調(diào)整角度。
設(shè)置相機(jī)預(yù)覽方法:
//設(shè)置相機(jī)預(yù)覽方向 mCamera.setDisplayOrientation(90);
保存圖片的時(shí)候調(diào)整角度:
效果圖如下:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android自定義相機(jī)聚焦和顯示框
- Android自定義相機(jī)Camera實(shí)現(xiàn)手動(dòng)對焦的方法示例
- android 7自定義相機(jī)預(yù)覽及拍照功能
- Android開源庫自定義相機(jī)模塊
- Android 自定義相機(jī)及分析源碼
- Android 用 camera2 API 自定義相機(jī)
- Android中關(guān)于自定義相機(jī)預(yù)覽界面拉伸問題
- Android自定義相機(jī)實(shí)現(xiàn)自動(dòng)對焦和手動(dòng)對焦
- Android自定義相機(jī)界面的實(shí)現(xiàn)代碼
- Android自定義相機(jī)、預(yù)覽區(qū)域裁剪
相關(guān)文章
Android studio 4.1打包失敗和插件錯(cuò)誤提示的解決
這篇文章主要介紹了Android studio 4.1打包失敗和插件錯(cuò)誤提示的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10Android編程之SurfaceView學(xué)習(xí)示例詳解
這篇文章主要介紹了Android編程之SurfaceView學(xué)習(xí)示例,結(jié)合實(shí)例分析了SurfaceView的功能、使用方法與注意事項(xiàng),具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10Android基于PhotoView實(shí)現(xiàn)的頭像/圓形裁剪控件
這篇文章主要給大家介紹了關(guān)于Android基于PhotoView實(shí)現(xiàn)的頭像/圓形裁剪控件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07Android 實(shí)現(xiàn)圖片生成卷角和圓角縮略圖的方法
本篇文章主要介紹了Android 實(shí)現(xiàn)圖片生成卷角和圓角縮略圖的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11Android4.2中全屏或者取消標(biāo)題欄的方法總結(jié)
有的時(shí)候我們會(huì)看到,會(huì)先出現(xiàn)標(biāo)題欄,然后再消失,因?yàn)槲覀冎皇窃赼ctivity的oncreate方法中定義的,其他實(shí)現(xiàn)方法如下,感興趣的朋友可以了解下哈2013-06-06Android鬧鐘啟動(dòng)時(shí)間設(shè)置無效問題的解決方法
這篇文章主要為大家詳細(xì)介紹了Android鬧鐘啟動(dòng)時(shí)間設(shè)置無效問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06Android Studio Intent隱式啟動(dòng),發(fā)短信,撥號,打電話,訪問網(wǎng)頁等實(shí)例代碼
這篇文章主要介紹了Android Studio Intent隱式啟動(dòng),發(fā)短信,撥號,打電話,訪問網(wǎng)頁等實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-12-12