#android #android-fragments #android-webview #android-alertdialog #dialogfragment
#Android #android-фрагменты #android-webview #android-alertdialog #dialogfragment
Вопрос:
У меня есть голый проект, только webview и реализация для оповещения и подсказки … каждый из них работает нормально сам по себе, но пользовательский интерфейс перестает отвечать, если приглашение находится непосредственно внутри alert: alert (приглашение («привет», «тест»));
Есть идеи о том, что может быть причиной этого? ниже приведены соответствующие части кода:
public class MainActivity extends AppCompatActivity implements JSDialogFragment.JSDialogResultListener{
private WebView m_webView;
public void OnJsDialogFragmentPositive(Bundle args, Object cb) {
Log.d("JSDialogFragment", "OnJsDialogFragmentPositive");
jsDialogType dType = (jsDialogType)args.getSerializable("dType");
if(null != dType amp;amp; null != cb) {
if(JS_DIALOG_TYPE_ALERT == dType) {
((JsResult) cb).confirm();
} else if(JS_DIALOG_TYPE_PROMPT == dType) {
String value = args.getString("value");
((JsPromptResult) cb).confirm(null != value ? value : "");
}
}
}
public void OnJsDialogFragmentNegative(Bundle args, Object cb) {
Log.d("JSDialogFragment", "OnJsDialogFragmentNegative");
}
m_webView = (WebView) findViewById(R.id.m_webView);
m_webView.getSettings().setJavaScriptEnabled(true);
m_webView.setWebChromeClient(new WebChromeClient() {
// shared set up transaction code
FragmentTransaction showJsTransactionInit() {
FragmentTransaction ft = getFragmentManager().beginTransaction();
android.app.Fragment prev = getFragmentManager().findFragmentByTag("mytag");
if (prev != null) ft.remove(prev);
ft.addToBackStack(null);
return ft;
}
@Override
public boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result) {
FragmentTransaction ft = showJsTransactionInit();
DialogFragment frag = JSDialogFragment.newInstanceAlert(message, result);
frag.show(ft, "mytag");
return true; // handled
}
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final android.webkit.JsPromptResult result) {
FragmentTransaction ft = showJsTransactionInit();
DialogFragment frag = JSDialogFragment.newInstancePrompt(message, result);
frag.show(ft, "mytag");
return true; // handled
}
});
и реализации JSDialogFragment, которая обрабатывает диалог:
public class JSDialogFragment extends DialogFragment {
interface JSDialogResultListener {
void OnJsDialogFragmentPositive(Bundle obj, Object cb);
void OnJsDialogFragmentNegative(Bundle obj, Object cb);
}
private Object mCB;
public void setCallBack(Object cb) {
mCB = cb;
}
// to init alert incase it may differ from how we show prompt
public static DialogFragment newInstanceAlert(String message, Object cb) {
JSDialogFragment frag = new JSDialogFragment();
frag.setCallBack(cb);
Bundle args = new Bundle();
args.putString("caption", message);
args.putSerializable("dType", jsDialogType.JS_DIALOG_TYPE_ALERT); (JS_DIALOG_TYPE_ALERT is just an enum to distinguish between the types)
frag.setArguments(args);
return frag;
}
// to init prompt incase it may differ from how we show alert
public static DialogFragment newInstancePrompt(String message, Object cb) {
JSDialogFragment frag = new JSDialogFragment();
frag.setCallBack(cb);
Bundle args = new Bundle();
args.putString("caption", message);
args.putSerializable("dType", jsDialogType.JS_DIALOG_TYPE_PROMPT);
frag.setArguments(args);
return frag;
}
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof JSDialogResultListener)) {
throw new ClassCastException(activity.toString() " must implement JSDialogResultListener");
}
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle args = getArguments();
String caption = args.getString("caption");
jsDialogType jsDType = (jsDialogType)args.getSerializable("dType");
if(null==jsDType) jsDType = jsDialogType.JS_DIALOG_TYPE_ALERT;
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) //, R.style.jsDialogsTheme)
.setTitle(R.string.jsDialogTitle)
.setMessage(caption);
switch(jsDType) {
case JS_DIALOG_TYPE_ALERT:
builder.setPositiveButton(android.R.string.ok , new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
((JSDialogResultListener) getActivity()).OnJsDialogFragmentPositive(args, mCB);
dialog.dismiss();
}
});
break;
case JS_DIALOG_TYPE_PROMPT:
builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
args.putString("value", "waaaawwweeeee3");
((JSDialogResultListener) getActivity()).OnJsDialogFragmentPositive(args, mCB);
dialog.dismiss();
}
}).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
((JSDialogResultListener) getActivity()).OnJsDialogFragmentNegative(args, mCB);
dialog.dismiss();
}
});
break;
}
return builder.create();
}
}
Есть мысли, предложения?
Комментарии:
1. Я забыл включить последний вызов, который переходит на страницу с предупреждением (подсказка (…, …)): m_webView.loadUrl(» example.com » );
2. Похоже, что после удаления приглашения базовый код для удаления скрывает только диалоговое окно, которое будет удалено позже, НО затем начинается создание нового фрагмента для предупреждения, и в середине его создания исходное приглашение теперь удаляется внутренним кодом, и говорит, что в backstack ничего нет…. но оповещение уже совершило транзакцию и попыталось вызвать onshow (который к настоящему времени должен был добавить еще одну транзакцию?) как правильно дождаться завершения диалога, прежде чем запускать другой….