Android 4.4相机代码分析

模式切换控件

CameraControls是相机界面下面的控制栏。

camera_controls.xml中的第一行

布局文件中有一项是

ModuleSwitcher继承自RotateImageView,说明它是一个可旋转的图片,implements  OnClickListener, OnTouchListener 说明它继承了这两个接口。继承这2个接口和它继承自哪个类没关系,只是表明它实现了这个接口,可以当做这个接口使用。例如实现了OnClickListener接口,就必须定义OnClick函数,就表示它可以作为SetOnClickListener的监听器。

ModuleSwitchListener是模式改变的监听器,这个接口定义在ModuleSwitcher类中,表示它的调用者可以实现这个接口,把自己注册给ModuleSwitcher,当模式改变的时候,可以通知到调用者。

private AnimatorListener mHideAnimationListener;表示这个Listener可以监听动画的消息。而此接口由Animation类实现。

ModuleSwitcher定义了2个构造函数,是因为它的父类定义了2个构造函数,构造函数的参数应该和父类保持一致,且应先调用super()的构造函数。

context就是Activity,context.getResources()就是这个应用的资源,context.getResources().getDimensionPixelSize()就是从资源中获取像素尺寸的值。

mIndicator是个Drawable,可以直接从资源中获取context.getResources().getDrawable(),显示在当前模式的地方。

initializeDrawables()初始化了所有模式的图片,只调用一次。给mDrawIds和mModuleIds 2个全局数组赋值。

onDraw()在绘制时调用,这里绘制了一下mIndicator,Drawable可以直接绘制,不需要通过资源或id,也不需要通过ImageView,先setBounds,再draw就可以了。

initPopup()初始化popup。

getParent(),每个view都可以调用这个函数,来获取自己的parent。

LayoutInflater的作用类似于findViewById,不同的是LayoutInflater用来查找layout文件夹下的布局文件。

LayoutInflater.from(getContext())获取当前应用的布局文件。

LayoutInflater.inflate()是把布局文件实例化成一个View对象,而不是马上显示出来,需要显示的时候,调用SetContentView(View view)显示。

LayoutInflater.from(getContext()).inflate(R.layout.switcher_popup, (ViewGroup) getParent());这句话就是把这个布局文件加入底下控制栏中。

mParent.findViewById(R.id.content);而这个布局文件的控件id为content,所以这句话获取到的是这个xml形成的View。

LayoutParams 是层的参数,层的位置,对齐方式等,每个view都有自己的LayoutParams。

mPopup.getLayoutParams()获取了popup的位置大小等参数。

content.addView,因为content是个LinearLayout,所以可以向里面添加视图。

new LinearLayout.LayoutParams 是新建一个位置尺寸信息。

MeasureSpec封装了父布局对子布局的布局要求,

MeasureSpec.makeMeasureSpec(mParent.getWidth(), MeasureSpec.AT_MOST) 表示最多能达到这个宽度

mPopup.measure(MeasureSpec.makeMeasureSpec(mParent.getWidth(), MeasureSpec.AT_MOST),
                MeasureSpec.makeMeasureSpec(mParent.getHeight(), MeasureSpec.AT_MOST));

这句话的意思是,popup的宽度,最多为父控件的宽度,高度,最多为父控件的高度。

mPopup.getLocationOnScreen(),mPopup.getHeight(),mPopup.getWidth() 获取在屏幕上的坐标,高度,宽度。

mParent.setOnTouchListener(this);就是向父控件注册一个函数,当父控件被触摸时,调用自己的onTouch()函数。onTouch()里就是去关闭popup。

showSwitcher(),显示切换popup。

layoutPopup(),当外界条件改变时,重新设置popup的尺寸,位置等。

mPopup.layout(),设置popup的位置,尺寸。

setTranslationX()设置水平方向的移动距离。

onLayout()在层改变时调用。

 

设置提示控件 id:on_screen_indicators,配置:menu_indicators.xml

CameraControls.java,是底下控制栏

camera_preferences.xml中存储了所有Camera的设置项。

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

CameraPreference是设置项的基类,是一个抽象类,所有具体的设置项都派生自CameraPreference。

具体的设置项有ListPreference(列表类型),PreferenceGroup(有一些子设置项)

派生自ListPreference的有CountDownTimerPreference,IconListPreference,

更下层的派生类又有RecordLocationPreference,MoreSettingAdapter等等。

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

每种不同类型的CameraPreference检测不同的属性Attr,这些在所有子类的java中处理。

a.recycle()是指a的内容已经使用完,系统可以回收a占用的内存了。

declare-styleable是给自定义组件添加自定义属性用的,自定义组件总有些和平台组件不一样的属性,这时就用到自定义属性了。

例如,CameraPreference是自定义组件,这就为CameraPreference定义了title属性,属性的类型是string。

由于CameraPreference是个抽象类,所有继承自它的子类都可以定义title属性。例如lIstPreference就可以。

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CameraPreference, 0, 0);这是在构造函数中,获取这个类的属性,所有这个类支持的属性都放在a中了。

mTitle = a.getString(R.styleable.CameraPreference_title);

R.styleable.CameraPreference_title是由系统生成的,是指所有继承自Camerareference的类的title属性。a.getString()就是获取title属性的值。而每个CameraPreference的子类必须定义title属性,否则就会报错。

PreferenceGroup也是一个控件,它中间可以包含其他的设置项。它本身也是一个设置项。它有一些指向子设置项的指针,可以通过函数访问它的子项。

ListPreference是列表型设置项。

a.getTextArray(R.styleable.ListPreference_entries)是获取entries属性的值,值是字符串array。

entries,entryvalues是写到底层文件中的值,labels。

ListPreference中只存储了value的值,而其他的index,entry,label都是根据value来获取。

可以根据需要去显示entry或label,都是可以显示出来的字符串,没有本质上的区别。在这里,label是大写字母的,显示在圆形菜单里。entry是小写字母,显示在列表菜单里。

ListPreference是负责存储数据的,它决定了显示什么数据,但具体是显示成列表还是圆形菜单,它却不管。所以ListPreference还是数据层面的,不属于ui。

IconListPreference继承自ListPreference,是带图标的列表菜单。

CameraSettings是相机设置项的总的接口,其他模块获取设置项的信息,都可以通过CameraSetings。

getPreferenceGroup()是获取PreferenceGroup,切换模式或切换前后摄像头时调用。

有些设置项是否支持,是根据底层hardware层或profile来获取的,CameraSetting也提供了接口供其他模块调用。CameraSetting在设置项中扮演了Control的角色。

initPreference()是初始化所有的preference,去掉一些不支持的设置项,或一些不支持的设置值。

去掉这些之后,剩下的就可以用于界面显示了。

upgradeLocalPreferences(),根据版本号的不同,做略微的调整,保证能够兼容之前的版本。

restorePreferences(),恢复默认设置。

ComboPreferences是用来向文件写入设置的值的,也用来读取。前后摄写的是不同的文件,有些设置项来说,前后摄是一致的,这样的设置项是global,被写入第3个文件。类中类editor提供了修改设置项的接口。

 

CameraActivity

MyOrientationEventListener,方向监听器。

 

PhotoUI,管理所有照相界面的UI流程,但不负责显示成什么样子。

mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
然后就调用onSurfaceTextureAvailable()函数。

DecodeTask解码任务。

mRenderOverlay用来显示菜单的层,mFlashOverlay显示拍好照之后的动画,mPreviewCover显示预览之前那一帧,mTextureView显示预览图,mOnScreenIndicators显示控制栏的提示图标,mShutterButton拍照按钮,mSwitcher前后摄切换按钮,mCameraControls底下控制栏。

updatePreviewAspectRatio()更新预览比例。从其他应用进相机时,控制栏使用review_module_control.xml,和常规xml有点不同。showPopup()显示更多设置的弹出式界面。

 

PieRenderer,继承自OverlayRenderer,是个渲染器。ZoomRenderer也是个渲染器。渲染器最主要就是onDraw函数,在onDraw()里面绘制。

RenderOverlay是个层,可以在它上面进行渲染。

PieItem

PhotoMenu

PieController

PreviewGestures预览手势

CameraControls底下控制栏

FocusOverlayManager对焦管理,所有方式的拍照都要通过这个类。

SurfaceTexture可以从camera获取图像流,但不是马上显示出来。

PhotoController是一套接口,由PhotoModule实现这个接口,PhotoUI调用。

LocationManager位置管理

ModuleSwitcher模式切换选择框

MediaSaveService媒体保存服务

Storage存储相关,把媒体写进媒体库

 

和底层相关的类:CameraProxy mCameraDevice相机设备。Parameters mParameters相机参数。 CameraInfo info 相机信息。

CameraModule是一套接口,有3个类继承自它。

PhotoModule保存了所有照相模式下的数据,它把所有的Module管理起来。mOnMediaSavedListener监听媒体保存好的消息。MainHandler主线程,处理各种消息。setCameraParametersWhenIdle如果调用不成功,则每秒钟检测一次。resetExposureCompensation()每次切换摄像头,把曝光值归零。ShutterCallback拍照回调。onBackPressed()按返回键。

 

关于预览和显示

TextureView mTextureView;这是用来显示预览的类。

SurfaceTexture mSurfaceTexture;也是和预览相关,但它接受到图像之后,不需要马上显示出来。

mTextureView.setSurfaceTextureListener(this);监听预览改变的消息。
mTextureView.addOnLayoutChangeListener(mLayoutListener);监听层改变的消息。通常从应用中设置项改变。
mTextureView.getTransform(mMatrix);设置预览的大小

SurfaceTextureSizeChangedListener mSurfaceTextureSizeListener;用来监听Texture改变的。

预览改变的消息有:onSurfaceTextureAvailable,Destroy,Update,SizeChange。

 

触屏消息传递

PhotoUI创建PreviewGesture。

预览界面点击消息  PreviewGestures -> mTapListener -> PhotoUI.onSingleTapUp() -> mController.onSingleTapUp() -> PhotoModule.onSingleTapUp() -> FocusOverlayManager.onSingleTapUp()

点击下面控制栏的按钮  mMenuButton.setOnClickListener

 

全景拍照代码:

WideAnglePanoramaModule Module。onPreviewUIReady UI准备好了。configMosaicPreview 配置预览,停止预览,配置渲染器,并开启预览。MosaicJpeg 全景图片。init 初始化。mOnFrameAvailableRunnable 新起的一个线程,处理frame上来的消息。全景有2种状态,预览viewfinder和拍照moasic。

 

WideAnglePanoramaUI 全景UI。

MosaicPreviewRenderer 全景渲染器。

MosaicFrameProcessor 全景进度显示。

MosaicJpeg 全景jpeg图片。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值