在ProgressBar在Android中可见时如何禁用用户交互?


79

我正在使用自定义的ProgressBar。现在,当任务正在进行时,我正在显示进度栏,但是用户仍然可以与视图和控件进行交互。可见时,如何像ProgressDialog一样在整个视图上禁用用户交互。

我是否需要在主视图上方使用透明视图,并在该视图上显示进度条,并在任务完成后隐藏该视图?

或者只是获取我的parentView的ID并将其设置为禁用?但是那样我就无法调暗背景,就像在视图/活动/片段上出现对话框时发生的一样。对?

我只想知道在进度条可见时禁止用户进行任何交互的方法。

谢谢



4
@txteclipse我不想自定义进度条,我已经做到了。因此,我的问题不是重复的。我只想在进度条可见时禁用用户交互,就像在看到ProgressDialog时一样,如果不关闭进度对话框,用户将无法与其他UI控件进行交互。现在,我的问题如何重复该问题。我的问题甚至与定制无关。
intellignt_idiot

1
如果要使用对话框的所有功能,则应使用对话框。模态实现并非易事:例如,可接受的答案不会阻止键盘交互。链接的问题中的第二个答案演示了如何通过ProgressDialog使用自定义的ProgressBar资源。如果那不能满足您的需求,则可以在ProgressBar中使用自定义布局
图论

Answers:


144

您的问题:当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);
        }
    });
}

当用户backPressed时,再次删除进度条将保留用户交互。

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

如果要添加禁用和灰显显示功能,则需要在xml布局文件中添加填充父级的线性布局。将其背景设置为#B0000000并将其设置visibiltyGONE。然后以编程方式将其设置visibilityVISIBLE

希望有帮助!


这个实现有一些有趣的地方。我正在开发一款用于极地手表的可穿戴应用,而该解决方案给我带来了一些麻烦。我注意到,如果由于某种原因,这种触摸后的操作由于某种原因阻止了UI使用用户解决方案(以防止发生多个事件),则android会打开任何应用程序或位于我应用程序背后的选项,从而使用户快速触摸屏幕。为了更好地解释它,就像我的应用程序最小化了几分之一秒的真实速度,并允许我触摸那一刻在屏幕上的任何东西。有没有人经历过类似的经历?
罗杰(Roger)

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"

注意: 在我的主视图中,我RelativeLayout以root身份并在根布局的最后一个位置(最后一个孩子)处添加了上述代码。

希望这可以帮助!!


我建议使用aFrameLayout而不是a LinearLayout,除此之外,这个答案是完美的并且有效。感谢Nivar
Lucas

当背景视图中有按钮时,此功能有效吗?除非您在此根目录布局中设置更高的海拔高度,否则这些海拔高度似乎更高(至少为API 21+),并且它们将是可单击的。
Ixx


3

使用文档默认方法progressbar.setCancelable(false)


1
但是它将对用户交互产生什么影响?当ProgressBar可见并且可取消设置为false时,我仍然可以触摸或键入EditText。
intellignt_idiot

6
并且自从进度条开始具有setCancelable(false)属性以来?
intellignt_idiot

当您的任务运行setenabled为假时作为父视图,而在完成任务后将setenabled设置为true时,您可以选择
Ramesh

3

制作一个具有透明背景的对话框。问题 getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);在于,当应用程序在后台运行并返回时,用户将能够与UI组件进行交互,从而进行更多的处理。因此,要阻止UI,请创建一个透明对话框,以及是否要设置隐藏/显示时间。在可运行线程中执行此操作。所以解决方案是

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>

如果您的UI中有浮动按钮,则它们仍将占据所有焦点,并且在进度条可见时仍可单击。用于此用途:(当您的进度条可见并在使您的进度条不可见/消失时重新启用它们)

fb.setEnabled(false);

1

扩展(双关语意)接受的答案

使用kotlin时,可以使用扩展功能。这样,您就可以快速而美观地阻止和取消阻止UI。

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

您可以在活动中使用阻止和取消阻止功能。另外,您可以添加更多功能,例如显示Toast或其他内容。

在自定义视图或任何其他视图中使用它时,您可以简单地将上下文转换为活动并使用功能。

使用blockInputForTask到环绕简单的线性任务,blockInput并且unblockInput需要在不同的范围,当他们。

您可以这样使用blockInputForTask

blockInputForTask { 
    // Your lines of code
    // Can be multiple lines
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.