Як вимкнути взаємодію користувача, поки ProgressBar відображається в Android?


80

Я використовую спеціальний ProgressBar. Зараз, поки виконується завдання, я показую індикатор прогресу, але користувач все ще може взаємодіяти з поданнями та елементами управління. Як відключити взаємодію користувача на всьому поданні, як це робить ProgressDialog, коли воно видно.

Чи потрібно мені використовувати прозорий вигляд поверх головного перегляду та показувати на цьому перегляді рядок прогресу та приховувати цей вигляд після виконання завдання.

Або просто отримати ідентифікатор мого parentView і встановити його вимкненим? Але тоді я не зможу затемнити фон, подібно до того, що відбувається, коли у вікні / Діяльність / Фрагмент з’являється діалогове вікно. Правда?

Я просто хочу знати спосіб заборонити користувачеві будь-яку взаємодію, поки відображається індикатор прогресу.

Дякую



4
@txteclipse Я не хочу налаштовувати панель прогресу, я це вже зробив. Отже, моє запитання не повторюється. Я просто хочу відключити взаємодію з користувачем, поки відображається панель виконання, так само, коли видимий ProgressDialog, користувач не може взаємодіяти з іншими елементами керування інтерфейсом, не відкидаючи діалогове вікно прогресу. Тепер, як моє запитання є дублікатом цього питання. Моє запитання навіть не пов'язане з налаштуваннями.
intellignt_idiot

1
Якщо вам потрібні всі функції діалогового вікна, вам слід скористатися діалоговим вікном. Модальність нетривіальна для реалізації: прийнята відповідь, наприклад, не блокує взаємодію з клавіатурою. Друга відповідь у зв’язаному запитанні демонструє, як використовувати власні ресурси ProgressBar із ProgressDialog. Якщо це не відповідає вашим потребам, ви можете використовувати власний макет із ProgressBar.
Теорія графіків

Відповіді:


147

Ваше запитання: Як вимкнути взаємодію користувача, поки ProgressBar видно в android?

Щоб вимкнути взаємодію з користувачем, вам просто потрібно додати наступний код

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

Щоб повернути взаємодію з користувачем, вам просто потрібно додати наступний код

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

Ось приклад: Примітка: Я даю вам лише приклад, щоб показати, як вимкнути або зберегти взаємодію користувача

Додайте індикатор виконання у свій xml. Щось подібне

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

У MainActivity при натисканні кнопки ви показуєте індикатор прогресу та вимикаєте взаємодію користувача.

@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);
        }
    });
}

І коли користувач backPress ви видаляєте індикатор прогресу знову, зберігаючи взаємодію користувача. Щось подібне

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

Якщо ви хочете додати функцію вимкнення та сірого відображення, вам потрібно додати у свій файл макета xml лінійний макет, який заповнює батьківський. Встановіть для тла # B0000000, а visibiltyдля - GONE. Потім програмно встановіть його visibilityна VISIBLE.

Сподіваюся, це допоможе!


1
У цьому впровадженні є щось цікаве. Я розробляю носиму програму для полярних годинників, і це рішення доставляє мені деякі проблеми. Я помітив, що всякий раз, коли користувач швидко торкається екрана, якщо дія після такого дотику блокує інтерфейс користувача за допомогою вашого рішення (Для запобігання численним подіям) з якоїсь причини Android відкриває будь-яку програму або опцію, яка стоїть за моєю програмою. Щоб спробувати пояснити це трохи краще, його подібно до того, як мій додаток мінімізує на частку секунди дуже швидко, і дозволяє мені торкатися будь-чого, що є на екрані в той момент. Хтось переживав щось подібне?
Роджер

13

Я виправив цю проблему, додавши кореневий макет до 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>

Зробив кореневий макет клікабельним

android:clickable="true"

ПРИМІТКА. У моєму основному поданні я мав права RelativeLayoutroot і додав згаданий код всередині кореневого макета в останню позицію (остання дочірня).

Сподіваюся, це допомагає !!


Я б запропонував FrameLayoutзамість a LinearLayout, крім цього, ця відповідь ідеальна, і вона просто працює. Дякую Нівару
Лукасу П.

Чи працює це, коли у фоновому режимі є кнопки? Висота цих здається вищою (api 21+ принаймні), і вони будуть натискатими, якщо ви не встановите більшу висоту в цьому кореневому макеті.
Ixx


3

Використовуйте метод документа за замовчуванням progressbar.setCancelable (false)


1
Але який вплив це матиме на взаємодію з користувачем? Я все ще можу торкнутися або ввести EditText, поки ProgressBar видно і для скасування встановлено значення false.
intellignt_idiot

6
і з якого моменту на панелі прогресу почалося властивість setCancelable (false)?
intellignt_idiot

У вас є опція, коли ваше завдання, яке виконується з можливістю відключення, є фальшивим як ваш батьківський подання, а після того, як виконане завдання може бути відключеним, встановлено як істина
Рамеш самбу,

3

Створіть діалогове вікно з прозорим фоном. Проблема в getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);тому, що коли програма перейде у фоновому режимі та повернеться, користувач зможе взаємодіяти з компонентами інтерфейсу користувача, набагато більше обробки. Отже, для блокування користувальницького інтерфейсу створіть прозоре діалогове вікно, і якщо ви хочете встановити час для приховування / показу. Зробіть це в потоці, який можна запустити. Тож рішення буде

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

відмінне рішення, підтримує чіткий контроль над процесом. О так, і це також прокидається. ЗАГОЛОВЛЕНО :)
Тоні Гіл,

1

Зробіть свій батьківський макет відносним макетом і додайте це:

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

Якщо у вашому інтерфейсі є плаваючі кнопки, вони все одно захоплюють весь фокус і залишаються клікабельними, коли видно індикатор виконання. для цього використання: (коли ваш рядок програми видимий і ввімкніть його знову, коли ви зробите свій рядок програми невидимим / зниклим)

fb.setEnabled(false);

1

Розширити (каламбур) на прийняту відповідь :

Коли ви використовуєте kotlin, ви можете використовувати функції розширення. Таким чином у вас є швидкий і приємний на вигляд метод блокування та розблокування інтерфейсу користувача.

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()
}

Ви можете використовувати функції блокування та розблокування у своїй діяльності. Крім того, ви можете додати більше функціональних можливостей, таких як показ тосту чи щось інше.

Використовуючи його у власному поданні або будь-якому іншому поданні, ви можете просто передати контекст на активність та використовувати функції.

Використовуйте blockInputForTaskдля оточення простих лінійних завдань та blockInputтаunblockInput коли вони потрібні в різних сферах.

Ви можете використовувати blockInputForTaskтак:

blockInputForTask { 
    // Your lines of code
    // Can be multiple lines
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.