公式ドキュメントを見ると、Deprecated since API level 26って書いてあるので、これからアプリを作るときは使わないほうが良さげ。
でもどうしても使いたいので自分で作ってみた。
ダイアログ本体
ProgressDialog.java
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.widget.ProgressBar;
import android.widget.TextView;
public class ProgressDialog extends DialogFragment {
private static final int DELAY_MILLISECOND = 450;
private static final int SHOW_MIN_MILLISECOND = 300;
private ProgressBar mProgressBar;
private TextView mProgressMessage;
private boolean mStartedShowing;
private long mStartMillisecond;
private long mStopMillisecond;
private String mMessage;
// required default constructor
public ProgressDialog() {
super();
}
public static ProgressDialog newInstance(String message) {
ProgressDialog instance = new ProgressDialog();
Bundle arguments = new Bundle();
arguments.putString("message", message);
instance.setArguments(arguments);
return instance;
}
@NonNull
@Override
@SuppressLint("InflateParams")
public Dialog onCreateDialog(Bundle savedInstanceState) {
mMessage = getArguments().getString("message");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
builder.setView(inflater.inflate(R.layout.dialog_progress, null));
return builder.create();
}
@Override
public void onStart() {
super.onStart();
mProgressBar = getDialog().findViewById(R.id.progress);
mProgressMessage = getDialog().findViewById(R.id.progress_message);
mProgressMessage.setText(mMessage);
}
@Override
public void show(final FragmentManager manager, final String tag) {
mStartMillisecond = System.currentTimeMillis();
mStartedShowing = false;
mStopMillisecond = Long.MAX_VALUE;
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (mStopMillisecond > System.currentTimeMillis()) {
showDialogAfterDelay(manager, tag);
}
}
}, DELAY_MILLISECOND);
}
private void showDialogAfterDelay(FragmentManager manager, String tag) {
mStartedShowing = true;
super.show(manager, tag);
}
public void cancel() {
mStopMillisecond = System.currentTimeMillis();
if (mStartedShowing) {
if (mProgressBar != null) {
cancelWhenShowing();
} else {
cancelWhenNotShowing();
}
}
}
private void cancelWhenShowing() {
if (mStopMillisecond < mStartMillisecond + DELAY_MILLISECOND + SHOW_MIN_MILLISECOND) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
dismissAllowingStateLoss();
}
}, SHOW_MIN_MILLISECOND);
} else {
dismissAllowingStateLoss();
}
}
private void cancelWhenNotShowing() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
dismissAllowingStateLoss();
}
}, SHOW_MIN_MILLISECOND);
}
public void setMessage(String message) {
if (mProgressMessage == null) {
mProgressMessage = getDialog().findViewById(R.id.progress_message);
}
mProgressMessage.setText(message);
}
}
ダイアログのレイアウト
dialog_progress.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progress"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/progress_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
app:layout_constraintBottom_toBottomOf="@+id/progress"
app:layout_constraintLeft_toRightOf="@+id/progress"
app:layout_constraintTop_toTopOf="@+id/progress"
app:layout_constraintVertical_bias="0.507" />
</android.support.constraint.ConstraintLayout>
使い方
呼び出し方
ProgressDialog progressDialog = ProgressDialog.newInstance("表示するメッセージ");
progressDialog.show(getSupportFragmentManager(), "Tag");
progressDialog.dismiss();
何段階かある処理で今何をやってるのか都度変更する
MainActivity
public class MainActivity extends AppCompatActivity {
private Button mButton;
private ProgressDialog mProgressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
doStepOne();
}
});
}
private void doStepOne() {
// 最初のメッセージだけはsetMessage()でセットできない。
// getDialogしてもnullになる。LifeCycleとやらを理解しないと駄目そう
mProgressDialog = ProgressDialog.newInstance("Step one ...");
mProgressDialog.show(getSupportFragmentManager(), "tag");
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... aVoid) {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
doStepTwo();
}
}.execute();
}
private void doStepTwo() {
// 一度表示されてしまえばsetMessage()で表示が変えられる
mProgressDialog.setMessage("Step two ...");
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... aVoid) {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
doFinish();
}
}.execute();
}
private void doFinish() {
mProgressDialog.dismiss();
}
}