博客:Android相机开发(二): 给相机加上偏好设置
https://www.polarxiong.com/archives/Android%E7%9B%B8%E6%9C%BA%E5%BC%80%E5%8F%91-%E4%BA%8C-%E7%BB%99%E7%9B%B8%E6%9C%BA%E5%8A%A0%E4%B8%8A%E5%81%8F%E5%A5%BD%E8%AE%BE%E7%BD%AE.html
概述:为相机APP添加偏好设置[分辨率、闪光灯、对焦]
设置菜单:PreferenceFragment [父类 Fragment]
自定义设置类:SettingsFragment
# 初始代码
import android.os.Bundle;
import android.preference.PreferenceFragment;
public class SettingFragment extends PreferenceFragment{
@Override
public void onCreate(Bundle savedInstanceState){
super onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);//加载xml中的菜单条目
}
}
添加菜单条目
# 过程:res下新建xml文件夹 --> xml文件夹内新建文件 preferences.xml
# 代码
<?xml version="1.0" encoding="utf-8"?>
<PreferenceSceren xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:defaultValue = "100"
android:entries = "@array/pref_jpegQuality"
android:entryValues = "@array/pref_jpegQuality"
android:key = "jpeg_quality"
android:title = "照片品质" />
<ListPreference .../>
<ListPreference .../>
</PreferenceSreen>
添加array值
# 过程: res->values下新建文件arrays.xml
# 代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name = "pref_jpegQuality">
<item>100</item>
<item>90</item>
....
<item>50</item>
</string-array>
</resources>
MainAtivty中添加按钮监听
# 代码
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activty{
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**/
CameraPreview mPreview = new CameraPreview(this);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
/*为按钮绑定点击监听
* 点击设置按钮时,显示设置菜单
*/
Button buttonSetting = (Buntton) findViewById(R.id.button_settings);
buttonSettings.setOnclickListener(new View.OnclickListener(){
@Override
public void onClick(View v){
getFragmentManager().beginTransaction().replace(R.id.camera_preview, new SettingsFragment()).addToBackStack(null).commit();
}
});
}
}
相机获取
# 原因:部分设置参数的数据集为相机支持的参数集,需要调用函数获取
首先要打开相机
# 代码
/* 通过getParameters() 获取相机参数
* 将相机参数保存到静态成员变量mParameters中
*/
import android.hardware.Camera;
static Camera mCamera;
static Camera.Parameters mParameters;
public static void passCamera(Camera amera){
mCamera = camera;
mParameters = camera.getParameters(); // 获取相机参数
}
动态加载
# 使用情况:preference.xml文件中 标签<ListPreference/>属性不全
- 只有 android:key 和 android:title等常用选项
- 没有 entries 和 entryValues [此处需要动态加载]
# 代码
/* 以 动态加载 预览分辨率 为例
* 加载方法 ((ListPreference的实例名).setEntries(A) 和 ((ListPreference的实例名).setEntries(A)
* 参数要求 A 为 字符序列 CharSequence[]
* 分辨率存储方式:List<Camera.Size>
* 调用set方法以前需要对数据集做相应的类型转换
*/
import android.preference.ListPreference;
import java.util.ArrayList;
import java.util.List;
public static final String KEY_PREF_PREV_SIZE = "preview_size";
private void loadSurpportedPreviewSize(){
cameraSizeListToListPreference(mParameters.getSurpportedPreviewSizes(),"preview_size");
}
private void cameraSizeListToListPreference(List<Camera.Size> list, String key){
List<String> stringList = new ArrayList<>();
for(Camera.Size size : list){
String stringSize = size.width + "X" + size.height;
stringList.add(stringSize);
}
stringListToListPreference(stringList,key);
}
private void stringListToListPreference(List<String> list, String key){
final CharSequence[] charSeq = list.toArray(new CharSequence[list.size()]);
ListPreference listPref = (ListPreerence)getPreferenceScreen().findPreference(key);
listPref.setEntries(charSeq);
listPref.setEntryValues(charSeq);
}
# 加载时间:设置菜单创建时加载
在onCreate()中调用加载方法[loadSurpportedPreviewSize()...]
添加相机 [in MainActivity]
# 添加前调整:修改CameraPreview的相机实例获取方法。返回正在使用的相机
public Camera getCameraInstance(){
if(mCamera == null){
try{
mCamera = Camera.open();
}catch(Exception e){
Log.d(TAG,"camera is not avaliable");
}
}
return mCamera;
}
#在MainActivity 中按钮监听添加之间 插入代码 获取相机
SettingsFragment.passCamera(mpreview.getCameraInstance());
GPS权限声明 in AndroidManifest.xml
# 代码:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
默认值添加 - 静态
# 加载方法:PreferenceManager.setDefaultValues(this,R.xml.preferences,false)
- 方法意义:xml文件中有的ListPreference的android:defaultValue属性设置的有效值
这种情况下依然需要java代码进行加载工作
- 参数:false表示 如果key已有value值则不会进行任何操作
否则设置value为xml文件中的指定值
- 代码调用位置 : MainActivity的onCreate()适当位置添加
默认值添加 - 动态
# 方案:SettingFragment中创建方法 setDefault()达到效果 最后再Activty中调用即可
# 原则:首先找到“相机预览分辨率”的value值,如果值为空则指定默认值,否则返回
# 代码
Public static void setDefalut(SharedPreferences sharedPref){
String valPreviewSize = sharedPrefs.getString(KEY_PREF_PREV_SIZE, null);
if(valPreviewSize == null){
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(KEY_PREF_PREV_SIZE, getDefaultPreviewSize());
...// 相机其他参数的默认值设置
editor.apply();
}
}
/* 相机本身是有默认值的
* 只是我们的偏好设置中还没有设置这个默认值
* 因此我们可以获取到相机的默认值,然后构造成为偏好设置中的格式
* 将这个值指定为value就可以了。
*/
private static String getDefaultPreviewSize(){
Camera.Size previewSize = mParameters.getPreviewSize();
return previewSize.width + "x" + previewSize.height;
}
... //其他参数的getDefalutXXX()方法
APP启动时自动加载偏好
# 方案:在SettingsFragment中创建init()方法,负责设置相机;
在MainActivity的onCreate()中,在设置完静态和动态默认值后调用init()方法,完成相机设置。
# SettingFragment 代码添加
import android.content.SharePreferences;
public static void init(SharePreferences sharedPref){
setPreviewSize(sharedPref.getString(KEY_PREF_PREV_SIZE,""));
...//其他的setXXX()方法
mCamera.stopPerview();//停止预览
mCamera.setParameters(mOarameters);//应用修改
mCamera.startPreview();//开始预览
}
private static void setPreviewSize(String value){
String[] split = value.split("X");
mParameters.setPreviewSize(Integer.parseInt(split[0]),Integer.parseInt(split[1]));
}
...//其他的setXXX()方法
# MainActivity 调用
SettingsFragment.init(PreferenceManager.getDefaultSharedPreferences(this));
条目值变化后的立即应用设置
# 方案:监听条目value的变化 [监听Preference变化]
1.SettingFragment 添加监听接口
2.SettingFragment 添加监听事件
# 添加监听接口:
public class SettingsFragment extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener
# 添加监听事件
/* 书写监听事件的回调函数 onSharedPreferenceChanged
* 在 onResume() 和 onPause() 进行相应调用 实现对应功能
*/
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
switch(key){
case KEY_PREF_PREV_SIZE:
setPreviewSize(sharedPreferences.getString(key, ""));
break;
case ...
...
}
/*预览更新*/
mCamera.stopPreview();
mCamera.setParameters(mParameters);
mCamera.startPreview();
}
@Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
设置菜单中显示ListPreference当前值
# 方案:为summary赋值
1. 在settingFragment中添加对应方法
2. 在合适位置进行方法调用 [onCreate() 或者 onSharedPreferenceChanged()中]
# 方法添加
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) {
// 为summary赋值
pref.setSummary(((ListPreference) pref).getEntry());
}
}
# 方法调用 SettingFragment
~ 在Oncreate()中添加 : 最后添加 initSummary(getPreferenceScreen());
~ 在onSharedPreferenceChanged()中 : 最开始添加updatePrefSummary(findPreference(key));