简体   繁体   中英

Remove padding in horizontal progress bar

In our application we need an indeterminate progress bar, like so:

进度条应该如何

We can achieve this by setting a negative margin on the ProgressBar, like this:

<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}" />

BUT because ConstraintLayout does not support negative margins, it will look like this:

带填充的进度条

OK, the negative margin was a hack. Let's replace it with a different hack, shall we? Let's introduce our custom view CustomProgressBar , which extends ProgressBar and overrides its onDraw method, like this:

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

But all of this smells like bad code. There has to be a better solution! What would you recommend?

Solution that feels less like a hack: Wrap a huge ProgressBar in a smaller FrameLayout . That way the FrameLayout constrains its height, but the ProgressBar still shows in full.

<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>

Another way to do this is to use a Guideline and center ProgressBar between the parent top and the guideline.

<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" />

I encountered the same problem as well. And like you said, I come across numerous solutions which all seem like a hack that might break something else down the line. With that said, I came across one solution which is to use this library instead for progress bar.

One thing to note is, it tells you to integrate it by adding:

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

However, when I used this, it gave me an error from an Android support library for Floating Action Bar. So I'll recommend you to use this instead:

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

A sample code snippet on how I used it:

<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"/>

Hope this helps!

A dirty workaround I did was set the height of the ProgressBar closely to the to stroke width like so:

Progress bar:

<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" />

Progress 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">
        <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>

Which looked like this:

在此处输入图片说明

Use inside Linearlayout and you will success, the simple way

 <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>

You declared your view without any explicit height so it's height is being picked from the pre-defined style.

<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/progressBarStyleHorizontal" will be searched in current theme and is stored in attrs.xml file. Since this defined by the platform it will obtain it's the value from there. As of writing this answer, I'm on android platform 29 and searching "?android:attr/progressBarStyleHorizontal" gives the following results

➜  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 

Opening one of the files which contain "progressBarStyleHorizontal" you will see minHeight defined in the style and is equal to 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>

This is the cause of the extra padding you are getting. You can fix it by giving your view height and a scaleY value like below

<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" />

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM