【自定义CollapsingToolbarLayout】监听可折叠标题的偏移/自己实现可折叠标题
苗锦洲
0
28
220
0
虽然官方已经实现了自动折叠展开以及标题的平移和缩放,但是有个新的需求,当标题需要参与到共享元素动画时,就需要知道或者计算出标题的实时偏移量,然后改变你需要改变的控件。
友情提示:此篇文章大约需要阅读 9分28秒
# 直接贴代码
```
//获取collapsing_tool_bar_layout的collapsingTextHelper,由于不是public的,因此使用java的反射来获取
val field = collapsing_tool_bar_layout.javaClass.getDeclaredField("collapsingTextHelper")
field.isAccessible = true
val collapsingTextHelper = field.get(collapsing_tool_bar_layout) as CollapsingTextHelper
//同理,获取collapsingTextHelper中的currentBounds
val fieldCurrentBounds = collapsingTextHelper.javaClass.getDeclaredField("currentBounds")
fieldCurrentBounds.isAccessible = true
val currentRectF = fieldCurrentBounds.get(collapsingTextHelper) as RectF
//自定义折叠Toolbar,使TextView随着AppBarLayout高度的变化而改变位置
//AppBarStateChangeListener是自定义继承自AppBarLayout.OnOffsetChangedListener的抽象类
app_bar_layout.addOnOffsetChangedListener(object : AppBarStateChangeListener() {
override fun onExpandPercentChange(state: State, expandPercent: Float) {
Log.d("CUSTOM_COLLAPSED_TITLE", "currentRectF:${JSON.toJSONString(currentRectF)}")
val layoutParams = LinearLayout.LayoutParams(text_view_symbol.layoutParams)
layoutParams.setMargins(
currentRectF.left.toInt(), layoutParams.topMargin, layoutParams.rightMargin,
(DensityUtils.dp2px(15f) * expandPercent).toInt() +
//因为textview大小为18sp,与折叠ToolbarLayout的20sp不一致,为了在折叠后尽量保持在一条水平先上
(DensityUtils.dp2px(2.5f) * (1 - expandPercent)).toInt()
)
// text_view_symbol.setTextSize(20-((20-18)*expandPercent))
text_view_symbol.layoutParams = layoutParams
text_view_creator_info.alpha = expandPercent
if (expandPercent > 0.8) {
fab_add_record.show()
} else {
fab_add_record.hide()
}
}
override fun onStateChanged(appBarLayout: AppBarLayout?, state: State?, i: Int) {
when (state) {
State.COLLAPSED -> {
XLog.d("RecordListActivity, State.COLLAPSED")
// fab_add_record.hide()
}
State.EXPANDED -> {
XLog.d("RecordListActivity, State.EXPANDED")
collapsing_tool_bar_layout?.title = null
text_view_symbol.visibility = View.VISIBLE
text_view_title.visibility = View.VISIBLE
}
State.SCROLLING -> {
collapsing_tool_bar_layout?.title = " " + viewModel.recordType.title
text_view_title.visibility = View.INVISIBLE
}
else -> {
//ignore
}
}
}
})
```
附AppBarStateChangeListener代码
```
abstract class AppBarStateChangeListener : AppBarLayout.OnOffsetChangedListener {
enum class State {
EXPANDED, COLLAPSED, SCROLLING, IDLE
}
private var mCurrentState = State.IDLE
override fun onOffsetChanged(appBarLayout: AppBarLayout?, i: Int) {
val expandPercent = 1f + (i / (appBarLayout?.totalScrollRange ?: -i).toFloat())
when {
i == 0 -> {
if (mCurrentState != State.EXPANDED) {
mCurrentState = State.EXPANDED
onStateChanged(appBarLayout, mCurrentState, i)
}
}
abs(i) >= appBarLayout!!.totalScrollRange -> {
if (mCurrentState != State.COLLAPSED) {
mCurrentState = State.COLLAPSED
onStateChanged(appBarLayout, mCurrentState, i)
}
}
else -> {
mCurrentState = State.SCROLLING
onStateChanged(appBarLayout, State.SCROLLING, i)
}
}
Log.d("AppBarLayout.onOffsetChanged","$i/${appBarLayout?.totalScrollRange},${mCurrentState},${expandPercent}")
onExpandPercentChange(mCurrentState, expandPercent)
}
abstract fun onExpandPercentChange(state: State, expandPercent: Float)
abstract fun onStateChanged(appBarLayout: AppBarLayout?, state: State?, i: Int)
}
```
# 问题解决过程
1. 查看CollapsingToolbarLayout的源码,发现CollapsingTextHelper,利用反射获取到collapsingTextHelper
2. 查看CollapsingTextHelper的源码,发现currentBounds,再利用反射获取到currentBounds
3. 监听AppBarLayout高度变化,然后获取currentBounds.left等信息,然后实时更改TextView的位置
评论
楼主暂时不想被别人评论哦~
已自动恢复阅读位置、日/夜间模式参数