前言
这里对UI的各元素进行分析。
UI界面
在该界面能够看到的元素有:
- ShutterManager
- ModePiker
- ThumbnailManager
- SettingManager
- PickerManager
- IndicatorManager
只有ShutterManager构造函数中使用super(context, VIEW_LAYER_SHUTTER);其余的都是调用super(context);
ViewManager默认的构造函数指定layout是VIEW_LAYER_NORMAL,所以这几个view都在同一个layout
public ViewManager(Camera context) { this(context, VIEW_LAYER_NORMAL); }
基本元素
TwoStateImageView
TwoStateImageView只提供了两个方法:
- setEnabled(boolean enabled)
- enableFilter(boolean enabled) 控制setAlpha 1.0f/0.4f
子类:
- PickerButton
- FlashPickerButton
- RotateAnimationImageView
- SelfRotateImageView
- ShutterButton
继承关系图:
RotateImageView
RotateImageView实现动画形式旋转ImageView。实现了setOrientation(int degree, boolean animation) 接口,提供了setBitmap(Bitmap bitmap) ,getDegree()方法。
不错的设计是, 在setBitmap()中先把bitmap转换成较小的thumbnail bitmap ,再生成TransitionDrawable或者BitmapDrawable。
生成TransitionDrawable之后通过onDraw()绘制动画过程。这个以后进一步学习
组合关系图
ViewManager
通过这个类图可以看到,每个feature对应的view都定义单独的ViewManager。(一共16个)
ViewManager中定义了abstract getView(),继承的子类中只需要实现该方法,通常是inflate() xml layout文件,并通过Camera的addView()方法加入到对应的view layer即可。(另外一篇文档有整个过程的描述)
ShutterManager
ShutterManager负责管理ShutterButton简介
shutter button负责监听click,long click事件,并通过内部自定义接口OnShutterButtonListener向外通知shutter button focus/click/long pressed 事件。
在ShutterManager中作为属性。
/** * A button designed to be used for the on-screen shutter button. * It's currently an {@code ImageView} that can call a delegate when the * pressed state changes. */
实现
Overrides: performClick() in View 监听button click
Overrides: drawableStateChanged() in ImageView 实现button focus
implements View.OnLongClickListener
在drawableStateChanged中,有注释到写到,为了保证物理按键,轨迹球,touch event都有相同的事件时序,通过post方法调整了touch events的时序。注释及代码如下:
// When pressing the physical camera button the sequence of // events is: // focus pressed, optional camera pressed, focus released. // We want to emulate this sequence of events with the shutter // button. When clicking using a trackball button, the view // system changes the drawable state before posting click // notification, so the sequence of events is: // pressed(true), optional click, pressed(false) // When clicking using touch events, the view system changes the // drawable state after posting click notification, so the // sequence of events is: // pressed(true), pressed(false), optional click // Since we're emulating the physical camera button, we want to // have the same order of events. So we want the optional click // callback to be delivered before the pressed(false) callback. // // To do this, we delay the posting of the pressed(false) event // slightly by pushing it on the event queue. This moves it // after the optional click notification, so our client always // sees events in this sequence: // pressed(true), optional click, pressed(false) post(new Runnable() { @Override public void run() { callShutterButtonFocus(pressed); } });
layout文件
res/layout-land/camera_shutter_photo_video.xml
res/layout-port/camera_shutter_photo_video.xml
<style name="ShutterButton"> <item name="android:layout_height">@dimen/shutter_size</item> <item name="android:layout_width">@dimen/shutter_size</item> <item name="android:scaleType">center</item> <item name="android:clickable">true</item> <item name="android:focusable">true</item> </style>
加载到主界面
由ShutterManager类的show()完成。
通过ViewGroup com.android.camera.Camera.getViewLayer(int layer)
case ViewManager.VIEW_LAYER_SHUTTER: viewLayer = mViewLayerShutter;
ModePicker
ModePicker中定义了10种模式;
设置,高亮当前模式;
通过内部接口类OnModeChangedListener向外通知listener;
加载layout文件。
该类只负责View,没有任何修改preference,parameter的行为
public static final int MODE_PHOTO = 0; public static final int MODE_HDR = 1; public static final int MODE_FACE_BEAUTY = 2; public static final int MODE_PANORAMA = 3; public static final int MODE_MAV = 4; public static final int MODE_ASD = 5; public static final int MODE_SMILE_SHOT = 6; public static final int MODE_BEST = 7; public static final int MODE_EV = 8; public static final int MODE_VIDEO = 9;
layout文件
res/layout-land/mode_picker.xml
res/layout-port/mode_picker.xml
PickerManager
PickerButton onClick
PickerButton通过内部定义的Listener,通知监听者PickerManager,再通知PickerManager的监听者Camera。以下是相关的interface.
PickerButton在向listener通知click事件的同时,会更新preference.
public interface Listener { boolean onPicked(PickerButton button, String key, String newValue); }
public interface PickerListener { boolean onCameraPicked(int camerId); boolean onFlashPicked(String flashMode); boolean onStereoPicked(boolean stereoType); }