美文网首页
Media Module之Camera(六) 设置

Media Module之Camera(六) 设置

作者: Lemon_Home | 来源:发表于2017-06-07 17:12 被阅读172次

Camera中的设置选项,主要的是控制Camera的显示效果和动作的。下面简单从代码的角度分析一下Camera的设置。

6.1 简单介绍

此部分主要介绍的是如何快速地定位设置项的位置,找到对应key和value的值。
首先根据字符串找到相应的菜单的位置,一般都会在如图的两个文件里面,分别对应拍照和录像模式的菜单;

image.png

就拿取景模式举例:根据“取景模式”这四个字对应的name值,找到xml中的位置;

<string name="pref_camera_scenemode_title"
 msgid="5709932164781367066">"取景模式"</string>
<IconListPreference

            camera:key=*"pref_camera_scenemode_key"*

camera:defaultValue=*"@string/pref_camera_scenemode_default"*

            camera:title=*"@string/pref_camera_scenemode_title"*

            camera:icons
 =*"@array/camera_scenemode_icon"*

            camera:singleIcon=*"@drawable/ic_settings_scenemode"*

            camera:largeIcons
 =*"@array/camera_scenemode_icon"*

            camera:thumbnails=*"@array/scenemode_thumbnails"*

            camera:entries=*"@array/pref_camera_scenemode_entries"*

camera:entryValues=*"@array/pref_camera_scenemode_entryvalues"*/>

再根据其key值找到相应的value值。首先根据字符串找到在CameraSettings.java中的相应的位置,

public static final StringKEY_SCENE_MODE =
 "pref_camera_scenemode_key";

然后根据其变量KEY_SCENE_MODE在代码中查找所有相关的代码,查看相应的功能逻辑,根据相应的功能逻辑做处理;

6.2 xml文件的解析器

首先设置菜单的显示是通过xml文件布局实现的实现方式,以设置取景模式为例:

Camera界面资源文件在xml/camera_preferences.xml文件中:

<IconListPreference

            camera:key=*"pref_camera_scenemode_key"*

camera:defaultValue=*"@string/pref_camera_scenemode_default"*

            camera:title=*"@string/pref_camera_scenemode_title"*

            camera:icons
=*"@array/camera_scenemode_icon"*

            camera:singleIcon=*"@drawable/ic_settings_scenemode"*

            camera:largeIcons
=*"@array/camera_scenemode_icon"*

            camera:thumbnails=*"@array/scenemode_thumbnails"*

            camera:entries=*"@array/pref_camera_scenemode_entries"*

camera:entryValues=*"@array/pref_camera_scenemode_entryvalues"*/>

PreferenceInflater.java(src/com/android/camera/PreferenceInflater.java)是个解析器,用来解析xml中所有的设置项,包括照相机和摄像机的,具体看解析哪个xml文件,然后保存在自己的成员变量list中,list就是ArrayList类型。

inflate(mContext.getResources().getXml(resId))就是得到的就是XmlPullParser对象,这个就是该xml文件的解析器。

6.3 自定义属性的添加

declare-styleable是给自定义组件添加自定义属性用的,自定义属性在res/values/attrs.xml

<resources>

    <declare-styleable name=*"Theme.GalleryBase"*>

        <attr name=*"listPreferredItemHeightSmall"*
format=*"dimension"* />

        <attr name=*"switchStyle"*
format=*"reference"* />

    </declare-styleable>

    <!--
Camera resources below -->

    <declare-styleable name=*"CameraPreference"*>

        <attr name=*"title"*
format=*"string"* />

    </declare-styleable>

    <declare-styleable name=*"ListPreference"*>

        <attr name=*"key"* format=*"string"* />

        <attr name=*"defaultValue"* format=*"string|reference"*
/>

        <attr name=*"entryValues"* format=*"reference"*
/>

        <attr name=*"entries"*
format=*"reference"* />

        <attr name=*"labelList"*
format=*"reference"* />

    </declare-styleable>

    <declare-styleable name=*"IconIndicator"*>

        <attr name=*"icons"*
format=*"reference"* />

        <attr name=*"modes"*
format=*"reference"* />

    </declare-styleable>

    <declare-styleable name=*"IconListPreference"*>

        <!-- If a preference does not have individual icons for each entry, it
can has a single icon to represent it. -->

        <attr name=*"singleIcon"*
format=*"reference"* />

        <attr name=*"icons"*
/>

        <attr name=*"largeIcons"*
format=*"reference"* />

        <attr name=*"thumbnails"*
format=*"reference"* />

        <attr name=*"images"*
format=*"reference"* />

    </declare-styleable>

</resources>

6.4 自定义属性的使用

camera_preferences.xml及video_preferences.xml的菜单选项包括ListPreference和IconListPreference两种。ListPreference是列表型设置项,是负责存储数据的,它决定了显示什么数据,IconListPreference继承自ListPreference,是带图标的列表菜单。

下面看ListPreference如何使用自定义属性:

public  ListPreference(Context context, AttributeSet
attrs) {
        super (context,attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ListPreference,0, 0);
        mKey = CameraUtil.checkNotNull(a.getString(R.styleable.ListPreference_key));
        // We allow the defaultValue attribute to be a string or an array of
        // strings. The reason we need multiple default values is that some
        // of them may be unsupported on a specific platform (for example,
        // continuous auto-focus). In that case the first supported value
        // in the array will be used.

翻译如下:

我们允许“默认值”属性是一个字符串或数组串.
我们需要多个默认值的原因是:它们可能在特定平台上不受支持(例如,连续、自动对焦)。
在这种情况下,第一个支持的值将在数组中使用。

        int attrDefaultValue = R.styleable.ListPreference_defaultValue;
        TypedValue tv = a.peekValue(attrDefaultValue);
        if (tv != null && tv.type == TypedValue.TYPE_REFERENCE) {
            mDefaultValues = a.getTextArray(attrDefaultValue);
        } else {
            mDefaultValues = **new** CharSequence[1];
            mDefaultValues[0] = a.getString(attrDefaultValue);
        }
        setEntries(a.getTextArray(R.styleable.ListPreference_entries));
        setEntryValues(a.getTextArray(R.styleable.ListPreference_entryValues));
        setLabels(a.getTextArray(R.styleable.ListPreference_labelList));
        a.recycle();
}

在camera_preferences.xml菜单项里包含了下面信息:

packages/apps/Camera2/res/values/arrays.xml定义了菜单项成员及其键值

<!--
Camera Preferences Scene Mode dialog box entries -->

    <string-array name=*"pref_camera_scenemode_entries"* translatable=*"false"*>

        <item>@string/pref_camera_scenemode_entry_night</item>

        <item>@string/pref_camera_scenemode_entry_auto</item>

    </string-array>

 

    <string-array name=*"pref_camera_scenemode_labels"*>

        <item>@string/pref_camera_scenemode_label_night</item>

        <item>@string/pref_camera_scenemode_label_auto</item>

    </string-array>

 

    <array name=*"pref_camera_scenemode_icons"*>

        <item>@drawable/ic_sce_night</item>

        <item>@drawable/ic_sce_off</item>

    </array>

 

    <string-array name=*"pref_camera_scenemode_entryvalues"* translatable=*"false"*>

        <item>night</item>

        <item>auto</item>

    </string-array>

由这些定义,我们可以看出,Android的Camera应用程序支持几种情景模式。但是硬件并非都支持。所以最终的菜单中只会显示这几种当中底层硬件所支持的,如果硬件支持的与其中任何一种都不匹配,则不会显示出“取景模式”菜单。
注意:进入相机菜单丢失问题硬件不支持导致菜单不可见;

6.5 加载菜单项

Xml文件的内容以及解析都讲完了,下面看下是怎么把菜单项加载进去的。
Packages/apps/Camera2/src/com/android/camera/CameraSettings.java
CameraSettings是相机设置项的总的接口,里面定义了菜单设置项的KEY值,

public static final String *KEY_SCENE_MODE = "pref_camera_scenemode_key";

这些KEY值是跟camera_preferences.xml里的菜单项对应的,接着在private voidinitPreference(PreferenceGroupgroup)中添加

ListPreference sceneMode = group.findPreference(*KEY_SCENE_MODE*);

来获取键值为KEY_SCENE_MODE的菜单项,接着

if (sceneMode != null) {
    filterUnsupportedOptions(group, sceneMode, mParameters.getSupportedSceneModes());
}

函数mParameters.getSupportedSceneModes()将获取camera 硬件支持的SceneMode的项,其定义在文件Framework/base/core/java/android/hardware/camera.java中。

sceneMode相当于从camera_preferences.xml中获取的sceneMode的项,它俩之间需要做个匹配,如果camera硬件支持的项不存在或者只有一项,则就会从group中去掉sceneMode的菜单。

6.6 效果设置:

我们通过下面代码获取当前菜单项所选中的值,如果是改变值则是改变值,否则就是默认值:

mSceneMode= mPreferences.getString(CameraSettings.*KEY_SCENE_MODE*,              mActivity.getString(R.string.pref_camera_scenemode_default));

如果改变值把选中的值设置到底层:

if(CameraUtil.isSupported(mSceneMode,mParameters.getSupportedSceneModes())) {
      if (!mParameters.getSceneMode().equals(mSceneMode)) {
           mCameraDevice.setSceneDetectionCallback(null,null);
           mParameters.setSceneMode(mSceneMode);
           sceneChanged = true;
       }
}

因为KEY值都存放在SharedPreferences 里,保存Camera设置的所有值,每次启动Camera都会重新读取保存的值。

6.7 界面菜单Camera 切换模式功能:

CameraControls是相机界面下面的控制栏,在其xml文件里显示自定义view项

<com.android.camera.ui.ModuleSwitcher
           android:id="@+id/camera_switcher"
           style="@style/SwitcherButton"
           android:layout_gravity="bottom|left"
           android:layout_marginBottom="-11dip"
      android:contentDescription="@string/accessibility_mode_picker"
/>

Packages/apps/Camera2/src/com/android/camera/ui/ModuleSwitcher.java
此类定义了ModuleSwitchListener接口

public  interface  ModuleSwitchListener {
        public void onModuleSelected(int i);
        public void onShowSwitcherPopup();
    }

ModuleSwitchListener是模式改变监听器当模式改变时通知调用者。
initializeDrawables()初始化了所有模式的图片,只调用一次,主要是给

int[] drawids = new int[numDrawIds];
int[] moduleids = new int[numDrawIds];

两个变量赋值,这两个变量主要是用于模式图标的显示。

相关文章

网友评论

      本文标题:Media Module之Camera(六) 设置

      本文链接:https://www.haomeiwen.com/subject/dphafxtx.html