材质滑块和范围滑块工具提示并不总是可见

ave*_*raj 11 android material-components-android

我希望保持工具提示值始终可见,并且工具提示的文本应该背景透明。我尝试了https://github.com/material-components/material-components-android/blob/master/docs/components/Slider.md但没有办法让工具提示始终可见

<com.google.android.material.slider.Slider
        android:id="@+id/slider_sound_sensitivity"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:valueFrom="0.0"
        android:valueTo="100.0"
        android:layout_marginTop="@dimen/_8sdp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.508"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/txt_sound_sensitivity" />

<com.google.android.material.slider.RangeSlider
        android:id="@+id/range_humidity_in_percentage"
        style="@style/Myslider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:valueFrom="0.0"
        android:valueTo="100.0"
        android:layout_marginTop="@dimen/_16sdp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/txt_humidity_in_percentage"
        app:values="@array/initial_slider_values" />
Run Code Online (Sandbox Code Playgroud)

Mar*_*osP 16

从 Material Design 1.6.0 及更高版本 (\'com.google.android.material:material:1.6.0\') 开始:

\n

@S.Gissel 在他的回答中建议了一个官方属性app:labelBehavior="visible",如下所示:

\n
<com.google.android.material.slider.Slider\n    app:labelBehavior="visible"/>\n\n<com.google.android.material.slider.RangeSlider\n    app:labelBehavior="visible"/>\n
Run Code Online (Sandbox Code Playgroud)\n

来自 Material Design 1.5.0 及以下版本:

\n

没有公共 API 可以使用\xc2\xa0app:labelBehavior\xc2\xa0 属性保持工具提示始终可见。下面是使用反射的解决方法:

\n
    \n
  1. 创建 Slider/RangeSlider 的子类并重写该onDraw(@NonNull Canvas canvas)方法并调用该setSliderTooltipAlwaysVisible(Slider slider)方法以保持工具提示始终可见,如下所示:

    \n

    对于滑块:

    \n
     public class MyCustomSlider extends Slider {\n\n public MyCustomSlider(@NonNull Context context) {\n     super(context);\n     init();\n }\n\n public MyCustomSlider(@NonNull Context context, @Nullable AttributeSet attrs) {\n     super(context, attrs);\n     init();\n }\n\n public MyCustomSlider(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n     super(context, attrs, defStyleAttr);\n     init();\n }\n\n private void init(){\n     //in case this View is inside a ScrollView you can listen to OnScrollChangedListener to redraw the View\n     getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {\n         @Override\n         public void onScrollChanged() {\n             invalidate();\n         }\n     });\n }\n\n @Override\n protected void onDraw(@NonNull Canvas canvas) {\n     super.onDraw(canvas);\n     setSliderTooltipAlwaysVisible(this);\n }\n\n public static void setSliderTooltipAlwaysVisible(Slider slider){\n\n     try\n     {\n         Class<?> baseSliderCls = Slider.class.getSuperclass();\n         if (baseSliderCls != null) {\n\n             Method ensureLabelsAddedMethod = baseSliderCls.getDeclaredMethod("ensureLabelsAdded");\n             ensureLabelsAddedMethod.setAccessible(true);\n             ensureLabelsAddedMethod.invoke(slider);\n         }\n     }\n     catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {\n         e.printStackTrace();\n     }\n }\n}\n
    Run Code Online (Sandbox Code Playgroud)\n

    对于范围滑块:

    \n
     public class MyCustomRangeSlider extends RangeSlider {\n\n public MyCustomRangeSlider(@NonNull Context context) {\n     super(context);\n     init();\n }\n\n public MyCustomRangeSlider(@NonNull Context context, @Nullable AttributeSet attrs) {\n     super(context, attrs);\n     init();\n }\n\n public MyCustomRangeSlider(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n     super(context, attrs, defStyleAttr);\n     init();\n }\n\n private void init(){\n     //in case this View is inside a ScrollView you can listen to OnScrollChangedListener to redraw the View\n     getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {\n         @Override\n         public void onScrollChanged() {\n             invalidate();\n         }\n     });\n }\n\n @Override\n protected void onDraw(@NonNull Canvas canvas) {\n     super.onDraw(canvas);\n     setSliderTooltipAlwaysVisible(this);\n }\n\n public static void setSliderTooltipAlwaysVisible(RangeSlider slider){\n\n     try\n     {\n         Class<?> baseSliderCls = RangeSlider.class.getSuperclass();\n         if (baseSliderCls != null) {\n\n             Method ensureLabelsAddedMethod = baseSliderCls.getDeclaredMethod("ensureLabelsAdded");\n             ensureLabelsAddedMethod.setAccessible(true);\n             ensureLabelsAddedMethod.invoke(slider);\n         }\n     }\n     catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {\n         e.printStackTrace();\n     }\n }\n}\n
    Run Code Online (Sandbox Code Playgroud)\n

    这里的关键点是在调用private void ensureLabelsAdded()后使用 Reflection 来调用 BaseSlider 类的私有方法。super.onDraw(canvas)

    \n
  2. \n
  3. 在您的 xml 中使用上述自定义滑块,如下所示:

    \n
    <?xml version="1.0" encoding="utf-8"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"\nandroid:layout_width="match_parent"\nandroid:layout_height="match_parent"\nxmlns:app="http://schemas.android.com/apk/res-auto">\n\n<my.package.name.MyCustomSlider\n    style="@style/Widget.App.Slider"\n    app:labelBehavior="floating"\n    android:id="@+id/slider_sound_sensitivity"\n    android:layout_width="0dp"\n    android:layout_height="wrap_content"\n    android:valueFrom="0.0"\n    android:valueTo="100.0"\n    android:layout_marginTop="@dimen/_8sdp"\n    app:layout_constraintTop_toTopOf="parent"\n    app:layout_constraintStart_toStartOf="parent"\n    app:layout_constraintEnd_toEndOf="parent"/>\n\n<my.package.name.MyCustomRangeSlider\n    style="@style/Widget.App.Slider"\n    app:labelBehavior="floating"\n    android:id="@+id/range_humidity_in_percentage"\n    android:layout_width="0dp"\n    android:layout_height="wrap_content"\n    android:valueFrom="0.0"\n    android:valueTo="100.0"\n    android:layout_marginTop="@dimen/_16sdp"\n    app:layout_constraintTop_toBottomOf="@+id/slider_sound_sensitivity"\n    app:layout_constraintStart_toStartOf="parent"\n    app:layout_constraintEnd_toEndOf="parent"\n    app:values="@array/initial_slider_values" />\n\n</androidx.constraintlayout.widget.ConstraintLayout>\n
    Run Code Online (Sandbox Code Playgroud)\n
  4. \n
\n

注意:如果您仍然需要在 Material Design 1.6.0 中使用此解决方法,则必须将上述 xml 属性更改为app:labelBehavior="floating"\ app:labelBehavior="visible"nMyCustomSlider/MyCustomRangeSlider。

\n

您的自定义样式是否style="@style/Widget.App.Slider"在 styles.xml 文件中定义,如下所示:

\n
   <style name="Widget.App.Slider" parent="Widget.MaterialComponents.Slider">\n        <item name="materialThemeOverlay">@style/ThemeOverlay.App.Slider</item>\n        <item name="labelStyle">@style/Widget.App.Tooltip</item>\n    </style>\n\n    <style name="ThemeOverlay.App.Slider" parent="">\n        <item name="colorPrimary">@android:color/holo_red_light</item>\n        <item name="colorOnSurface">@android:color/holo_red_light</item>\n    </style>\n\n    <style name="Widget.App.Tooltip" parent="Widget.MaterialComponents.Tooltip">\n        <item name="android:textAppearance">@style/TextAppearance.App.Tooltip</item>\n        <!--This is the Tooltip Background Color. In case you don\'t want a background change it to @android:color/transparent -->\n        <item name="backgroundTint">@android:color/holo_orange_light</item>\n    </style>\n\n    <style name="TextAppearance.App.Tooltip" parent="TextAppearance.MaterialComponents.Tooltip">\n        <item name="android:textColor">@android:color/holo_blue_light</item>\n    </style>\n
Run Code Online (Sandbox Code Playgroud)\n

在上面的 xml 中,您可以通过更改 backgroundTint 颜色将工具提示背景更改为透明颜色: <item name="backgroundTint">@android:color/transparent</item>。

\n

带有透明背景的工具提示始终可见的结果:

\n

slider_transparent_tooltip

\n

带有工具提示的结果在不透明背景下始终可见:

\n

slider_non_transparent_tooltip

\n

  • 这个解决方案乍一看非常棒。我实现了它,但在滚动视图内,工具提示保留,而其余部分则滚动。:-/ (2认同)