编辑器–多功能输入框重构
类型
- 在创建富文本内容区域需要多功能输入框
- 在评论页需要展示评论输入框
现有问题
- 当前类达到了1000行…
- 嵌套页面需要太多控制功能栏显隐操作
- 编辑器回调方法中也需要控制显隐
- 布局嵌套过深不易控制
- 代码中过多findviewbyid和注册监听不美观,导致类行数过多
- 所有多媒体功能都放在InputView这个类里没有做抽象,导致类行数过多
- 评论上传图片和请求不应该放在inputView里
优化方案
优化逻辑的核心思想就是面向对象基本特征:封装、继承、多态。我打算从四个方面入手优化重构,组件的子布局拆分,各个功能的抽取例如音频视频这种都可以独立成类来管理,然后就是基类抽象和业务抽象,可以按富文本输入框和评论输入框这两个类型完全剥离开独立出来,再按照业务类型区分是主题或写作来控制富文本输入框具体内容。
布局拆分
布局按功能模块抽取
首先按照功能模块把所有view从整体布局中进行抽取,结构如下:
layout_easybar 评论功能栏
layout_richbar 富文本功能栏
layout_easybar_func 评论功能布局
layout_record_func 录音功能整体布局
layout_record_ready 录音准备布局
layout_record_go 录音开始布局
layout_record_over 录音结束布局
结构梳理
来分析一下两个类型输入框的结构,从整体来看都是一致的:上层是功能栏,中间有一个像素的线,下面是一个功能区域,用来盛放表情和音频。后面可以用代码代替,省去xml布局。
<!--功能栏-->
<LinearLayout
android:id="@+id/ll_input_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/colorGray7" />
<!--功能区域-->
<RelativeLayout
android:id="@+id/ll_input_rich_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
功能抽取
首先来梳理一下功能栏上的功能按钮,一共有表情、图片、音频、视频四种,表情和图片已做了封装处理,音频和视频占据了大量声明和逻辑的代码,我们需要对他俩进行封装。还有一些纯功能的方法我们需要进行抽取,例如软键盘的显隐控制。
- 音频功能类AudioFunc,在类的内部对音频的三个页面进行控制,并用ButterKnife将声明优化。
- 视频功能类VideoFunc,在类的内部进行回调和压缩的处理,和业务相关的抽取成接口抛出去。
- 软键盘控制类InputTools, 将控制类方法补充完整,可做成通用工具类使用。
基类抽象
因为两个类型输入框大体结构是一样的,所以我们可以在基类将总体布局定义好,然后抽取他们共用的代码部分例如功能盒子区域的显示和隐藏,在功能盒子中初始化音频和表情布局,设置统一的监听事件。
/**
* 初始化父容器
*/
private void initParent() {
setOrientation(VERTICAL);
llInputBar = new LinearLayout(activity);
llInputBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
addView(llInputBar);//添加功能栏外布局
View vLine = new View(activity);
vLine.setBackgroundResource(R.color.colorGray7);
vLine.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 1));
addView(vLine);//添加线
llInputBox = new RelativeLayout(activity);
llInputBox.setLayoutParams(new AutoRelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
addView(llInputBox);//添加盒子布局
}
/**
* 初始化功能
*/
private void initFunc() {
initBar();//初始化功能栏
initEmoji();//表情布局
initRecord();//音频布局
setBoxChildGone();//初始化将盒子内布局隐藏
getKeyBoardHeight();//获取键盘高度
}
/**
* 具体功能栏由子类填充
*/
public abstract void initBar();
子类实现
通过上述步骤后子类实现就超级简单了,经过重构后,只需要关注于bar上的点击事件的实现就好了,下面是富文本输入框的编辑器的点击事件,
@OnClick({R.id.button_emoji, R.id.button_image, R.id.button_voice, R.id.button_video, R.id.button_keyboard})
public void onClick(View view) {
switch (view.getId()) {
case R.id.button_emoji:
setVisible(flInputEmoji);
break;
case R.id.button_image:
PictureConfig.getInstance().init(ImageOptions.getImageOption()).openPhoto(activity, imageCallback);
break;
case R.id.button_voice:
setVisible(llInputRecord);
break;
case R.id.button_video:
videoFunc.clickVideo(view);
break;
case R.id.button_keyboard:
clickKeyboard();
break;
}
}
这个是两个子类各自的类结构,通篇超不过100行。
注意事项
在manifest注册文件中需要把要调用到富文本输入框的地方增加android:windowSoftInputMode="adjustResize"
将当前Activity调整为弹起时重新调整布局大小,来弹出输入框。