浏览代码

添加伸缩/展开Tab列表控件

Frankensteinly 8 月之前
父节点
当前提交
4f13c81cee

+ 99 - 0
app/src/main/java/com/grkj/iscs_mc/view/widget/ExpandableTabLayout.kt

@@ -0,0 +1,99 @@
+package com.grkj.iscs_mc.view.widget
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.View
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.RelativeLayout
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.LayoutExpandableTabLayoutBinding
+import com.grkj.iscs_mc.util.ToastUtils
+import com.zhy.adapter.recyclerview.CommonAdapter
+import com.zhy.adapter.recyclerview.base.ViewHolder
+
+/**
+ * 伸缩/展开 Tab列表
+ */
+class ExpandableTabLayout(private val ctx: Context, attrs: AttributeSet) :
+    RelativeLayout(ctx, attrs) {
+
+    companion object {
+        const val DOWNWARDS = 0
+        const val UPWARDS = 1
+    }
+
+    private var mBinding: LayoutExpandableTabLayoutBinding
+    private var isCollapse = true
+
+    init {
+        val root = View.inflate(ctx, R.layout.layout_expandable_tab_layout, this)
+        mBinding = LayoutExpandableTabLayoutBinding.bind(root)
+
+        val attrSet = ctx.obtainStyledAttributes(attrs, R.styleable.ExpandableTabLayout)
+
+        val direction = attrSet.getInt(R.styleable.ExpandableTabLayout_expand_direction, 0)
+        if (direction == 1) {
+            mBinding.ivAction.rotation = 180f
+        }
+
+        val interactive = attrSet.getBoolean(R.styleable.ExpandableTabLayout_interactive, true)
+        // TODO tab下划线
+
+        val title = attrSet.getString(R.styleable.ExpandableTabLayout_expand_title)
+        title?.let {
+            mBinding.tvTitle.text = title
+        } ?: let {
+            mBinding.tvTitle.visibility = View.GONE
+        }
+
+        attrSet.recycle()
+
+        mBinding.rvTab.adapter =
+            object : CommonAdapter<String>(
+                ctx,
+                R.layout.item_rv_expandable_tab,
+//                mutableListOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56","57", "58", "59", "60", "61")
+                mutableListOf()
+            ) {
+                override fun convert(holder: ViewHolder, t: String, position: Int) {
+                    holder.getView<ImageView>(R.id.iv_icon).setImageResource(R.mipmap.safety_helmet)
+                    holder.setText(R.id.tv_name, "安全帽($t)")
+                    holder.setOnClickListener(R.id.root) {
+                        ToastUtils.tip("点击了$t")
+                    }
+                }
+            }
+        mBinding.rvTab.isNestedScrollingEnabled = false
+
+        mBinding.ivAction.setOnClickListener {
+            if (isCollapse) {
+                mBinding.root.layoutParams = mBinding.root.layoutParams.apply {
+                    height = ctx.resources.getDimensionPixelSize(R.dimen.expandable_tab_expand_height)
+                }
+                mBinding.root.requestLayout()
+
+                val layoutManager = GridLayoutManager(ctx, 5)
+                mBinding.rvTab.layoutManager = layoutManager
+
+                mBinding.llContainer.orientation = LinearLayout.VERTICAL
+            } else {
+                mBinding.root.layoutParams = mBinding.root.layoutParams.apply {
+                    height = ctx.resources.getDimensionPixelSize(R.dimen.expandable_tab_collapse_height)
+                }
+
+                val layoutManager = LinearLayoutManager(ctx)
+                layoutManager.orientation = LinearLayoutManager.HORIZONTAL
+                mBinding.rvTab.layoutManager = layoutManager
+
+                mBinding.llContainer.orientation = LinearLayout.HORIZONTAL
+            }
+            isCollapse = !isCollapse
+
+            mBinding.ivAction.rotation = if (isCollapse) 0f else 180f
+        }
+    }
+}

+ 31 - 0
app/src/main/res/layout/item_rv_expandable_tab.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root"
+    android:layout_width="wrap_content"
+    android:layout_height="31dp"
+    android:orientation="vertical"
+    android:paddingHorizontal="@dimen/common_spacing_small">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="28dp"
+        android:gravity="center"
+        android:orientation="horizontal">
+
+        <ImageView
+            android:id="@+id/iv_icon"
+            android:layout_width="15dp"
+            android:layout_height="wrap_content" />
+
+        <TextView
+            android:id="@+id/tv_name"
+            style="@style/CommonTextView"
+            android:layout_marginLeft="@dimen/common_spacing_small" />
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/iv_indicator"
+        android:layout_width="match_parent"
+        android:layout_height="3dp"
+        android:background="@color/main_color" />
+</LinearLayout>

+ 40 - 0
app/src/main/res/layout/layout_expandable_tab_layout.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="#3e6aa5">
+
+    <ImageView
+        android:id="@+id/iv_action"
+        android:layout_width="@dimen/common_icon_size"
+        android:layout_height="@dimen/common_icon_size"
+        android:layout_alignParentRight="true"
+        android:layout_marginVertical="@dimen/common_spacing"
+        android:layout_marginRight="@dimen/common_spacing_small"
+        android:background="@mipmap/expand" />
+
+    <LinearLayout
+        android:id="@+id/ll_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_toLeftOf="@id/iv_action"
+        android:orientation="horizontal">
+
+        <TextView
+            android:id="@+id/tv_title"
+            style="@style/CommonTextView"
+            android:layout_marginLeft="@dimen/common_spacing_small"
+            android:layout_marginTop="12dp"
+            android:layout_marginBottom="@dimen/common_spacing_small" />
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/rv_tab"
+            style="@style/CommonRecyclerView"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="@dimen/common_spacing_small"
+            android:layout_marginTop="2dp"
+            android:layout_marginRight="@dimen/common_spacing"
+            android:orientation="horizontal" />
+    </LinearLayout>
+</RelativeLayout>

二进制
app/src/main/res/mipmap/expand.png


二进制
app/src/main/res/mipmap/safety_helmet.png


+ 9 - 0
app/src/main/res/values/attrs.xml

@@ -29,4 +29,13 @@
         <attr name="paint_color" format="color" />
         <attr name="stroke_width" format="integer" />
     </declare-styleable>
+
+    <declare-styleable name="ExpandableTabLayout">
+        <attr name="expand_direction">
+            <flag name="upwards" value="0x00000000" />
+            <flag name="downwards" value="0x00000001" />
+        </attr>
+        <attr name="interactive" format="boolean" />
+        <attr name="expand_title" format="string" />
+    </declare-styleable>
 </resources>

+ 3 - 0
app/src/main/res/values/dimens.xml

@@ -36,6 +36,9 @@
     <dimen name="switch_thumb_stroke">2dp</dimen>
     <dimen name="switch_thumb_size">22dp</dimen>
 
+    <dimen name="expandable_tab_collapse_height">40dp</dimen>
+    <dimen name="expandable_tab_expand_height">160dp</dimen>
+
     <dimen name="menu_padding">15dp</dimen>
     <dimen name="divider_line_width">1dp</dimen>
     <dimen name="divider_line_margin">5dp</dimen>