短视频 SDK Android(手势操作)

TAVWidgetContentView 是所有挂件(贴纸、画中画等组件,后文全部统称挂件)手势操作的视图,挂件选中、取消选中、拖动、拖移位置拦截、旋转角度拦截等操作都可以在该类中进行。

相关产品
短视频 SDK 产品页,含版本规格、价格与购买入口。

一、相关接口类

接口类名 描述
TAVEditor SDK 操作入口类。
TAVWidgetContentView SDK 手势操作封装基类。

二、挂件编辑过程

当手势点击某个挂件时,TAVWidgetContentView 会调用 ITAVWidgetEditViewFactory 中的方法去创建挂件编辑视图,目前内置的基础编辑视图有两种:

·贴纸基础编辑视图:TAVStickerEditView

·画中画基础编辑视图:TAVPipEditView

挂件边框和操作按钮的绘制都在相应的 EditView 进行绘制,可以通过继承相应的 EditView 对不同挂件绘制不同的编辑框。

三、主要接口介绍

接口名 描述
ITAVWidgetEventListener 挂件操作的事件接口,挂件激活、取消激活、拖动、点击等事件都会在该接口回调。
ITAVWidgetTouchOutsideListener 没有点中任何挂件的回调。
ITAVWidgetEditViewFactory 创建自定义挂件编辑视图的工厂。
ITAVWidgetMoveLimitProvider 挂件移动策略提供者。

四、主要方法介绍

方法名 描述
setTouchable 设置是否可以进行手势操作。
setNoFocusGestureEnabled 设置是否可以直接拖动挂件,无需先选中挂件。
setWidgetType 设置可以操作的挂件类型。
setMoveRegionRect 设置挂件拖动区域。
activeWidget 激活指定挂件。
resignCurrentActive 取消激活当前激活的挂件。
addWidgetEventListener 添加挂件操作事件监听。
setWidgetTouchOutsideListener 设置没有点到挂件的回调。
setEditViewFactory 设置自定义的挂件编辑视图工厂。如果认为 SDK 内部默认的编辑视图不足以满足业务需求,可以自行实现创建编辑视图。
setSyncWithRender 设置操作挂件是否与渲染同步。
setMoveLimitProvider 设置挂件移动的限制策略,可为每个挂件指定移动限制方式和移动限制区域。

五、设置自定义的贴纸编辑视图

1. 先自行实现贴纸编辑视图。

public class MyStickerEditView extends TAVStickerEditView { public MyStickerEditView(Context context, TAVSticker sticker) { super(context, sticker); // 自己的逻辑 // 如果需要获取挂件在View中的顶点位置,可以使用 getVertexPoints 方法获得 } }

2. 然后为 TAVWidgetContentView 设置挂件编辑视图工厂:

public class MyWidgetContentView extends TAVWidgetContentView { public MyWidgetContentView(Context context) { super(context); setEditViewFactory(new ITAVWidgetEditViewFactory() { @Override public TAVStickerEditView createStickerEditView(TAVSticker sticker) { return new MyStickerEditView(context, sticker); } @Override public TAVPipEditView createPipEditView(TAVPip pip) { // 不需要自定义画中画编辑视图时,返回 SDK 默认实现 return new TAVPipEditView(context, pip); } }); } }

3. 在 TAVEditor initWithPreview 的时候传入自定义的 TAVWidgetContentView:

// 通过 TAVMagicFactory 创建编辑器实例 TAVEditor editor = TAVMagicFactory.createEditor(); TAVEditorConstants.PreviewParam param = new TAVEditorConstants.PreviewParam(); param.videoView = findViewById(R.id.preview_container); // FrameLayout,承载预览画面 // 传入自定义的TAVWidgetContentView param.contentView = new MyWidgetContentView(context); param.loopPlay = true; param.autoPlay = true; editor.initWithPreview(param);

六、监听挂件手势事件

public class MyWidgetContentView extends TAVWidgetContentView { public MyWidgetContentView(Context context) { super(context); // 添加挂件事件监听 addWidgetEventListener(new ITAVWidgetEventListener() { @Override public void onWidgetClick(TAVWidget widget, MotionEvent event) { // 挂件被点击 } @Override public void onWidgetTouchBegin(TAVWidget widget, MotionEvent event) { // 挂件开始拖动 } @Override public void onWidgetTouchEnd(TAVWidget widget, MotionEvent event) { // 挂件拖动结束 } @Override public void onWidgetAdjust(TAVWidget widget, TAVWidgetOperationMode operationMode) { // 挂件正在拖动 } @Override public void onWidgetActive(TAVWidget widget) { // 挂件被激活编辑 } @Override public void onWidgetResign(TAVWidget widget) { // 挂件被取消激活 } }); }}

七、挂件手势层可配置项

TAVWidgetContentView 的公开配置能力,可在自定义子类的构造函数中调用。

挂件类型常量(位掩码)

常量 值 说明
WIDGET_TYPE_NONE 0 不响应任何挂件。
WIDGET_TYPE_STICKER 1 贴纸。
WIDGET_TYPE_PIP 2 画中画(1 << 1)。
WIDGET_TYPE_ALL 3 贴纸 + 画中画,默认值。

手势事件常量(位掩码)

常量 值 说明
EVENT_TYPE_NONE 0 不响应任何手势。
EVENT_TYPE_DRAG 1 拖动。
EVENT_TYPE_DOUBLE_ZOOM_ROTATE 2 双指缩放/旋转。
EVENT_TYPE_SINGLE_ZOOM_ROTATE 4 单指缩放/旋转。
EVENT_TYPE_CLICK 8 点击。
EVENT_TYPE_ALL 15 全部事件,默认值。

配置方法

方法 说明 默认
bindEditor(TAVEditor editor) 绑定编辑器并注册贴纸/画中画观察者;重复调用抛 IllegalStateException。 –
setWidgetType(int widgetType) / getWidgetType() 参与手势的挂件类型,取值用 WIDGET_TYPE_* 组合;设置后立即刷新编辑视图可见性。 WIDGET_TYPE_ALL
setEventType(int eventType) 响应的手势事件类型,取值用 EVENT_TYPE_* 组合。 EVENT_TYPE_ALL
setTouchable(boolean touchable) 是否响应触摸。 true
setNoFocusGestureEnabled(boolean enabled) 无焦点手势开关。 false
setSyncWithRender(boolean syncWithRender) 是否与渲染同步。 true
setMoveRegionRect(Rect rect) 限制挂件可拖动区域。 –
setMoveLimit(TAVWidgetMoveLimit moveLimit) 统一设置挂件移动限制模式。 –
setMoveLimitProvider(ITAVWidgetMoveLimitProvider provider) 按挂件分别指定移动限制模式与限制区域。 –

状态查询与激活

方法 说明
activeWidget(TAVWidget widget) / activeWidget(int id) 激活指定挂件,进入可编辑状态。
resignCurrentActive() 取消当前挂件的激活状态。
getActiveWidget() / getActiveEditView() 获取当前激活的挂件与其编辑视图。
getWidgetEditView(int id) 按挂件 ID 取对应的编辑视图。
forEachEditView(TAVConsumer<TAVWidgetEditView> consumer) 遍历所有编辑视图。

可重写钩子(子类覆盖)

方法 说明
positionInterceptor(float x, float y) 挂件拖动位置拦截,返回最终绘制坐标。
rotateInterceptor(float degree) 旋转角度拦截,返回最终角度。
scaleInterceptor(float scale) 缩放比例拦截,返回最终比例;覆盖后可能导致最大/最小缩放限制失效。
shouldShowEditView() 控制编辑视图是否展示。
updateWidgetEditViewVisibility() 编辑视图可见性更新逻辑。
isTouchOnSticker(TAVSticker sticker, float x, float y) / isTouchOnPip(TAVPip pip, float x, float y) 自定义命中判定。

挂件状态与移动限制枚举

枚举 取值 说明
TAVWidgetEditMode DEFAULT / ACTIVE / INACTIVE 默认状态 / 激活(可交互编辑) / 非激活(不可交互)。
TAVWidgetMoveLimit LIMIT_CENTER_POINT / LIMIT_VERTEX 限制挂件中心点 / 限制挂件顶点。

public class MyWidgetContentView extends TAVWidgetContentView { public MyWidgetContentView(Context context) { super(context); // 只让贴纸响应拖动与点击 setWidgetType(WIDGET_TYPE_STICKER); setEventType(EVENT_TYPE_DRAG | EVENT_TYPE_CLICK); // 移动时限制顶点,避免拖出画面 setMoveLimit(TAVWidgetMoveLimit.LIMIT_VERTEX); } @Override protected PointF positionInterceptor(float x, float y) { // 返回拦截处理后的坐标 return super.positionInterceptor(x, y); }}

八、高级操作

需要重写 TAVWidgetContentView 相关方法。

九、自定义 TAVWidgetContentView 展示逻辑

@Override protected boolean shouldShowEditView() { // 增加自己的展示判断逻辑 return super.shouldShowEditView(); } @Override protected void updateWidgetEditViewVisibility() { if (null != currentEditView && null != currentWidget) { final boolean shouldShow = shouldShowEditView(); // 根据展示条件修改TAVWidgetEditView可见性 } }

十、操作拦截

TAVWidgetContentView 提供了下列接口实现对挂件的拦截:

接口名 描述
positionInterceptor 挂件位置拦截。
rotateInterceptor 挂件旋转角度拦截。
scaleInterceptor 挂件缩放拦截。

示例代码展示了通过重写 positionInterceptor 方法来实现移动时的位置吸附效果:

@Override protected PointF positionInterceptor(float x, float y) { PointF translation = new PointF(x, y); PointF[] previewPoints = currentEditView.computeVertexPoints(translation); float previewCenterX = (previewPoints[0].x + previewPoints[2].x) / 2f; float previewCenterY = (previewPoints[0].y + previewPoints[2].y) / 2f; float viewCenterX = getWidth() / 2f; float viewCenterY = getHeight() / 2f; float deltaX = viewCenterX – previewCenterX; float deltaY = viewCenterY – previewCenterY; // 小于10像素吸附 if (Math.abs(deltaX) <= 10) { translation.x += deltaX; } if (Math.abs(deltaY) <= 10) { translation.y += deltaY; } return translation; }

赞 (0)
上一篇 4天前
下一篇 4天前