美文网首页
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