android - Android/Kotlin,如何减少此代码的重复部分
问题描述
我是库作者,必须通过覆盖 ViewGroup.onInterceptTouchEvent() 来拦截子视图的所有触摸事件。
首先,我编写了以下代码(简化):
interface touchIntercepter {
// my library set this field to intercept touch event
var touchHandler: ((MotionEvent) -> Boolean)?
}
class LinearLayoutTouchIntercepter @JvmOverloads constructor (
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
)
: touchIntercepter
, LinearLayout(context, attrs, defStyleAttr, defStyleRes)
{
override var touchHandler: ((MotionEvent) -> Boolean)? = null
override fun onInterceptTouchEvent(event: MotionEvent) = touchHandler?.invoke(event) ?: false
}
库用户可以在他们的布局 xml 文件中使用 LinearLayoutTouchInterceptor 而不是标准的 LinearLayout,然后我的库代码可以通过 touchIntercepter 接口拦截用户布局的子视图的触摸事件。
我认为如果有 ViewGroup.setOnInterceptTouchListener() 之类的东西,View.setOnClickListener() 之类的东西,那就太好了,但我发现没有。
现在的问题是,我想为 RelativeLayout、FrameLayout 和其他 ViewGroup 后代提供相同的功能。
例如,
class RelativeLayoutTouchIntercepter @JvmOverloads constructor (
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
)
: touchIntercepter
, RelativeLayout(context, attrs, defStyleAttr, defStyleRes)
{
override var touchHandler: ((MotionEvent) -> Boolean)? = null
override fun onInterceptTouchEvent(event: MotionEvent) = touchHandler?.invoke(event) ?: false
}
如您所见,所有代码都是相同的,但唯一的区别是继承 XXXXXLayout 而不是 LinearLayout。我不想复制和粘贴它们,但不知道如何减少重复。
似乎 Kotlin 泛型在这种情况下没有帮助,而 C++ 模板完美地可以帮助像这样的伪代码:
template <typename T>
class TouchInterceptorTmpl : public T
{
void onInterceptTouchEvent() override;
};
using RelativeLayoutTouchInterceptor = TouchInterceptorTmpl<RelativeLayout>;
using FrameLayoutTouchInterceptor = TouchInterceptorTmpl<FrameLayout>;
在 Kotlin 中没有办法这样做吗?
解决方案
您可以通过对接口进行具体实现并将其用作委托来减少重复。onInterceptTouchEvent
不幸的是,由于继承的工作原理,您无法避免在每个实现中重写,但您可以为您的接口创建一个扩展函数以稍微缩短该代码。
请注意,Kotlin 中的接口名称按约定大写。
设置:
interface TouchInterceptor {
var touchInterceptionHandler: ((MotionEvent) -> Boolean)?
}
class TouchInterceptorImpl: TouchInterceptor {
override var touchInterceptionHandler: ((MotionEvent) -> Boolean)? = null
}
fun TouchInterceptor.intercept(event: MotionEvent): Boolean = touchInterceptionHandler?.invoke(event) ?: false
用法:
class RelativeLayoutTouchIntercepter @JvmOverloads constructor (
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
)
: TouchInterceptor by TouchInterceptorImpl()
, RelativeLayout(context, attrs, defStyleAttr, defStyleRes)
{
override fun onInterceptTouchEvent(event: MotionEvent): Boolean = intercept(event)
}
推荐阅读
- java - 如何编写java字符串长度方法代码?
- java - Eclipse 动态 Web 项目 -> 构建路径上的源文件夹空白
- python - MySql longblob 到 python dict
- mod-rewrite - 使用 CloudFlare IPCountry + mod_rewrite 的多个国家/地区重定向
- javascript - Vs 2019 / Asp.net MVC / .Net framework 4.6.1 -> Ctrl + F5 不断导致开发计算机崩溃
- android - 如何在 kotlin 的表格视图中检查重叠信息?
- django - Django - can't update existing data in database, doesn't update
- reactjs - 如何在 React-visibility-sensor 中第一次滚动后保持元素可见?
- amazon-redshift - 从 Red-Shift 迁移到 Snowflake——将 RedShift 中的卸载转换为复制到阶段
- r - 如何正确地使用“符号”R