刚刚运动完回来,又跑过来写博客啦,因为我前几天呢写了一下拍照的小demo,所以现在过来总结啦.
关于拍照呢,我们可以自定义,也可以直接调用系统的,在这里我就把两种方法都说一下吧.
一.自定义类型
如果想要自定义的话呢,我们要使用SurfaceView,用来显示摄像头所照到的视图,我就只知道它就是可以显示你拍照的那个区域,详细解释的话,大家去百度好不好呀.
以下是我的xml文件代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="5"/>
<LinearLayout
android:id="@+id/buttonLayout"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ImageView
android:id="@+id/scalePic"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginLeft="10dp"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_gravity="center_vertical"
android:onClick="imageClick"
android:background="@drawable/img_frame"
/>
<Button
android:id="@+id/takepicture"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginLeft="40dp"
android:background="@drawable/btn"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_gravity="center"
android:onClick="btnOnclick"
/>
</LinearLayout>
</LinearLayout>
我本来是想把按钮放中间,但是我底下有俩个控件,不太会弄,如果有啥方法的话大家可以告诉我
现在我们要开始设置权限了哟
<uses-sdk
android:minSdkVersion="5"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这里大家要注意以下手机安卓版本,我上次把minSDK设置成了4,但我手机是5点几,结果我创建文件夹总是不成功,导致保存图片保存不了
设置完权限,我们就要开始写MainActivity了哟
首先呢我们使用surfaceview.getHolder()这个方法得到SurfaceHolder对象,然后调用几个方法,下面有注释
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 显示界面
setContentView(R.layout.activity_main);
layout = this.findViewById(R.id.buttonLayout);
// scalePic = (ImageView)findViewById(R.id.scalePic);
SurfaceView surfaceView = (SurfaceView) this
.findViewById(R.id.surfaceView);
surfaceView.getHolder()
.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView.getHolder().setFixedSize(176, 144); //设置Surface分辨率
surfaceView.getHolder().setKeepScreenOn(true);// 屏幕常亮
surfaceView.getHolder().addCallback(new SurfaceCallback());//为SurfaceView的句柄添加一个回调函数
}
然后我们来写SurfaceCallback这个类
private final class SurfaceCallback implements Callback {
// 拍照状态变化时调用该方法
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
parameters = camera.getParameters(); // 获取各项参数
parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式
parameters.setPreviewSize(width, height); // 设置预览大小
parameters.setPreviewFrameRate(5); //设置每秒显示4帧
parameters.setPictureSize(width, height); // 设置保存的图片尺寸
parameters.setJpegQuality(80); // 设置照片质量
}
// 开始拍照时调用该方法
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open(); // 打开摄像头
camera.setPreviewDisplay(holder); // 设置用于显示拍照影像的SurfaceHolder对象
camera.setDisplayOrientation(getPreviewDegree(MainActivity.this));
camera.startPreview(); // 开始预览
} catch (Exception e) {
e.printStackTrace();
}
}
// 停止拍照时调用该方法
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
camera.release(); // 释放照相机
camera = null;
}
}
}
然后我们来给按钮绑定监听
*/
public void btnOnclick(View v) {
if (camera != null) {
switch (v.getId()) {
case R.id.takepicture:
// 拍照
camera.takePicture(null, null, new MyPictureCallback());
System.out.println("takePicture!!!!!");
break;
}
}
}
takePicture()方法是camera自带的,我们只要重写一下第三个参数
<pre name="code" class="html">private final class MyPictureCallback implements PictureCallback {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
bundle = new Bundle();
bundle.putByteArray("bytes", data); //将图片字节数据保存在bundle当中,实现数据交换
saveToSDCard(data); // 保存图片到sd卡中
Toast.makeText(getApplicationContext(),"success",
Toast.LENGTH_SHORT).show();
camera.startPreview(); // 拍完照后,重新开始预览
} catch (Exception e) {
e.printStackTrace();
}
}
}
至于里面保存到sd卡的方法我就不展示啦,还有显示图片的那个方法我虽然写了但是也没写好,所以我这里就只展示怎么自定义拍照了
二.调用系统照相机
调用系统的话,代码更简单而且照片拍出来更清楚呢,不过有一个问题就是我不知道如何调用照相机的同时下面可以将手机系统的相册展示出来(百度了好久也没找到,难道我瞎了?????)
调用系统自带的相机关键代码就是这个
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
然后要重写onActivityResult方法
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
/* String sdStatus = Environment.getExternalStorageState();
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 检测sd是否可用
Log.i("TestFile",
"SD card is not avaiable/writeable right now.");
return;
}*/
File sd = Environment.getExternalStorageDirectory();
String path = sd.getPath()+"/DCIM/Camera";
String name = new DateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg";
Toast.makeText(this, name, Toast.LENGTH_LONG).show();
bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data");// 获取相机返回的数据,并转换为Bitmap图片格式
File file = new File(path);
if(!file.exists()){
file.mkdirs();
System.out.println(file.mkdirs());
}
File bitFile = new File(file,name);
try {
bitFile.createNewFile();
System.out.println(bitFile);
FileOutputStream stream = new FileOutputStream(bitFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
((ImageView) findViewById(R.id.scalePic)).setImageBitmap(bitmap);// 将图片显示在ImageView里
takePic();
//lblImage.setImageBitmap(bitmap);
}
}
我把那个调用相机的方法写在了takePic()里面,所以拍完之后可以继续拍,至于那个ImageView就忽略吧,没弄出来(伤心呀).
好了,就写到这里啦,虽然本人文采也不好,技术也不强,但是我也算是走心了,大家多多指教多多忍受一下,我又要去玩耍了(听说打篮球可以长高,我走啦哈哈哈哈哈哈).