Remova o preenchimento vertical da ProgressBar horizontal

127

Por padrão, o ProgressBar tem um certo preenchimento acima e abaixo da própria barra. Existe uma maneira de remover esse preenchimento para ter apenas a barra no final?

abergmeier
fonte
7
Conforme observado em outros tópicos, a configuração maxHeightnão funciona.
abergmeier
android:minHeight="4dp"
Sam Chen

Respostas:

71

Eu uso o seguinte como uma solução alternativa para esse problema.

android:layout_marginBottom="-8dp"
android:layout_marginTop="-4dp"
Stephen Wan
fonte
1
Eu não precisava de layout_marginBottom.
AlikElzin-kilaka
11
android:layout_marginTop="-6dp"trabalhou para mim. Gostaria de saber se é dependente do dispositivo? Eu só testei no Xperia Z1
Thorbjørn Kappel Hansen
2
@ ThorbjørnKappelHansen Depende do dispositivo. O Galaxy S6 e uma margem superior de -6dp não funcionam como desejado.
Muhammad Abdul-Rahim
1
Eu acho que as margens dependeriam do tamanho da barra de progresso e da versão do Android.
Noel
2
usando Framelayout(como em esta resposta é melhor solução e não depende do tamanho do telefone / tipo de versão / os
koceeng
57

Foi assim que usei a resposta de Juozas:

altura do meu ProgressBaré 4dp. Então eu criei um FrameLayoutcom altura 4dp e defina o layout_gravityde ProgressBarcomo center. Funciona como um encanto.

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="4dp">

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

</FrameLayout>
penduDev
fonte
23
É uma boa ideia, mas seu código não funcionou para mim no Android 7.0 usando a barra de progresso da biblioteca de suporte. O bar ficou mais fino, mas ainda tinha estofamento no topo.
Sam
4
@ Sam Basta fazer o ProgressBar, por exemplo, height = 100dp. Devido ao FrameLayout, ele ainda permanece em 4dp, mas a barra parece mais espessa.
Megaetron
5
Não está funcionando na API 24+. A barra fica mais fina, não importa o tamanho que a definimos.
Mauker
36

Acabei usando uma biblioteca personalizada para resolver esse problema. A maioria das outras soluções funciona, mas os resultados não são consistentes em vários dispositivos.

MaterialProgressBar

  • Aparência consistente no Android 4.0 ou superior.
  • Tonalidade correta nas plataformas.
  • Capaz de remover o preenchimento intrínseco da estrutura ProgressBar.
  • Capaz de ocultar a faixa da estrutura ProgressBar horizontal.
  • Usado como um substituto para o framework ProgressBar.

Para adicionar como uma dependência gradle:

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

Para adicionar uma ProgressBar sem preenchimento intrínseco ao seu layout:

<me.zhanghai.android.materialprogressbar.MaterialProgressBar
    android:layout_width="wrap_content"
    android:layout_height="4dp"
    android:indeterminate="true"
    app:mpb_progressStyle="horizontal"
    app:mpb_useIntrinsicPadding="false"
    style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal" />

app:mpb_useIntrinsicPadding="false"faz o truque. Para mais detalhes, consulte a página do GitHub .

Binoy Babu
fonte
Primeiro, tentei evitar adicionar outra dependência apenas para remover algum preenchimento. Mas todas as outras soluções falharam de uma ou de outra maneira / versão e, no final, foram 3 minutos para fazê-lo funcionar! Obrigado.
ToniTornado
32
Uma biblioteca inteira apenas para corrigir o preenchimento em uma exibição. Caminho a percorrer Google.
Denny
Você pode usar @ style / Widget.AppCompat.ProgressBar.Horizontal para o exposto acima (dependendo da configuração)
ror
31

Se alguém ainda precisar de ajuda, tente o seguinte:

<androidx.core.widget.ContentLoadingProgressBar
    android:id="@+id/progress"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="@style/Widget.AppCompat.ProgressBar.Horizontal"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="@+id/guideline"
    android:indeterminate="true"
    android:visibility="visible"
    app:layout_constraintBottom_toTopOf="@+id/guideline" />

Aqui, a barra de progresso está dentro do ConstraintLayout , e os constraintTop_toTopOf e constraintBottom_toTopOf atributos devem ser aplicados ao mesmo elemento (neste caso, é diretriz).

Ali_Waris
fonte
4
Isso deve ser marcado como a resposta correta, pois funciona perfeitamente!
Philio
1
Esta é a resposta certa! Você é compatível com todos os dispositivos (que não são fornecidos com margem negativa) e versões do Android (que não são fornecidas pela solução de layout de quadro). Além disso, você não precisa fazer todo o trabalho necessário importando os drawables do sistema para o aplicativo (o que não fornece uma interface do usuário consistente em todo o sistema para todas as versões do Android).
Vaios
2
@Ali_Waris obrigado por postar uma resposta, estou interessado em entender esta solução como incapaz de fazê-la funcionar. Você poderia expandir a resposta para incluir o ConstraintLayout e a diretriz da resposta?
scottyab 9/09/19
Qual é a orientação aqui? Para onde vai?
iamgopal 31/07
16

É possível desenhar ProgressBar verticalmente centralizado dentro de um pai que cortaria o preenchimento. Como o ProgressBar não pode se desenhar maior que o pai, precisamos criar um pai grande para colocar dentro de uma exibição de recorte.

<FrameLayout
    android:id="@+id/clippedProgressBar"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="4dp"
    tools:ignore="UselessParent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="16dp"
        android:layout_gravity="center_vertical">

        <ProgressBar
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:indeterminate="true"/>

    </FrameLayout>

</FrameLayout>
Juozas Kontvainis
fonte
1
Isso funcionou no Android 7.0, mas não resultou em nenhuma barra de progresso no meu Sony Xperia M executando o Android 4.1.2.
Sam
@ Sam obrigado por relatar! O que você vê se alterar a altura do primeiro FrameLayout de 4dp para 48dp?
Juozas Kontvainis
A barra de progresso aparece, mas há muito preenchimento por baixo e um pouco de preenchimento acima dela.
Sam
@ Sam Atualizei minha resposta, espero que funcione de forma aceitável no seu dispositivo Sony. Se isso não ajudar, sugiro revisar a configuração do tema do aplicativo. O uso do tema Holo no KitKat deve corrigi-lo.
Juozas Kontvainis
15

Para remover o preenchimento vertical ProgressBar, você pode fazer isso

  • fixar a altura de ProgressBar
  • Use scaleY = "value" (value = height / 4) (4 é a altura padrão da barra de progresso)

O exemplo contém 1 wrap_content ProgressBar, 1 8dp ProgressBar, 1 100dpProgressBar

insira a descrição da imagem aqui

<ProgressBar
    style="?android:attr/progressBarStyleHorizontal"
    ...
    android:layout_height="8dp"
    android:scaleY="2" />
Phan Van Linh
fonte
14

Uma solução completa para esse problema seria a seguinte. Caso alguém precise de fragmentos de código, foi isso que eu fiz.

  1. Copiou todos os 8 drawables horizontais indeterminados da barra de progresso
  2. Editou os drawables usando algum manipulador de imagem e remova os paddings desnecessários
  3. Copiou o XML extraível chamado progress_indeterminate_horizontal_holo.xml da plataforma android
  4. Copiou o estilo Widget.ProgressBar.Horizontal e seus pais
  5. Defina o estilo e min_height manualmente no layout

Aqui está o arquivo progress_indeterminate_horizontal_holo.xml

<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
<item android:drawable="@drawable/progressbar_indeterminate_holo1" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo2" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo3" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo4" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo5" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo6" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo7" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo8" android:duration="50" />

Recursos de estilo copiados para o meu arquivo de estilos local.

<style name="Widget">
    <item name="android:textAppearance">@android:attr/textAppearance</item>
</style>

<style name="Widget.ProgressBar">
    <item name="android:indeterminateOnly">true</item>
    <item name="android:indeterminateBehavior">repeat</item>
    <item name="android:indeterminateDuration">3500</item>
</style>

<style name="Widget.ProgressBar.Horizontal">
    <item name="android:indeterminateOnly">false</item>
    <item name="android:indeterminateDrawable">@drawable/progress_indeterminate_horizontal_holo</item>
</style>

E, finalmente, defina a altura mínima como 4dp no meu arquivo de layout local.

<ProgressBar
    android:id="@+id/pb_loading"
    style="@style/Widget.ProgressBar.Horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:indeterminate="true"
    android:minHeight="4dp"
    android:minWidth="48dp"
    android:progressDrawable="@drawable/progress_indeterminate_horizontal_holo" />
Subin Sebastian
fonte
De onde podemos copiar o drawable mencionado na etapa 1: "1.Copiou todos os 8 drawables indeterminados da barra de progresso horizontal"?
GreenHand
3
@JeffreyLin Copiei-o deste local<your-sdk-folder>/platforms/android-17/data/res/drawable-hdpi/
Subin Sebastian
33
Não é incrível o quanto de trabalho você precisa fazer para alcançar um comportamento de bom senso que deveria vir por padrão no Android?
SpaceMonkey
1
E para design de material?
precisa saber é o seguinte
@ at Aat Eu não acho que as diretrizes materiais têm barras de progresso semelhantes. Consulte este documento: google.com/design/spec/components/…
Subin Sebastian 12/16
10

Encontrei o mesmo problema ao usar a barra de progresso com o estilo horizontal.

A causa principal é que o drawable padrão de 9 correções para a barra de progresso: (progress_bg_holo_dark.9.png) possui alguns pixels verticais transparentes como preenchimento.

A solução final que funcionou para mim: personalizar o progresso desenhável, meu código de exemplo da seguinte forma:

custom_horizontal_progressbar_drawable.xml

<?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="rectangle">
            <solid android:color="#33ffffff" />
        </shape>
    </item>
    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape android:shape="rectangle">
                <solid android:color="#ff9800" />
            </shape>
        </clip>
    </item>
    <item android:id="@android:id/progress">
        <clip>
            <shape android:shape="rectangle">
                <solid android:color="#E91E63" />
            </shape>
        </clip>
    </item>
</layer-list>

snippet de layout:

<ProgressBar
    android:id="@+id/song_progress_normal"
    style="@style/Widget.AppCompat.ProgressBar.Horizontal"
    android:layout_width="match_parent"
    android:layout_height="5dp"
    android:layout_alignParentBottom="true"
    android:progressDrawable="@drawable/custom_horizontal_progressbar_drawable"
    android:progress="0"/>
emotionfxxk
fonte
Esta é provavelmente a melhor solução. Seu código de exemplo não produziu nenhuma barra de progresso no meu Sony Xperia M executando o Android 4.1.2.
Sam
8

Um truque é adicionar margens negativas à sua barra de progresso.

Abaixo está um exemplo do código XML, supondo que ele esteja na parte superior da tela:

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

resultado do código

chinmay.d
fonte
Adicionar margens negativas resolveu o problema para mim. Obrigado!
icarovirtual 26/03/19
5

A resposta de Subin parece ser a única (atualmente) que não é um hack frágil sujeito a falhas em versões futuras do Android ProgressBar.

Mas, em vez de ter o trabalho de dividir os recursos, modificá-los e mantê-los indefinidamente, optei por usar a biblioteca MaterialProgressBar , que faz isso por nós:

<me.zhanghai.android.materialprogressbar.MaterialProgressBar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:indeterminate="true"
    android:layout_gravity="bottom"
    custom:mpb_progressStyle="horizontal"
    custom:mpb_showTrack="false"
    custom:mpb_useIntrinsicPadding="false"
    style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
/>

No build.gradle:

// Android horizontal ProgressBar doesn't allow removal of top/bottom padding
compile 'me.zhanghai.android.materialprogressbar:library:1.1.6'

Esse projeto tem uma boa demonstração que mostra as diferenças entre ele e o ProgressBar interno.

Stephen Talley
fonte
4

se alguém ainda estiver procurando uma solução - verifique este comentário

defina a altura mínima para 4 dp

   android:minHeight="4dp"

-

  <ProgressBar
    android:id="@+id/web_view_progress_bar"
    style="@style/Widget.AppCompat.ProgressBar.Horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:indeterminate="false"
    android:max="100"
    android:min="0"
    android:progress="5"
    android:minHeight="4dp"
    android:progressTint="@color/vodafone_red"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:progress="60" />
ahmed ewess
fonte
Eu prefiro esta resposta.
Sam Chen
2

Eu uso minHeight e maxHeigh. Ajuda para diferentes versões da API.

<ProgressBar
    android:id="@+id/progress_bar"
    style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:maxHeight="3dp"
    android:minHeight="3dp" />

Ele precisa usar os dois. A API 23 funciona bem com

android:layout_height="wrap_content"
android:minHeight="0dp"

Porém, versões mais baixas da API aumentam a altura da barra de progresso para maxHeight nesse caso.

Andrii Volynets
fonte
2

Tente o seguinte:

<ProgressBar
    android:id="@+id/progress_bar"
    style="@android:style/Widget.ProgressBar.Horizontal"
    android:progress="25"
    android:progressTint="@color/colorWhite"
    android:progressBackgroundTint="@color/colorPrimaryLight"
    android:layout_width="match_parent"
    android:layout_height="4dp" />

... e, em seguida, configure a barra de progresso de acordo com as suas necessidades, pois ela exibirá inicialmente uma barra de tamanho médio com uma tonalidade de progresso amarela e uma tonalidade de fundo cinza de progresso. Além disso, observe que não há preenchimento vertical.

DaveNOTDavid
fonte
2

Use assim, dentro do 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>
alizulfuqar
fonte
Funciona bem! Da próxima vez, descreva o que você codifica e quais alterações você fez. ;-)
Desenvolvedor De Jokela
1

adicionar o android: progressDrawable a uma lista de camadas definida no drawable corrigiu o problema para mim. Ele funciona mascarando a barra de progresso em um drawable personalizado

exemplo de implementação descrito em https://stackoverflow.com/a/4454450/1145905

kip2
fonte
1

Estou usando style="@style/Widget.AppCompat.ProgressBar.Horizontal"e foi bastante fácil se livrar das margens. Esse estilo é:

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

Acabei de substituir a altura mínima / máxima:

    <ProgressBar
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:indeterminate="true"
        android:minHeight="2dp"
        android:maxHeight="2dp" />
Anthony
fonte
Eu nunca foi satisified com a barra de progresso genéricos e virou-se para uma biblioteca no final: me.zhanghai.android.materialprogressbar.MaterialProgressBar
Anthony
1

Não é necessário baixar nenhum novo módulo ou até mesmo colocar um FrameLayout na barra de progresso. Estes são todos apenas hacks. Apenas 2 etapas:

No seu Whatever.xml

<ProgressBar
    android:id="@+id/workoutSessionGlobalProgress"
    android:layout_width="match_parent"
    android:layout_height="YOUR_HEIGHT"
    android:progressDrawable="@drawable/progress_horizontal"
    android:progress="0"
    <!-- High value to make ValueAnimator smoother -->
    android:max="DURATION * 1000"
    android:indeterminate="false"
    style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal"/>

progress_horizontal.xml, altere os valores como desejar.

Não gosta dos cantos arredondados?
Remover raio do canto

Não gosta das cores? Mude as cores, etc. Feito!

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="5dip" />
            <gradient
                    android:startColor="#ff9d9e9d"
                    android:centerColor="#ff5a5d5a"
                    android:centerY="0.75"
                    android:endColor="#ff747674"
                    android:angle="270"
                    />
        </shape>
    </item>

    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <gradient
                        android:startColor="#80ffd300"
                        android:centerColor="#80ffb600"
                        android:centerY="0.75"
                        android:endColor="#a0ffcb00"
                        android:angle="270"
                        />
            </shape>
        </clip>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <gradient
                        android:startColor="#ffffd300"
                        android:centerColor="#ffffb600"
                        android:centerY="0.75"
                        android:endColor="#ffffcb00"
                        android:angle="270"
                        />
            </shape>
        </clip>
    </item>

</layer-list>

Geralmente, estas são as etapas para alterar o código de qualquer coisa que você não gosta. Basta encontrar o código fonte e descobrir o que mudar. Se você seguir o código-fonte ProgressBar, encontrará um arquivo chamado progress_horizontal.xml que ele faz referência. Basicamente, como eu resolvo todos os meus problemas de XML.

Daniel Kim
fonte
0
 <ProgressBar
        android:layout_marginTop="-8dp"
        android:layout_marginLeft="-8dp"
        android:layout_marginRight="-8dp"
        android:id="@+id/progress_bar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="4dp"
        android:indeterminate="false"
        android:indeterminateTint="@color/white"
        android:max="100"
        android:paddingStart="8dp"
        android:paddingRight="0dp"
        android:progressDrawable="@drawable/progress_bg" />
mallem mahesh
fonte
0
<androidx.core.widget.ContentLoadingProgressBar
                    android:id="@+id/progressBar"
                    style="@style/Widget.AppCompat.ProgressBar.Horizontal"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:indeterminate="true"
                    android:paddingTop="2dp"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintBottom_toTopOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"/>
ZIRES
fonte
Por favor, não publique simplesmente o código. Dê algum contexto à sua resposta.
Martin Gal
0

Basta usar o Material ProgressIndicator que não possui margem oculta.

<com.google.android.material.progressindicator.ProgressIndicator
        android:id="@+id/progressBar"
        style="@style/Widget.MaterialComponents.ProgressIndicator.Linear.Indeterminate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:indicatorColor="@color/colorPrimary"
        app:trackColor="@color/colorAccent" />
devgun
fonte
-1

Uma solução simples não-truques que é compatível com qualquer versão do Android e não precisa de bibliotecas externas está fingindo ProgressBarcom dois ViewsinteriorLinearLayout . Foi assim que acabei. Parece bastante elegante e essa abordagem é bastante flexível - você pode animar de maneiras divertidas, adicionar texto etc.

Layout:

<LinearLayout
    android:id="@+id/inventory_progress_layout"
    android:layout_width="match_parent"
    android:layout_height="4dp"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/inventory_progress_value"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TextView
        android:id="@+id/inventory_progress_remaining"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

Código:

public void setProgressValue(float percentage) {
    TextView progressValue = (TextView) findViewById(R.id.inventory_progress_value);
    TextView progressRemaining = (TextView) findViewById(R.id.inventory_progress_remaining);

    LinearLayout.LayoutParams paramsValue = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    LinearLayout.LayoutParams paramsRemaining = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

    paramsValue.weight = (100 - percentage);
    paramsRemaining.weight = percentage;

    progressValue.setLayoutParams(paramsValue);
    progressRemaining.setLayoutParams(paramsRemaining);

}

Resultado (com alguma elevação adicionada):

insira a descrição da imagem aqui

Janeks Bergs
fonte
-1

A melhor solução deve ser

android:minHeight="0dp"

Nenhuma solução alternativa e funciona como um encanto.

Alex Fan
fonte
não funcionou, você pode explicar por que isso deve funcionar?
Humild_wolf 10/10/19
@humble_wolf Funcionou para mim no meu projeto anterior quando escrevi a resposta; pode depender de alguma versão específica da biblioteca? Deveria funcionar porque o motivo pelo qual existe uma barra semelhante ao preenchimento da barra de progresso não é o preenchimento real, mas existe um minHeighttamanho maior que 0 (digamos, 32dp talvez) predefinido. Ao alterar essa propriedade, você obtém uma aparência diferente.
Alex Fan
Não funcionou para mim no modo Inderminar = verdadeiro, talvez trabalhando no modo determinado. Se você realmente deseja que esta seja uma resposta, escreva a explicação em resposta com todas as condições.
Humble_wolf 12/12/19