Wie deaktiviere ich die Benutzerinteraktion, während ProgressBar in Android sichtbar ist?

79

Ich verwende eine benutzerdefinierte ProgressBar. Während eine Aufgabe ausgeführt wird, wird der Fortschrittsbalken angezeigt, der Benutzer kann jedoch weiterhin mit den Ansichten und Steuerelementen interagieren. Wie deaktiviere ich die Benutzerinteraktion in der gesamten Ansicht wie ein ProgressDialog, wenn er sichtbar ist?

Muss ich eine transparente Ansicht über der Hauptansicht verwenden und den Fortschrittsbalken in dieser Ansicht anzeigen und diese Ansicht ausblenden, sobald eine Aufgabe abgeschlossen ist?

Oder einfach die ID meiner Elternansicht abrufen und deaktivieren? Aber dann kann ich den Hintergrund nicht dimmen, genau wie wenn ein Dialogfeld in der Ansicht / Aktivität / Fragment angezeigt wird. Richtig?

Ich möchte nur wissen, wie der Benutzer von jeglicher Interaktion ausgeschlossen werden kann, während der Fortschrittsbalken sichtbar ist.

Vielen Dank

intelligentnt_idiot
quelle
Mögliches Duplikat von Custom Drawable für ProgressBar / ProgressDialog
Graph Theory
4
@txteclipse Ich möchte den Fortschrittsbalken nicht anpassen, das habe ich bereits getan. Meine Frage ist also nicht doppelt. Ich möchte nur die Benutzerinteraktion deaktivieren, während der Fortschrittsbalken sichtbar ist, genauso wie wenn ein ProgressDialog sichtbar ist, kann der Benutzer nicht mit anderen UI-Steuerelementen interagieren, ohne den Fortschrittsdialog zu schließen. Wie kommt es nun, dass meine Frage ein Duplikat dieser Frage ist? Meine Frage bezieht sich nicht einmal im entferntesten auf die Anpassung.
intellignt_idiot
1
Wenn Sie alle Funktionen eines Dialogfelds nutzen möchten, sollten Sie ein Dialogfeld verwenden. Die Implementierung von Modalität ist nicht trivial: Die akzeptierte Antwort blockiert beispielsweise nicht die Tastaturinteraktion. Die zweite Antwort in der verknüpften Frage zeigt, wie benutzerdefinierte ProgressBar-Ressourcen mit einem ProgressDialog verwendet werden. Wenn dies Ihren Anforderungen nicht entspricht, können Sie mit Ihrer ProgressBar ein benutzerdefiniertes Layout verwenden .
Graphentheorie

Antworten:

144

Ihre Frage: Wie deaktiviere ich die Benutzerinteraktion, während ProgressBar in Android sichtbar ist?

Um die Benutzerinteraktion zu deaktivieren, müssen Sie nur den folgenden Code hinzufügen

getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

Um die Benutzerinteraktion wiederherzustellen, müssen Sie nur den folgenden Code hinzufügen

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

Hier ein Beispiel: Hinweis: Ich gebe Ihnen nur ein Beispiel, um zu zeigen, wie Sie die Benutzerinteraktion deaktivieren oder beibehalten können

Fügen Sie Ihrer XML einen Fortschrittsbalken hinzu

<ProgressBar
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/progressBar"
    android:visibility="gone"/>

Wenn Sie in MainActivity eine Taste drücken, wird der Fortschrittsbalken angezeigt und die Benutzerinteraktion deaktiviert.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mImageView = (ImageView) findViewById(R.id.imageView);
    mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
    mImageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mProgressBar.setVisibility(View.VISIBLE);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
        }
    });
}

Und wenn der Benutzer zurückgedrückt wird, entfernen Sie den Fortschrittsbalken wieder und behalten die Benutzerinteraktion bei. So etwas

  @Override
public void onBackPressed() {
    super.onBackPressed();
    mProgressBar.setVisibility(View.GONE);
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}

Wenn Sie eine Funktion zum Deaktivieren und Ausgrauen der Anzeige hinzufügen möchten, müssen Sie in Ihrer XML-Layoutdatei ein lineares Layout hinzufügen, das das übergeordnete Layout ausfüllt. Setzen Sie den Hintergrund auf # B0000000 und visibiltyauf GONE. Dann ist es programmatisch festgelegt visibilityzu VISIBLE.

Ich hoffe das hilft!

Niyamat Ullah
quelle
Diese Implementierung hat etwas Interessantes. Ich entwickle eine tragbare App für eine Polaruhr und diese Lösung hat mir einige Probleme bereitet. Ich habe festgestellt, dass Android immer dann, wenn der Benutzer den Bildschirm schnell berührt, wenn die Aktion nach einer solchen Berührung die Benutzeroberfläche mithilfe Ihrer Lösung blockiert (um mehrere Ereignisse zu verhindern), aus irgendeinem Grund eine App oder Option öffnet, die sich hinter meiner App befindet. Um es ein wenig besser zu erklären, wird meine App für den Bruchteil einer Sekunde sehr schnell minimiert und ich kann alles berühren, was sich gerade auf dem Bildschirm befindet. Hat jemand etwas ähnliches erlebt?
Roger
13

Ich habe dieses Problem behoben, indem ich dem das Root-Layout hinzugefügt habe ProgressBar.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:clickable="true"
    android:gravity="center"
    android:visibility="gone"
    android:id="@+id/progress">
    <ProgressBar
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:indeterminate="true"
        android:indeterminateTintMode="src_atop"
        android:indeterminateTint="@color/primary"/>
</LinearLayout>

Das Root-Layout anklickbar gemacht

android:clickable="true"

HINWEIS: In meiner Hauptansicht hatte ich RelativeLayoutals Root und habe den oben genannten Code im Root-Layout an der letzten Position (letztes Kind) hinzugefügt.

Hoffe das hilft!!

Nirav Dangi
quelle
Ich würde vorschlagen, dass FrameLayoutanstelle von a LinearLayout, anders als das, diese Antwort perfekt ist und einfach funktioniert. Danke Nivar
Lucas P.
Funktioniert dies, wenn sich in der Hintergrundansicht Schaltflächen befinden? Die Höhe dieser scheint höher zu sein (mindestens API 21+) und sie können angeklickt werden, es sei denn, Sie legen in diesem Root-Layout eine höhere Höhe fest.
Ixx
9

einfach einstellen:

android:clickable="true" 

in Ihrer XML

<ProgressBar...

Nur das macht Magie!

Paulo Linhares - Packapps
quelle
3

Verwenden Sie die Standardmethode für Dokumente progressbar.setCancelable (false).

Ramesh Sambu
quelle
1
Aber wie wird sich das auf die Benutzerinteraktion auswirken? Ich kann EditText weiterhin berühren oder eingeben, während die ProgressBar sichtbar und stornierbar ist und auf false gesetzt ist.
intellignt_idiot
6
und seit wann hat ein Fortschrittsbalken die Eigenschaft setCancelable (false)?
intellignt_idiot
Sie haben die Option, wenn Ihre Aufgabe als übergeordnete Ansicht setenabled false ausgeführt wird und wenn die erledigte Aufgabe setenabled als true festgelegt wurde
Ramesh sambu
3

Machen Sie einen Dialog mit transparentem Hintergrund. Das Problem dabei getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);ist, dass Benutzer, die in den Hintergrund treten und zurückkehren, mit UI-Komponenten interagieren können, was viel mehr Handhabung bedeutet. Erstellen Sie zum Blockieren der Benutzeroberfläche einen transparenten Dialog und legen Sie die Zeit für das Ausblenden / Anzeigen fest. Tun Sie dies in einem ausführbaren Thread. Die Lösung wird also sein

public class TransparentDialogHelper {

    private Dialog overlayDialog;

    @Inject
    public TransparentDialogHelper() {

    }

    public void showDialog(Context context) {
        if (AcmaUtility.isContextFinishing(context)) {
            return;
        }
        if (overlayDialog == null) {
            overlayDialog = new Dialog(context, android.R.style.Theme_Panel);
            overlayDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED);
        }
        overlayDialog.show();
    }

    public void hideDialog() {
        if (overlayDialog == null || AcmaUtility.isContextFinishing(overlayDialog.getContext())) {
            return;
        }
        overlayDialog.cancel();
    }
}

-------- Timer

Handler handler = new Handler();
handler.postDelayed( () -> {
    view.hideProgress();
}, 2000);
Qumber Abbas
quelle
Hervorragende Lösung, behält die explizite Kontrolle über den Prozess. Oh ja, und es woks auch. UPVOTED :)
Tony Gil
1

Erstellen Sie Ihr übergeordnetes Layout als relatives Layout und fügen Sie Folgendes hinzu:

    <RelativeLayout ... >

    <other layout elements over which prog bar will appear>

<RelativeLayout android:id="@+id/rl_progress_bar"
                android:layout_width="match_parent" android:clickable="true"
                android:layout_height="match_parent" >
<ProgressBar android:id="@+id/pb"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
             android:indeterminateOnly="true"
             style="@android:style/Widget.DeviceDefault.ProgressBar"
             android:theme="@style/AppTheme.MyProgressBar"
    />
</RelativeLayout>

Wenn Sie schwebende Schaltflächen in Ihrer Benutzeroberfläche haben, erfassen diese immer noch den gesamten Fokus und bleiben anklickbar, wenn der Fortschrittsbalken sichtbar ist. für diese Verwendung: (wenn Ihre Prog-Leiste sichtbar ist und aktivieren Sie sie wieder, wenn Sie Ihre Prog-Leiste unsichtbar machen / verschwinden lassen)

fb.setEnabled(false);
AndroidGuy
quelle
1

Erweiterung (Wortspiel beabsichtigt) auf die akzeptierte Antwort :

Wenn Sie Kotlin verwenden, können Sie Erweiterungsfunktionen verwenden. Auf diese Weise haben Sie eine schnelle und gut aussehende Methode zum Blockieren und Entsperren der Benutzeroberfläche.

fun AppCompatActivity.blockInput() {
    window.setFlags(
        WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
        WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
}

fun AppCompatActivity.unblockInput() {
    window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
}

fun AppCompatActivity.blockInputForTask(task: () -> Unit) {
    blockInput()
    task.invoke()
    unblockInput()
}

Sie können die Sperr- und Entsperrfunktionen in Ihrer Aktivität verwenden. Sie können auch weitere Funktionen wie das Anzeigen eines Toasts oder ähnliches hinzufügen.

Wenn Sie es in einer benutzerdefinierten Ansicht oder einer anderen Ansicht verwenden, können Sie den Kontext einfach in Aktivität umwandeln und die Funktionen verwenden.

Verwenden Sie blockInputForTaskdiese Option , um einfache lineare Aufgaben zu umgeben blockInputund unblockInputwann sie in verschiedenen Bereichen benötigt werden.

Sie können blockInputForTaskwie folgt verwenden:

blockInputForTask { 
    // Your lines of code
    // Can be multiple lines
}
Benjamin Basmaci
quelle