web-dev-qa-db-fra.com

Afficher une superposition de chargement sur l'écran Android

Je souhaite afficher une superposition sur l'écran qui affiche un petit symbole de chargement ou éventuellement du texte pendant que mon application tente de se connecter au serveur. Mon écran de connexion est tout à l'intérieur d'une disposition linéaire verticale.

L’effet que j’essaie d’obtenir ressemble à ceci: http://docs.xamarin.com/recipes/ios/standard_controls/popovers/display_a_loading_message

35
James Monger

Peut-être trop tard, mais je suppose que quelqu'un pourrait le trouver utile.

Activité:

public class MainActivity extends Activity implements View.OnClickListener {

    String myLog = "myLog";

    AlphaAnimation inAnimation;
    AlphaAnimation outAnimation;

    FrameLayout progressBarHolder;
    Button button;

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

        button = (Button) findViewById(R.id.button);
        progressBarHolder = (FrameLayout) findViewById(R.id.progressBarHolder);

        button.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                new MyTask().execute();
                break;
        }

    }

    private class MyTask extends AsyncTask <Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            button.setEnabled(false);
            inAnimation = new AlphaAnimation(0f, 1f);
            inAnimation.setDuration(200);
            progressBarHolder.setAnimation(inAnimation);
            progressBarHolder.setVisibility(View.VISIBLE);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            outAnimation = new AlphaAnimation(1f, 0f);
            outAnimation.setDuration(200);
            progressBarHolder.setAnimation(outAnimation);
            progressBarHolder.setVisibility(View.GONE);
            button.setEnabled(true);
        }

        @Override
        protected Void doInBackground(Void... params) {
            try {
                for (int i = 0; i < 5; i++) {
                    Log.d(myLog, "Emulating some task.. Step " + i);
                    TimeUnit.SECONDS.sleep(1);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

}

Layout xml:

<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"
    tools:context=".MainActivity">

    <Button
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="Start doing stuff"
        Android:id="@+id/button"
        Android:layout_below="@+id/textView"
        Android:layout_centerHorizontal="true" />

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:textAppearance="?android:attr/textAppearanceLarge"
        Android:text="Do Some Stuff"
        Android:id="@+id/textView"
        Android:layout_alignParentTop="true"
        Android:layout_centerHorizontal="true" />

    <FrameLayout
        Android:id="@+id/progressBarHolder"
        Android:animateLayoutChanges="true"
        Android:visibility="gone"
        Android:alpha="0.4"
        Android:background="#000000"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:indeterminate="true"
            Android:layout_gravity="center" />
    </FrameLayout>
</RelativeLayout>
76
Kostya Buts

J'aime l'approche de Kostya Mais la réponse

Sur cette base, voici quelques idées pour créer facilement la même superposition réutilisable dans votre application:

Envisagez de placer FrameLayout en superposition dans un fichier de présentation séparé, par exemple. res/layout/include_progress_overlay:

<FrameLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/progress_overlay"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:alpha="0.4"
    Android:animateLayoutChanges="true"
    Android:background="@Android:color/black"
    Android:clickable="true"
    Android:visibility="gone">

    <ProgressBar
        style="?android:attr/progressBarStyleLarge"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_gravity="center"
        Android:indeterminate="true"/>

</FrameLayout>

(Une chose que j'ai ajoutée dans la superposition FrameLayout est Android:clickable="true". Ainsi, si la superposition est affichée, elle empêche les clics d'atteindre les éléments de l'interface utilisateur situés en dessous. Au moins, dans mon cas d'utilisation typique, c'est ce que je veux.)

Ensuite, incluez-le si nécessaire: 

<!-- Progress bar overlay; shown while login is in progress -->
<include layout="@layout/include_progress_overlay"/>

Et en code:

View progressOverlay;
[...]

progressOverlay = findViewById(R.id.progress_overlay);
[...]

// Show progress overlay (with animation): 
AndroidUtils.animateView(progressOverlay, View.VISIBLE, 0.4f, 200);
[...]

// Hide it (with animation): 
AndroidUtils.animateView(progressOverlay, View.GONE, 0, 200); 

Avec le code d'animation extrait dans une méthode util: 

/**
 * @param view         View to animate
 * @param toVisibility Visibility at the end of animation
 * @param toAlpha      Alpha at the end of animation
 * @param duration     Animation duration in ms
 */
public static void animateView(final View view, final int toVisibility, float toAlpha, int duration) {
    boolean show = toVisibility == View.VISIBLE;
    if (show) {
        view.setAlpha(0);
    }
    view.setVisibility(View.VISIBLE);
    view.animate()
            .setDuration(duration)
            .alpha(show ? toAlpha : 0)
            .setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            view.setVisibility(toVisibility);
        }
    });
}

(Ici, en utilisant view.animate(), ajouté dans l’API 12, au lieu de AlphaAnimation.)

51
Jonik

J'ai ProgressBar dans Relative Layout et je le cache ou le montre respectivement. Et oui l'activité peut être transparente.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" >

    <LinearLayout
        Android:id="@+id/hsvBackgroundContainer"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_alignParentLeft="true"
        Android:layout_alignParentTop="true"
    </LinearLayout>


    <ProgressBar
        Android:id="@+id/pbProgess"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_centerHorizontal="true"
        Android:layout_centerVertical="true" />

</RelativeLayout>
5
Malachiasz

Un spinner avec un message sur l'application peut être créé à l'aide de ProgressDialog. Bien que cela ne produise pas l'effet exact comme dans l'image, c'est un bon moyen de montrer que l'application fonctionne.

3
James Monger

J'ai eu la même question, j'ai essayé les solutions mais n'était pas la meilleure interface utilisateur, donc, j'ai fait les étapes suivantes.

  1. Divisez l'écran en 2 vues: Contenu et ProgressBar.
  2. Lorsque vous souhaitez appeler ProgressBar, vous modifiez la visibilité en VISIBLE et ajoutez les propriétés suivantes au contenu id = content et non au conteneur progressBar.

content.background = "# 000000" content.alpha = "0.4"

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

        <RelativeLayout
            Android:id="@+id/content"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:animateLayoutChanges="true"
            tools:context=".MainActivity">

            <Button
                Android:id="@+id/button"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_below="@+id/textView"
                Android:layout_centerHorizontal="true"
                Android:text="Start doing stuff" />

            <TextView
                Android:id="@+id/textView"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_alignParentTop="true"
                Android:layout_centerHorizontal="true"
                Android:text="Do Some Stuff"
                Android:textAppearance="?android:attr/textAppearanceLarge" />

        </RelativeLayout>

        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_gravity="center"
            Android:indeterminate="true"
            Android:visibility="gone" />

    </FrameLayout>
0
Emiliano Schiavone