【问题标题】:Remove padding in horizontal progress bar删除水平进度条中的填充
【发布时间】:2017-03-24 16:55:17
【问题描述】:

在我们的应用程序中,我们需要一个不确定的进度条,如下所示:

我们可以通过在 ProgressBar 上设置负边距来实现这一点,如下所示:

<ProgressBar
    android:id="@+id/progressbar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:indeterminate="true"
    android:marginTop="-7dp"
    android:visibility="@{loading ? View.VISIBLE : View.GONE}" />

但是因为 ConstraintLayout 不支持负边距,它看起来像这样:

好的,负边距是一个hack。让我们用不同的 hack 替换它,好吗?让我们介绍一下我们的自定义视图CustomProgressBar,它扩展了ProgressBar 并覆盖了它的onDraw 方法,如下所示:

@Override
protected void onDraw(Canvas canvas) {
    int marginTop = dpToPx(7);
    canvas.translate(0, -marginTop);
    super.onDraw(canvas);
}

但所有这些都像是糟糕的代码。必须有更好的解决方案! 你会推荐什么?

【问题讨论】:

    标签: java android android-studio layout android-constraintlayout


    【解决方案1】:

    您声明的视图没有任何明确的高度,因此它的高度是从预定义的样式中选取的。

    <ProgressBar
        android:id="@+id/progressbar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:indeterminate="true"
        android:marginTop="-7dp"
        android:visibility="@{loading ? View.VISIBLE : View.GONE}" />
    

    "?android:attr/progressBarStyleHorizo​​ntal" 将在当前主题中搜索并存储在 attrs.xml 文件中。由于这是由平台定义的,它将从那里获得它的价值。在撰写此答案时,我在 android 平台 29 上搜索“?android:attr/progressBarStyleHorizo​​ntal”会得到以下结果

    ➜  values 
    pwd
    /Users/vihaanverma/Library/Android/sdk/platforms/android-29/data/res/values
    ➜  values 
    grep -rin "progressBarStyleHorizontal" . 
    ./themes_device_defaults.xml:126:        <item name="progressBarStyleHorizontal">@style/Widget.DeviceDefault.ProgressBar.Horizontal</item>
    ./themes_device_defaults.xml:857:        <item name="progressBarStyleHorizontal">@style/Widget.DeviceDefault.Light.ProgressBar.Horizontal</item>
    ./themes.xml:272:        <item name="progressBarStyleHorizontal">@style/Widget.ProgressBar.Horizontal</item>
    ./themes_holo.xml:263:        <item name="progressBarStyleHorizontal">@style/Widget.Holo.ProgressBar.Horizontal</item>
    ./themes_holo.xml:626:        <item name="progressBarStyleHorizontal">@style/Widget.Holo.Light.ProgressBar.Horizontal</item>
    ./public.xml:148:  <public type="attr" name="progressBarStyleHorizontal" id="0x01010078" />
    ./themes_material.xml:258:        <item name="progressBarStyleHorizontal">@style/Widget.Material.ProgressBar.Horizontal</item>
    ./themes_material.xml:635:        <item name="progressBarStyleHorizontal">@style/Widget.Material.Light.ProgressBar.Horizontal</item>
    ./styles_material.xml:1010:        <item name="progressBarStyle">?attr/progressBarStyleHorizontal</item>
    ./attrs.xml:684:        <attr name="progressBarStyleHorizontal" format="reference" />
    ➜  values 
    

    打开包含“progressBarStyleHorizo​​ntal”的文件之一,您将看到样式中定义的 minHeight 等于 16dp。

    <style name="Widget.Material.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
        <item name="progressDrawable">@drawable/progress_horizontal_material</item>
        <item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal_material</item>
        <item name="minHeight">16dip</item>
        <item name="maxHeight">16dip</item>
    </style>
    

    这是您获得额外填充的原因。您可以通过给出视图高度和如下所示的 scaleY 值来修复它

    <ProgressBar
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:indeterminate="true"
        android:scaleY="5"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    

    【讨论】:

      【解决方案2】:

      在Linearlayout里面使用,你会成功的,方法很简单

       <LinearLayout
              android:layout_width="match_parent"
              android:background="#efefef"
              android:layout_height="wrap_content">
      
              <ProgressBar
                  android:id="@+id/progressBar"
                  android:layout_width="fill_parent"
                  android:layout_height="wrap_content"
                  android:indeterminate="true"
                  android:visibility="gone"
                  android:layout_marginTop="-7dp"
                  android:layout_marginBottom="-7dp"
                  style="@style/Widget.AppCompat.ProgressBar.Horizontal"
                  />
      
          </LinearLayout>
      

      【讨论】:

        【解决方案3】:

        感觉不像黑客的解决方案:将一个巨大的 ProgressBar 包裹在一个较小的 FrameLayout 中。这样FrameLayout 会限制其高度,但ProgressBar 仍会完整显示。

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="4dp">
        
            <ProgressBar
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="match_parent"
                android:layout_height="32dp"
                android:layout_gravity="center" />
        
        </FrameLayout>
        

        【讨论】:

        • 另一种解决方案是
        • 太糟糕了,我们只需要为这么简单的事情做这件事。
        【解决方案4】:

        我所做的 dirty 解决方法是将 ProgressBar 的高度设置为接近笔画宽度,如下所示:

        进度条:

        <ProgressBar
            android:id="@+id/pb_loading_progress"
            style="@style/Widget.AppCompat.ProgressBar.Horizontal"
            android:layout_width="match_parent"
            android:layout_height="2.1dp"
            android:layout_below="@id/tb_browser"
            android:max="100"
            android:progressDrawable="@drawable/style_browser_progress_drawable"
            android:visibility="invisible" />
        

        进度可绘制:

        <?xml version="1.0" encoding="utf-8"?>
        <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:id="@android:id/background">
                <shape android:shape="line">
                    <stroke
                        android:width="2dp"
                        android:color="@color/colorPrimary" />
                </shape>
            </item>
            <item android:id="@android:id/progress">
                <clip
                    android:clipOrientation="horizontal"
                    android:gravity="left">
                    <shape android:shape="line">
                        <stroke
                            android:width="2dp"
                            android:color="@color/white" />
                    </shape>
                </clip>
            </item>
        </layer-list>
        

        看起来像这样:

        【讨论】:

        • 对我来说这是一个很好的答案。无需使用 -paddings 或 sth 来处理布局本身。当您将值添加到维度 xml 时,这更容易理解。 +1
        • 这不是只适用于确定的,而不是不确定的吗? OP 谈到不确定。
        • @John61590 OP 在他的问题中确实使用了不确定性。但是问题的重点是删除填充(因此是标题),这并不重要你的进度条是确定的还是不确定的。
        【解决方案5】:

        我也遇到了同样的问题。就像你说的那样,我遇到了许多解决方案,这些解决方案看起来都像是一个黑客,可能会破坏其他东西。 话虽如此,我遇到了一种解决方案,即使用此library 代替进度条。

        需要注意的是,它告诉你通过添加来集成它:

        compile 'me.zhanghai.android.materialprogressbar:library:1.3.0'
        

        但是,当我使用它时,它给了我一个来自浮动操作栏的 Android 支持库的错误。所以我建议你改用这个:

        compile 'me.zhanghai.android.materialprogressbar:library:1.1.7'
        

        关于我如何使用它的示例代码 sn-p:

        <me.zhanghai.android.materialprogressbar.MaterialProgressBar
            android:id="@+id/reviewProgressBar"
            style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal"
            android:layout_width="match_parent"
            android:layout_height="6dp"
            android:layout_below="@+id/my_toolbar"
            android:indeterminate="false"
            app:mpb_progressStyle="horizontal"
            app:mpb_useIntrinsicPadding="false"/>
        

        希望这会有所帮助!

        【讨论】:

          【解决方案6】:

          另一种方法是在父顶部和指南之间使用 Guideline 和 center ProgressBar。

          <ProgressBar
              android:id="@+id/progressBar2"
              style="?android:attr/progressBarStyleHorizontal"
              android:layout_width="0dp"
              android:paddingTop="-4dp"
              android:layout_height="wrap_content"
              app:layout_constraintRight_toRightOf="parent"
              app:layout_constraintLeft_toLeftOf="parent"
              app:layout_constraintBottom_toTopOf="@+id/guideline"
              app:layout_constraintTop_toTopOf="parent" />
          
          <android.support.constraint.Guideline
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:id="@+id/guideline"
              android:orientation="horizontal"
              app:layout_constraintGuide_begin="4dp" />
          

          【讨论】:

          • 谢谢,确实成功了!我通过在指南上设置app:layout_constraintGuide_begin="9dp" 并且只为进度条设置app:layout_constraintTop_toTopOf="@+id/guideline"(不是constraintBottom 或填充)来改变答案 - 有效。我仍然觉得很老套,但我觉得这是目前最好的选择。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-07-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-05
          • 2012-12-19
          相关资源
          最近更新 更多