Android实现中部布局展开/折叠(折叠为Drawable线条)
实现中部布局展开/折叠为Drawable线条的方案
嘿,刚好能帮到你!我有两个实用的方案来实现你要的这种中部展开/折叠效果,折叠后显示自定义Drawable线条而不是收去顶部,完全适配包含按钮、文本、ImageView的布局:
方案一:自定义ViewGroup实现高度渐变折叠
这个方案能实现平滑的高度过渡动画,折叠时逐渐收缩成指定的Drawable线条,展开时恢复原布局,可控性更强。
步骤1:创建自定义布局类
class CollapsibleLineLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr) { private var isExpanded = true private var originalHeight = 0 // 折叠后线条的高度,可根据需求调整 private val lineHeight = dpToPx(2) // 替换成你自己的线条Drawable private val lineDrawable = ContextCompat.getDrawable(context, R.drawable.custom_line) init { orientation = VERTICAL // 布局初始化完成后记录原高度 viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { originalHeight = measuredHeight viewTreeObserver.removeOnGlobalLayoutListener(this) } }) } // 切换展开/折叠状态 fun toggleExpandCollapse() { isExpanded = !isExpanded startHeightAnimation() } private fun startHeightAnimation() { val targetHeight = if (isExpanded) originalHeight else lineHeight ValueAnimator.ofInt(measuredHeight, targetHeight).apply { duration = 300 // 动画时长,可调整 addUpdateListener { animator -> val currentHeight = animator.animatedValue as Int layoutParams.height = currentHeight requestLayout() } start() } } override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) // 折叠状态下绘制线条Drawable if (!isExpanded) { lineDrawable?.let { drawable -> drawable.setBounds(0, 0, width, lineHeight) drawable.draw(canvas!!) } } } // dp转px工具方法 private fun dpToPx(dp: Int): Int { return (dp * resources.displayMetrics.density).toInt() } }
步骤2:在布局中使用自定义控件
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <!-- 自定义折叠布局,放在屏幕中部 --> <com.yourpackage.CollapsibleLineLayout android:id="@+id/collapsible_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp"> <!-- 你的内容元素:按钮、文本、ImageView等 --> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="操作按钮"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="折叠后会变成线条"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher"/> </com.yourpackage.CollapsibleLineLayout> <!-- 触发按钮,也可以直接给折叠布局添加点击事件 --> <Button android:id="@+id/toggle_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="切换展开/折叠" android:layout_marginTop="20dp"/> </LinearLayout>
步骤3:在Activity中添加触发逻辑
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val collapsibleLayout = findViewById<CollapsibleLineLayout>(R.id.collapsible_layout) val toggleBtn = findViewById<Button>(R.id.toggle_btn) toggleBtn.setOnClickListener { collapsibleLayout.toggleExpandCollapse() } // 也可以让折叠布局自身可点击触发 collapsibleLayout.setOnClickListener { collapsibleLayout.toggleExpandCollapse() } } }
方案二:ConstraintLayout配合过渡动画快速实现
如果不需要高度渐变,只是切换显示内容和线条,这个方案更简单快捷:
步骤1:编写布局文件
<androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 可折叠的内容布局,居中放置 --> <LinearLayout android:id="@+id/content_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintVertical_bias="0.5"> <!-- 你的内容元素 --> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="测试文本"/> </LinearLayout> <!-- 折叠后的线条View,和内容布局位置重合 --> <View android:id="@+id/collapse_line" android:layout_width="match_parent" android:layout_height="2dp" android:background="@drawable/custom_line" android:visibility="gone" app:layout_constraintTop_toTopOf="@id/content_layout" app:layout_constraintBottom_toBottomOf="@id/content_layout"/> <!-- 触发按钮 --> <Button android:id="@+id/toggle_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="切换" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" android:layout_margin="16dp"/> </androidx.constraintlayout.widget.ConstraintLayout>
步骤2:Activity中添加切换逻辑
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val contentLayout = findViewById<LinearLayout>(R.id.content_layout) val collapseLine = findViewById<View>(R.id.collapse_line) val toggleBtn = findViewById<Button>(R.id.toggle_btn) val rootLayout = findViewById<ConstraintLayout>(R.id.root_layout) toggleBtn.setOnClickListener { // 启动过渡动画 TransitionManager.beginDelayedTransition(rootLayout) if (contentLayout.visibility == View.VISIBLE) { contentLayout.visibility = View.GONE collapseLine.visibility = View.VISIBLE } else { contentLayout.visibility = View.VISIBLE collapseLine.visibility = View.GONE } } } }
额外注意点
- 自定义Drawable可以实现虚线、渐变、带圆角的线条等样式,完全适配你的UI需求
- 如果布局包含ScrollView,要注意处理滚动和折叠操作的冲突
- 可以根据需求调整动画时长、线条高度等参数,优化交互体验
内容的提问来源于stack exchange,提问作者Call Me James
相关产品推荐
相关产品推荐

