3

我需要一个 UI 元素,它允许用户展开/折叠(显示/隐藏)包含可选/高级信息的视图。

我设想这是一个文本标签(例如“高级选项”、“更多/更少”)加上一个在打开和关闭之间切换的图标。我有一些可以达到目的的图标,并且元素的功能与 ToggleButton 的功能非常匹配,因此我尝试使用样式化的 ToggleButton 来解决这个问题。

这个解决方案被证明是超级丑陋的(从维护的角度来看)。我将在下面添加它作为答案。

我希望有人可以提出更好的解决方案,或者指出如何简化我的解决方案。

顺便说一句,在这个 SO Q/A中很好地解决了视图的展开/折叠动画。

4

4 回答 4

5

谢天谢地,我找到了一个更简单的方法。

我没有使用 ToggleButton(涉及 11 个资源文件来设置样式),而是使用带有 CompoundDrawable 的 TextView,然后自己管理状态。

这种方式涉及更多代码,但节省了大量资源文件。它还可以更轻松地处理多个主题,例如,在这里我根据主题为所需图标设置资源 ID:

final MainActivity ma = (MainActivity) getActivity();
if  (ma.isDarkTheme()) {
    icon_expand = getResources().getIdentifier( "ic_action_expand","drawable", ma.getPackageName() );       
    icon_collapse = getResources().getIdentifier( "ic_action_collapse","drawable", ma.getPackageName() );       
} else {
    icon_expand = getResources().getIdentifier( "ic_action_expand_light","drawable", ma.getPackageName() );     
    icon_collapse = getResources().getIdentifier( "ic_action_collapse_light","drawable", ma.getPackageName() );     
}

我在片段的 onCreate 中执行此操作。不幸的是,我必须在运行时解析图标 ID,但这似乎是它的完成方式。

我不知道为什么我的图标在这种情况下以正常大小显示,而当我将它们指定为 ToggleButton 的背景层时以双倍大小显示(这需要为我的所有图标提供 ScaledDrawable 资源)。

这是我的 onClickListener(用于 TextView):

protected OnClickListener expandCtrlListener = new OnClickListener() {
    public void onClick(View v) {
        assertTrue( v == expandCtrl );
        isExpanded = !isExpanded;
        advancedView.setVisibility( isExpanded ?  View.VISIBLE : View.GONE );
        expandCtrl.setCompoundDrawablesWithIntrinsicBounds( isExpanded ? icon_collapse : icon_expand, 0, 0, 0 );
    }
};

请注意,这些都没有显示展开/折叠的动画。这在我在问题末尾提到的文章中得到了解决。

于 2013-09-13T01:23:48.890 回答
1

正如我在问题中所写,按钮的功能与 ToggleButton 非常匹配,因此我从一个布局开始,该布局在一些文本旁边显示了一个样式化的 ToggleButton:

<RelativeLayout
    android:id="@+id/expandLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="right"
    android:layout_marginRight="12dp" >
    <ToggleButton
        android:id="@+id/expcollButton"
        style="@style/expCollToggleBtn"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checked="false"/>
    <TextView
        android:id="@+id/expandText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="8dp"
        android:layout_toRightOf="@id/expcollButton"
        android:text="Show Options" />
</RelativeLayout>

样式(在 styles.xml 文件中)如下所示。这会使按钮文本无效并指向背景可绘制对象。

<style name="expCollToggleBtn">
    <item name="android:background">@drawable/expcoll_btn_toggle_bg_light</item>
    <item name="android:textOn"></item>
    <item name="android:textOff"></item>
    <item name="android:disabledAlpha">?android:attr/disabledAlpha</item>
</style>

背景drawable是一个layer-list xml文件,它指向另一个drawable(也许有办法摆脱这个文件,直接指向下面的选择器?)

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+android:id/background" android:drawable="@android:color/transparent" />
    <item android:id="@+android:id/toggle" android:drawable="@drawable/expcoll_btn_toggle" />
</layer-list>

选择器列出了打开/关闭的图像:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="false" android:drawable="@drawable/ic_action_expand" />
    <item android:state_checked="true" android:drawable="@drawable/ic_action_collapse" />
</selector>

现在,第一个复杂情况是这会导致按钮/图像过大。我已经为所有像素密度提供了合适的图像,所以我不确定为什么会发生这种情况,但解决方案是缩放图像。

不幸的是,这似乎需要为每个图像提供一个 ScaledDrawable。我实际上有四个图像,因为我愚蠢地决定在我的应用程序中支持浅色和深色主题。所以我需要其中的四个。

<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_action_expand"
    android:scaleGravity="center"
    android:scaleHeight="50%"
    android:scaleWidth="50%" 
/>

另外,请注意 ScaledDrawables 中存在一个错误,在此处描述,因此需要加以考虑。

最后,由于我试图支持两个主题,我还需要选择器和图层列表文件的多个副本,并且需要向 attrs.xml 文件添加属性。在这一点上,我有 11 个 XML 文件(加上所有密度的 10 个图像文件)全部用于一个非常普通的按钮。

这不可能!

于 2013-09-12T20:04:05.650 回答
0

一个简单的展开折叠代码

   //show/hide boxes panel
    var expansion: Boolean = false

    expand_up.setOnClickListener {
        if (!expansion) {
            expand_up.setImageResource(R.drawable.collapse)
            boxes_panel.visibility = View.VISIBLE
            expansion = true
        }
        else{
            expand_up.setImageResource(R.drawable.expand)
            boxes_panel.visibility = View.GONE
            expansion = false
        }
    } 
于 2021-03-17T12:11:47.400 回答
-2

有一个图书馆。
它被称为 SAExpandableButton,你可以在这里找到它

于 2017-10-12T12:34:35.427 回答