如何禁用用户交互,而进程条是可见的,在机器人?

我正在使用一个定制的 ProgressBar。现在,当一个任务正在进行时,我显示了进度条,但是用户仍然可以与视图和控件交互。 如何在整个视图上禁用用户交互,就像 ProgressDialog 所做的那样,当它是可见的时候。

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

或者只是获取我父视图的 id 并将其设置为禁用?但是这样我就不能调暗背景了,就像视图/活动/片段上出现对话框时发生的情况一样。对吧?

我只是想知道如何在进度条可见的情况下禁止用户进行任何交互。

谢谢

75319 次浏览

Use document default method progressbar.setCancelable(false)

Your question: How to disable the user interaction while ProgressBar is visible in android?

To disable the user interaction you just need to add the following code

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

To get user interaction back you just need to add the following code

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

Here is an example: Note:I am giving you just an example to show how to disable or retain user interaction

Add a progress bar in your xml.Something like this

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

In MainActivity when a button pressed you show the progressbar and disable the user interaction.

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

And when user backPressed you remove the progressbar again retain the user interaction.Something like this

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

If you want to add a feature of disable and greyed out display, you need to add in your xml layout file a linear layout that fills the parent. Set its background to #B0000000 and its visibilty to GONE. Then programmatically set its visibility to VISIBLE.

Hope this help!

just set:

android:clickable="true"

in your xml

<ProgressBar...

Only this makes magic!

I have fixed this issue by adding root layout to the 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>

Made the root layout clickable

android:clickable="true"

NOTE: In my main view, I had RelativeLayout as root and have added above-mentioned code inside the root layout at the last position (last child).

Hope this helps!!

Make a dialog with transparent background. The issue with getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); is that when app will go in background and come back user will be able to interact with UI components, a lot more handling. So for blocking UI make a transparent dialog and if you want to set time for hide/show. Do this in a runnable thread. So the solution will be

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

Make your parent layout as Relative Layout & add this :

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

If you have floating buttons in your UI, they still grab all the focus & remain clickable when the progress bar is visible. for this use : (when your prog bar is visible & re-enable them when you make your prog bar invisible/gone)

fb.setEnabled(false);

To extend (pun intended) on the accepted Answer :

When you use kotlin you can use extension functions. That way you have a quick and nice looking method for blocking and unblocking 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()
}

You can use the blocking and unblocking functions in your activity. Also, you can add more functionality like showing a Toast or something.

When using it in a custom view or any other view, you can simply cast the context to activity and use the functions.

Use blockInputForTask to surround simple linear tasks and blockInputand unblockInput when they are needed in different scopes.

You can use blockInputForTask like this:

blockInputForTask {
// Your lines of code
// Can be multiple lines
}