OR博客
【自定义CollapsingToolbarLayout】监听可折叠标题的偏移/自己实现可折叠标题
苗锦洲
创建于:2021-01-27 16:04:24
0
28
220
0
虽然官方已经实现了自动折叠展开以及标题的平移和缩放,但是有个新的需求,当标题需要参与到共享元素动画时,就需要知道或者计算出标题的实时偏移量,然后改变你需要改变的控件。
# 直接贴代码 ``` //获取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的位置
评论
楼主暂时不想被别人评论哦~