创新实训项目分析——第八篇

2021SC@SDUSC


前言

以手机相机为依托的camera项目不仅需要有基础的拍照功能,并且还需要对拍摄的照⽚进⾏⼀系列处理,包括但不仅限于图⽚抗扭曲,曝光度,聚焦等。具体可以整理为以下功能:
1. 相机预览功能
2. 拍照的偏好设置,如闪光灯,聚焦,曝光补偿
3. 相机可随设备旋转,拍摄横屏和竖屏的照⽚
4. 拍照后保存在⼿机的pictures⽂件夹
5. 可以预览拍摄的照⽚
6. 图⽚抗扭曲处理
这篇将继续分析相机的偏好设置和拍照的功能。

一、项目环境

android studio版本 4.1.2

sdk版本 Compile SDK version:30

Build Tools Version 30.0.3

gradle版本 6.8.3

二、代码分析

条目value变化时立即应用设置

用户调整偏好设置之后,SettingsFragment需要监听条目value变化,给SettingsFragment添加监听事件,一旦出现变化,就根据其key立即应用新的value到相机。


public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    switch (key) {//key中存储变化的偏好设置
        case KEY_PREF_FOCUS_MODE:
            setFocusMode(sharedPreferences.getString(key, ""));
            break;
        case KEY_PREF_FLASH_MODE:
            setFlashMode(sharedPreferences.getString(key, ""));
            break;
      case KEY_PREF_EXPOS_COMP:
            setExposComp(sharedPreferences.getString(key, ""));
            break;
    }
    mCamera.stopPreview();
    mCamera.setParameters(mParameters);
    mCamera.startPreview();
}

onSharedPreferenceChanged()为监听事件回调。onResume()和onPause()是Android推荐写法,防止由于Fragment的不断调用导致事件监听失效。
onResume():onResume()是当该activity与用户能进行交互时被执行,用户可以获得activity的焦点,能够与用户交互。此时的活动一定位于返回栈的栈顶,并且处于运行状态。
onPause():onPause()意味着你的activity仍然处于部分可见的状态,但正在进入其他的activity,当时大多数时候,那意味着用户正在离开这个activity并马上会进入Stopped state. Activity必需离开Activity栈的栈顶
onStop():当你的activity调用onStop()方法, activity不再可见,并且应该释放那些不再需要的所有资源。一旦你的activity停止了,系统会在不再需要这个activity时摧毁它的实例。在极端情况下,系统会直接杀死你的app进程,并且不执行activity的onDestroy()回调方法, 因此你需要使用onStop()来释放资源,从而避免内存泄漏。
onDestory(): onDestory()作用是在一个Activity对象被销毁之前,Android系统会调用该方法,用于释放此Activity之前所占用的资源。
三种调用的场景:
一个Activity启动另一个Activity: onPause()->onStop(),再返回:onRestart()->onStart()->onResume()
程序按back 退出: onPause()->onStop()->onDestory(),再进入:onCreate()->onStart()->onResume();
程序按home 退出: onPause()->onStop(),再进入:onRestart()->onStart()->onResume();

设置菜单中显示ListPreference的当前值

PreferenceGroup是直接继承于Preference,起到的是一个容器作用,他的子类有 PreferenceCategory 和PreferenceScreen,这两个直接继承PreferenceGroup所以在开发中起的作用也是容器,用于”安置“其他子Preference的容器。

如果pref时PreferenceGroup的实例,那pref中将pref强转为PreferenceGroup类,利用PreferenceGroup中的getPreference()方法获取到容器内Preference的数量,并且利用getPreference来得到参数,这是一个嵌套函数,如果已经得到了具体的函数,就调用updateSummary方法, 利用getEntry()方法用于在指定参数的帮助下获取此实例的 参数值。

private static void initSummary(Preference pref) {
    if (pref instanceof PreferenceGroup) {
        PreferenceGroup prefGroup = (PreferenceGroup) pref;
        for (int i = 0; i < prefGroup.getPreferenceCount(); i++) {
            initSummary(prefGroup.getPreference(i));
        }
    } else {
        updatePrefSummary(pref);
    }
}
private static void updatePrefSummary(Preference pref) {
    if (pref instanceof ListPreference) {
        pref.setSummary(((ListPreference) pref).getEntry());
    }
}
 

以下是界面效果:在这里插入图片描述

在这里插入图片描述

照片文件命名:生成文件名

文件名首先标记文件类型,然后是时间,如IMG_20160503_153218.jpg,在CameraPreview中添加:

public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
private Uri outputMediaFileUri;
private String outputMediaFileType ="0";

external storage就是SD卡,利用了Environment.getExternalStoragePubicDirectory( Environment.DIRECTORY_PICTURES)获得到文件存储目录,用以进一步存储照片,getExternalStoragePubicDirectory()是一个更加方便的访问Android给我们提供好的一些公共目录的方法
File.separator 的作用相当于 ’ \ ',起到一个分隔符的作用,用于指定新文件的路径
URI,统一资源标志符(Uniform Resource Identifier, URI),表示的是每一种可用的资源,如 图像、视频片段、程序等都由一个URI进行标识的。

private File getOutputMediaFile(int type) {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), TAG);
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.d(TAG, "failed to create directory");
                return null;
            }//创建目录,失败返回false
        }
        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");
            outputMediaFileType = "image/*";
        } else if (type == MEDIA_TYPE_VIDEO) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "VID_" + timeStamp + ".mp4");
            outputMediaFileType = "video/*";
        } else {
            return null;
        }
        outputMediaFileUri = Uri.fromFile(mediaFile);
        return mediaFile;
    }
public Uri getOutputMediaFileUri() {
    return outputMediaFileUri;
}
public String getOutputMediaFileType() {
    return outputMediaFileType;
}

三、总结

这次分析完成了相机预览和偏好设置的代码,并且开始了关于拍照处理的代码,首先分析了关于拍照片文件命名和存储的代码,下一篇将开始分析如何实现拍照

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值