您的位置:首页 > 移动开发 > Android开发

Android开发之Textureview简介

2016-08-10 23:32 309 查看
最近,在修改Android4.4的原生相机Camera2,很习惯的去寻找SurfaceView,结果任凭我使用grep还是ack,都无法搜索到SurfaceView,最后还是通过代码CameraActivity-->CameraModule-->PhotoUI-->R.layout.photo_module找到,原来是使用了TextureView。不是很了解此控件,百度之,在官方API文档中找到此控件:

官方文档大概的意思是:

TextureView可以用来显示内容流。这样一个内容流例如可以视频或者OpenGL的场景。内容流可以来自本应用程序以及其他进程。

Textureview必须在硬件加速开启的窗口中。

与SurfaceView相比,TextureView不会创建一个单独的窗口,这使得它可以像一般的View一样执行一些变换操作,比如移动、动画等等,例如,你可以通过调用myView.setAlpha(0.5f)将TextureView设置成半透明。

使用TextureView很简单:你需要使用的就是SurfaceTexture,SurfaceTexture可以用于呈现内容。

下面是我写一个小例子来演示如何渲染相机预览到TextureView,在官方文档例子的基础上稍微改动了一下:

main.xml:

<framelayout android:id="@+id/camera_preview" android:layout_height="fill_parent" android:layout_weight="1" android:layout_width="fill_parent">

</framelayout>


CameraPreview.java:

import java.io.IOException;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.view.TextureView;

@SuppressLint(NewApi)
public class CameraPreview extends TextureView implements
TextureView.SurfaceTextureListener {
private Camera mCamera;
private TextureView mTextureView;
public CameraPreview(Context context , Camera camera) {
super(context);
mCamera = camera;
// TODO Auto-generated constructor stub
}

public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height) {
//        mCamera = Camera.open();
try {
mCamera.setPreviewTexture(surface);
mCamera.startPreview();
} catch (IOException ioe) {
// Something bad happened
}
}

public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height) {
// Ignored, Camera does all the work for us
}

public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
return true;
}

public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Invoked every time there's a new Camera preview frame
}

}


CameraTest.java:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;

import com.example.mycamera.R.id;

@SuppressLint(NewApi)
public class CameraTest extends Activity {
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
private Camera mCamera;
private CameraPreview mPreview;
private static final String TAG = ERROR;
private PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
Log.d(TAG,
Error creating media file, check storage permissions:
+ e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, File not found:  + e.getMessage());
} catch (IOException e) {
Log.d(TAG, Error accessing file:  + e.getMessage());
}
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 创建Camera实例
mCamera = getCameraInstance();
// 创建Preview view并将其设为activity中的内容
mPreview = new CameraPreview(this, mCamera);
mPreview.setSurfaceTextureListener(mPreview);
//设置浑浊
mPreview.setAlpha(0.5f);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
// preview.setAlpha(0.0f);
preview.addView(mPreview);
// 在Capture按钮中加入listener
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 从摄像头获取图片
mCamera.takePicture(null, null, mPicture);
}
});
}

/** 安全获取Camera对象实例的方法 */

public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open(); // 试图获取Camera实例
}
catch (Exception e) {
// 摄像头不可用(正被占用或不存在)
}
return c; // 不可用则返回null
}

/** 为保存图片或视频创建File */
private static File getOutputMediaFile(int type) {
// 安全起见,在使用前应该
// 用Environment.getExternalStorageState()检查SD卡是否已装入
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
MyCameraApp);
// 如果期望图片在应用程序卸载后还存在、且能被其它应用程序共享,
// 则此保存位置最合适
// 如果不存在的话,则创建存储目录
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(MyCameraApp, failed to create directory);
return null;
}
Log.d(MyCameraApp, failed to create directory);
}
// 创建媒体文件名
String timeStamp = new SimpleDateFormat(yyyyMMdd_HHmmss)
.format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ IMG_ + timeStamp + .jpg);
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ VID_ + timeStamp + .mp4);
} else {
return null;
}
return mediaFile;
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// 捕获的图像保存到Intent指定的fileUri
Toast.makeText(this, Image saved to:
+ data.getData(),
Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_CANCELED) {
// 用户取消了图像捕获
} else {
// 图像捕获失败,提示用户
}
}

if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// 捕获的视频保存到Intent指定的fileUri
Toast.makeText(this, Video saved to:
+ data.getData(),
Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_CANCELED) {
// 用户取消了视频捕获
} else {
// 视频捕获失败,提示用户
}
}
}

@Override
protected void onPause() {
super.onPause();
releaseCamera(); // 在暂停事件中立即释放摄像头
}

private void releaseCamera() {
if (mCamera != null) {
mCamera.release(); // 为其它应用释放摄像头
mCamera = null;
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息