ProgressBar debajo de la barra de acción

79

Resumen de la pregunta: ¿Cómo puedo hacer una ProgressBarintegración dentro de ActionBar, como en la aplicación de Chrome?

Detalles: mire esta captura de pantalla de Chrome:

Captura de pantalla de Chrome para Android

Quiero crear una barra de acción como esta. Justo debajo de la barra de acción, hay una barra de progreso que se llena según la carga de la página. He visto este ejemplo en muchas aplicaciones, como Feedly, pero no he podido crear mi propia implementación. Intenté usar las propias API de Android para crearlo:

@Override
protected void onCreate(Bundle savedInstanceState) {
    //Request Permission to display the Progress Bar...
    this.requestWindowFeature(Window.FEATURE_PROGRESS);
            this.setWindowContentView(R.layout.activity_main)
    super.onCreate(savedInstanceState);

    this.setProgressBarIndeterminate(true);
}

Pero este código solo hace que ProgressBar se muestre sobre la barra de acción, así:

Captura de pantalla de mi aplicación

Entonces, ¿cómo puedo hacer que mi ProgressBar aparezca debajo de la barra de acción, como en la aplicación de Chrome?

zubietaroberto
fuente
posible pregunta duplicada de esta respuesta: stackoverflow.com/a/10755545/794088
petey
ya has encontrado la solución?
Eric
capturas de pantalla para mi abuela
IlyaEremin

Respuestas:

7

Este es ahora un comportamiento nativo que se puede obtener usando SwipeRefreshLayout .

Puede envolver su vista desplazable con a SwipeRefreshLayouty luego solo necesita escuchar los eventos onRefresh :

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
    swipeLayout.setOnRefreshListener(this);
    swipeLayout.setColorScheme(android.R.color.holo_blue_bright, 
            android.R.color.holo_green_light, 
            android.R.color.holo_orange_light, 
            android.R.color.holo_red_light);
}


@Override public void onRefresh() {
    new Handler().postDelayed(new Runnable() {
        @Override public void run() {
            swipeLayout.setRefreshing(false);
        }
    }, 5000);
}

En este blog se puede encontrar un tutorial sencillo y agradable .

AlexGuti
fuente
56

No estaba completamente satisfecho con la respuesta aceptada anterior, así que investigué un poco más.

El truco que creo que usaron es que recuperaron la vista superior en la jerarquía de vista llamada DecorViewy agregaron la barra de progreso allí. De esa manera, la barra de progreso se muestra tanto sobre la barra de acción como sobre el área de contenido. Tenga en cuenta que la respuesta de la SD coloca la barra de progreso en el área de contenido y 'roba' espacio del contenido real, lo que puede conducir a resultados inesperados.

Capturas de pantalla de muestra de esta implementación:

Barra de progreso

ProgressBarIndeterminate

Código

Simplemente ponga este código en el onCreatemétodo de alguna actividad y debería funcionar:

// create new ProgressBar and style it
final ProgressBar progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));
progressBar.setProgress(65);

// retrieve the top view of our application
final FrameLayout decorView = (FrameLayout) getWindow().getDecorView();
decorView.addView(progressBar);

// Here we try to position the ProgressBar to the correct position by looking
// at the position where content area starts. But during creating time, sizes 
// of the components are not set yet, so we have to wait until the components
// has been laid out
// Also note that doing progressBar.setY(136) will not work, because of different
// screen densities and different sizes of actionBar
ViewTreeObserver observer = progressBar.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        View contentView = decorView.findViewById(android.R.id.content);
        progressBar.setY(contentView.getY() - 10);

        ViewTreeObserver observer = progressBar.getViewTreeObserver();
        observer.removeOnGlobalLayoutListener(this);
    }
});

Puede jugar con el argumento de altura de LayoutParams para establecer la barra de progreso más ancha o más estrecha, pero es posible que tenga que ajustar el -10desplazamiento.

Estilismo

Desafortunadamente, puedes ver el feo fondo gris de la barra de progreso. Para eliminarlo, simplemente buscar el fondo por id e intentar ocultarlo no funciona. Para eliminar el fondo, tuve que crear un dibujo idéntico de la versión del sistema y eliminar el elemento de fondo.

TL; DR: crea un archivo progress_horizontal_holo_no_background_light.xmly pega este elemento de dibujo:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/secondaryProgress">
        <scale android:scaleWidth="100%"
               android:drawable="@drawable/progress_secondary_holo_light" />
    </item>

    <item android:id="@android:id/progress">
        <scale android:scaleWidth="100%"
               android:drawable="@drawable/progress_primary_holo_light" />
    </item>

</layer-list>

Copie los elementos de diseño .png apropiados de sdk/platforms/android-xx/data/res/drawable-xxx/su proyecto y luego en el código puede agregar:

progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.progress_horizontal_holo_no_background_light));

Extra: barra de progreso indeterminada

Las versiones anteriores a KitKat de barras de progreso indeterminadas son bastante feas y lentas. Puede descargar una nueva barra de progreso sin problemas llamada ButteryProgressBar. Simplemente búsquelo en Google (no puedo publicar más enlaces, porque soy nuevo aquí: [), agregue la clase a su proyecto y simplemente puede reemplazar el ProgressBar anterior con este código y tener una barra de progreso indeterminada crujiente:

final ButteryProgressBar progressBar = new ButteryProgressBar(this);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));

También es posible que deba simplificar este código:

final TypedArray ta = c.obtainStyledAttributes(attrs, R.styleable.ButteryProgressBar);
try {
    mBarColor = ta.getColor(R.styleable.ButteryProgressBar_barColor,
            c.getResources().getColor(android.R.color.holo_blue_light));
    mSolidBarHeight = ta.getDimensionPixelSize(
            R.styleable.ButteryProgressBar_barHeight,
            Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity));
    mSolidBarDetentWidth = ta.getDimensionPixelSize(
            R.styleable.ButteryProgressBar_detentWidth,
            Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity));
} finally {
    ta.recycle();
}

a este código:

mBarColor = c.getResources().getColor(android.R.color.holo_blue_light);
mSolidBarHeight = Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity);
mSolidBarDetentWidth = Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity);

Espero haber ayudado :)

Antimonit
fuente
El método removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener) del tipo ViewTreeObserver está obsoleto
Frozen Crayon
@ArjunU. ¿Qué deberíamos usar en su lugar?>
Patrick Geyer
@PatrickGeyer ver stackoverflow.com/questions/16189525/…
Frozen Crayon
Probé la barra de progreso indeterminada ( ButteryProgressBar) con ActionBarActivitypero no funciona. ¿Cómo puedo poner una barra de progreso indeterminada debajo de ActionBar/Toolbar? Este es el diseño que estoy usando: stackoverflow.com/a/26440880/1480019
user1480019
2
@GerritHoekstra: En caso de que la getSupportActionBar().getHeight()función funcione, ya casi estás allí. La progressBar.setY()función establece la posición relativa a la parte superior de la pantalla, incluida la barra de estado. Entonces lo que tienes que hacer es hacerlo setY(supportActionBarHeight + Math.ceil(25 * context.getResources().getDisplayMetrics().density)). La barra de estado tiene 25px de alto (mdpi) y escala con densidades más altas (hdpi / xhdpi / ...). Pruébalo y dime si funciona.
Antimonit
25

Extienda las actividades de la siguiente clase para tener un ProgressBar en la parte superior (debajo de ActionBar) de cada uno y un getProgressBar()método:

Clase para padres:

public abstract class ProgressActivity extends Activity {
    private ProgressBar mProgressBar;

    @Override
    public void setContentView(View view) {
        init().addView(view);
    }

    @Override
    public void setContentView(int layoutResID) {
        getLayoutInflater().inflate(layoutResID,init(),true);
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        init().addView(view,params);
    }

    private ViewGroup init(){
        super.setContentView(R.layout.progress);
        mProgressBar = (ProgressBar) findViewById(R.id.activity_bar);
        return (ViewGroup) findViewById(R.id.activity_frame);
    }

    protected ProgressBar getProgressBar(){
        return mProgressBar;
    }
}

Diseño (progress.xml):

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
    android:layout_width="match_parent" android:layout_height="match_parent">
<ProgressBar android:id="@+id/activity_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="-8dp"
    style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
    />
  <FrameLayout android:id="@+id/activity_frame"
      android:layout_width="match_parent"
      android:layout_height="fill_parent"
      />
</LinearLayout>
Dakota del Sur
fuente
1
Funciona ... en su mayor parte. ProgressBar parece independiente de la barra de acciones. Tuve que agregar el android:layout_marginTop="-8dp"ProgressBar para simular el efecto de "sombra". Pero para este método, probablemente sea más eficiente agregarlo al diseño principal. Sin embargo, ahora funciona según lo previsto. Gracias por el truco.
zubietaroberto
@zubietaroberto Sí, puede agregarlo al diseño principal si solo lo está usando para una actividad. Si desea que varias actividades tengan esta característica, puede ampliar la clase que se muestra arriba.
SD
1
Su trabajo para mí, pero la barra de progreso aparece debajo de la pestaña host, ¿cómo puedo hacerlo por encima de la pestaña host y debajo de la barra de acción?
DeckyFx
4

He compilado el código de este hilo, así como otros hilos en StackOverflow y he creado un proyecto que se puede utilizar para implementar ButteryProgessbar, así como "desplegar hacia abajo para actualizar". https://github.com/pauldmps/Gmail-like-Pull-Down-to-Refresh

Siéntase libre de usar el código en su aplicación.

Muchísimas gracias a ustedes.

Shantanu Paul
fuente
3

Utilice el siguiente código. solo use un estilo predeterminado en la barra de progreso comostyle="?android:attr/progressBarStyleHorizontal"

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    <ProgressBar 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        android:indeterminate="true"

        />

</RelativeLayout>
Rango
fuente
0

Bueno, hice algo similar para una de mis aplicaciones para mascotas y no estoy seguro de si esa es la única o la mejor manera de hacerlo, pero definitivamente funciona.

Para empezar, use una barra de acción de superposición y luego establezca el elemento de diseño de fondo en "nulo" para que la barra de acción de superposición sea transparente.

Ahora, en el diseño de su actividad, establezca el margen superior de la vista raíz en "altura de la barra de acciones". Puede hacerlo así.

<RelativeLayout
    ...
    android:layout_marginTop="?android:attr/actionBarSize" />

Ahora la acción no ocultará el contenido de su actividad.

Lo siguiente que debe hacer ahora es agregar una vista de encabezado en la parte superior de la vista raíz con la misma altura que la barra de acción. Ponle un color de fondo. Este ahora sería el color de su barra de acción y dado que la barra de acción se alinea perfectamente en la parte superior de esta vista de encabezado.

Ahora puede colocar fácilmente una barra de progreso en la vista del encabezado y alinearla con la parte inferior de la vista del encabezado. Para el usuario, esto parecería como si la barra de progreso estuviera en la barra de acción, al igual que Chrome.

usuario2405598
fuente