[android] Improved alert dialog, added opportunity to inflate different layouts for it, added the first dialog such an approach

This commit is contained in:
Dmitry Donskoy 2019-01-23 13:51:28 +03:00 committed by Aleksandr Zatsepin
parent 9bac7a72db
commit 61bd7d95c0
15 changed files with 342 additions and 31 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="@dimen/margin_base">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/title"
android:textAppearance="@style/MwmTheme.DialogTitleBase"
android:gravity="center|start"
android:layout_gravity="center_vertical"
android:textStyle="bold"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="0dp"/>
<android.support.v7.widget.AppCompatImageView
android:id="@+id/image"
android:layout_gravity="center_vertical"
android:layout_width="@dimen/primary_button_min_height"
android:layout_height="@dimen/primary_button_min_height"
android:src="@drawable/ic_error_36px"/>
</LinearLayout>
<TextView
android:id="@+id/description"
android:textAppearance="?android:attr/textAppearance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center|start"
android:layout_marginTop="@dimen/margin_half"/>
<Button
android:id="@+id/accept_btn"
android:layout_width="wrap_content"
android:layout_marginTop="@dimen/margin_base_plus"
style="@style/MwmWidget.Button.Primary"/>
<TextView
android:id="@+id/decline_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="@dimen/primary_button_min_height"
android:gravity="center"
android:layout_marginTop="@dimen/margin_half_plus"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textAllCaps="true"
android:textStyle="bold"
android:background="?attr/selectableItemBackground"/>
</LinearLayout>

View file

@ -4,14 +4,23 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseMwmDialogFragment;
import com.mapswithme.util.UiUtils;
import com.mapswithme.util.log.Logger;
import com.mapswithme.util.log.LoggerFactory;
@ -21,12 +30,12 @@ public class AlertDialog extends BaseMwmDialogFragment
private static final String ARG_MESSAGE_ID = "arg_message_id";
private static final String ARG_POSITIVE_BUTTON_ID = "arg_positive_button_id";
private static final String ARG_NEGATIVE_BUTTON_ID = "arg_negative_button_id";
private static final String ARG_IMAGE_RES_ID = "arg_image_res_id";
private static final String ARG_REQ_CODE = "arg_req_code";
private static final int UNDEFINED_BUTTON_ID = -1;
private static final String ARG_FRAGMENT_MANAGER_STRATEGY_INDEX = "arg_fragment_manager_strategy_index";
private static final String ARG_DIALOG_VIEW_STRATEGY_INDEX = "arg_dialog_view_strategy_index";
@NonNull
private final DialogInterface.OnClickListener mPositiveClickListener
= (dialog, which) -> AlertDialog.this.onClick(which);
private static final int INVALID_ID = -1;
@Nullable
private AlertDialogCallback mTargetCallback;
@ -35,6 +44,9 @@ public class AlertDialog extends BaseMwmDialogFragment
@NonNull
private ResolveFragmentManagerStrategy mFragmentManagerStrategy = new ChildFragmentManagerStrategy();
@NonNull
private ResolveDialogViewStrategy mDialogViewStrategy = new AlertDialogStrategy();
public void show(@NonNull Fragment parent, @NonNull String tag)
{
FragmentManager fm = mFragmentManagerStrategy.resolve(parent);
@ -46,10 +58,14 @@ public class AlertDialog extends BaseMwmDialogFragment
transaction.commitAllowingStateLoss();
}
private void onClick(int which)
@LayoutRes
protected int getLayoutId()
{
if (mTargetCallback != null)
mTargetCallback.onAlertDialogPositiveClick(getArguments().getInt(ARG_REQ_CODE), which);
throw new UnsupportedOperationException("By default, you" +
"shouldn't implement this method." +
" AlertDialog.Builder will do everything itself. " +
"But if you want to use this method, " +
"you'll have to implement it");
}
@Override
@ -84,17 +100,23 @@ public class AlertDialog extends BaseMwmDialogFragment
if (args == null)
throw new IllegalArgumentException("Arguments must be non null!");
int titleId = args.getInt(ARG_TITLE_ID);
int messageId = args.getInt(ARG_MESSAGE_ID);
int positiveButtonId = args.getInt(ARG_POSITIVE_BUTTON_ID);
int negativeButtonId = args.getInt(ARG_NEGATIVE_BUTTON_ID);
android.support.v7.app.AlertDialog.Builder builder =
DialogUtils.buildAlertDialog(getContext(), titleId, messageId);
builder.setPositiveButton(positiveButtonId, mPositiveClickListener);
if (negativeButtonId != UNDEFINED_BUTTON_ID)
builder.setNegativeButton(negativeButtonId, (dialog, which) -> onNegativeClicked(which));
initStrategies(args);
return mDialogViewStrategy.createView(this, args);
}
return builder.show();
private void initStrategies(@NonNull Bundle args)
{
int fragManagerStrategyIndex = args.getInt(ARG_DIALOG_VIEW_STRATEGY_INDEX, INVALID_ID);
mFragmentManagerStrategy = FragManagerStrategyType.values()[fragManagerStrategyIndex].getValue();
int dialogViewStrategyIndex = args.getInt(ARG_DIALOG_VIEW_STRATEGY_INDEX, INVALID_ID);
mDialogViewStrategy = DialogViewStrategyType.values()[dialogViewStrategyIndex].getValue();
}
private void onPositiveClicked(int which)
{
if (mTargetCallback != null)
mTargetCallback.onAlertDialogPositiveClick(getArguments().getInt(ARG_REQ_CODE), which);
}
private void onNegativeClicked(int which)
@ -120,9 +142,18 @@ public class AlertDialog extends BaseMwmDialogFragment
args.putInt(ARG_POSITIVE_BUTTON_ID, builder.getPositiveBtnId());
args.putInt(ARG_NEGATIVE_BUTTON_ID, builder.getNegativeBtnId());
args.putInt(ARG_REQ_CODE, builder.getReqCode());
AlertDialog dialog = new AlertDialog();
args.putInt(ARG_IMAGE_RES_ID, builder.getImageResId());
FragManagerStrategyType fragManagerStrategyType = builder.getFragManagerStrategyType();
args.putInt(ARG_FRAGMENT_MANAGER_STRATEGY_INDEX, fragManagerStrategyType.ordinal());
DialogViewStrategyType dialogViewStrategyType = builder.getDialogViewStrategyType();
args.putInt(ARG_DIALOG_VIEW_STRATEGY_INDEX, dialogViewStrategyType.ordinal());
AlertDialog dialog = builder.getDialogFactory().createDialog();
dialog.setArguments(args);
dialog.setFragmentManagerStrategy(builder.getFragManagerStrategy());
dialog.setFragmentManagerStrategy(fragManagerStrategyType.getValue());
dialog.setDialogViewStrategy(dialogViewStrategyType.getValue());
return dialog;
}
@ -131,6 +162,11 @@ public class AlertDialog extends BaseMwmDialogFragment
mFragmentManagerStrategy = strategy;
}
private void setDialogViewStrategy(@NonNull ResolveDialogViewStrategy strategy)
{
mDialogViewStrategy = strategy;
}
public static class Builder
{
private int mReqCode;
@ -141,9 +177,16 @@ public class AlertDialog extends BaseMwmDialogFragment
@StringRes
private int mPositiveBtn;
@StringRes
private int mNegativeBtn = UNDEFINED_BUTTON_ID;
private int mNegativeBtn = INVALID_ID;
@DrawableRes
private int mImageResId;
@NonNull
private ResolveFragmentManagerStrategy mFragManagerStrategy = new ChildFragmentManagerStrategy();
private FragManagerStrategyType mFragManagerStrategyType = FragManagerStrategyType.DEFAULT;
@NonNull
private DialogViewStrategyType mDialogViewStrategyType = DialogViewStrategyType.DEFAULT;
@NonNull
private DialogFactory mDialogFactory = new DefaultDialogFactory();
@NonNull
public Builder setReqCode(int reqCode)
@ -210,16 +253,42 @@ public class AlertDialog extends BaseMwmDialogFragment
}
@NonNull
public Builder setFragManagerStrategy(@NonNull ResolveFragmentManagerStrategy fragManagerStrategy)
public Builder setImageResId(@DrawableRes int imageResId)
{
mFragManagerStrategy = fragManagerStrategy;
mImageResId = imageResId;
return this;
}
@DrawableRes
public int getImageResId()
{
return mImageResId;
}
@NonNull
public Builder setFragManagerStrategyType(@NonNull FragManagerStrategyType strategyType)
{
mFragManagerStrategyType = strategyType;
return this;
}
@NonNull
ResolveFragmentManagerStrategy getFragManagerStrategy()
public Builder setDialogViewStrategyType(@NonNull DialogViewStrategyType strategyType)
{
return mFragManagerStrategy;
mDialogViewStrategyType = strategyType;
return this;
}
@NonNull
public DialogViewStrategyType getDialogViewStrategyType()
{
return mDialogViewStrategyType;
}
@NonNull
FragManagerStrategyType getFragManagerStrategyType()
{
return mFragManagerStrategyType;
}
@NonNull
@ -227,9 +296,22 @@ public class AlertDialog extends BaseMwmDialogFragment
{
return createDialog(this);
}
@NonNull
public Builder setDialogFactory(@NonNull DialogFactory dialogFactory)
{
mDialogFactory = dialogFactory;
return this;
}
@NonNull
DialogFactory getDialogFactory()
{
return mDialogFactory;
}
}
public static class ChildFragmentManagerStrategy implements ResolveFragmentManagerStrategy
private static class ChildFragmentManagerStrategy implements ResolveFragmentManagerStrategy
{
@NonNull
@Override
@ -239,7 +321,7 @@ public class AlertDialog extends BaseMwmDialogFragment
}
}
public static class ActivityFragmentManagerStrategy implements ResolveFragmentManagerStrategy
private static class ActivityFragmentManagerStrategy implements ResolveFragmentManagerStrategy
{
@NonNull
@Override
@ -248,4 +330,102 @@ public class AlertDialog extends BaseMwmDialogFragment
return baseFragment.getActivity().getSupportFragmentManager();
}
}
private static class AlertDialogStrategy implements ResolveDialogViewStrategy
{
@NonNull
@Override
public Dialog createView(@NonNull AlertDialog instance, @NonNull Bundle args)
{
int titleId = args.getInt(ARG_TITLE_ID);
int messageId = args.getInt(ARG_MESSAGE_ID);
int positiveButtonId = args.getInt(ARG_POSITIVE_BUTTON_ID);
int negativeButtonId = args.getInt(ARG_NEGATIVE_BUTTON_ID);
android.support.v7.app.AlertDialog.Builder builder =
DialogUtils.buildAlertDialog(instance.getContext(), titleId, messageId);
builder.setPositiveButton(positiveButtonId,
(dialog, which) -> instance.onPositiveClicked(which));
if (negativeButtonId != INVALID_ID)
builder.setNegativeButton(negativeButtonId,
(dialog, which) -> instance.onNegativeClicked(which));
return builder.show();
}
}
private static class ConfirmationDialogStrategy implements ResolveDialogViewStrategy
{
@NonNull
@Override
public Dialog createView(@NonNull AlertDialog fragment, @NonNull Bundle args)
{
AppCompatDialog appCompatDialog = new AppCompatDialog(fragment.getContext());
LayoutInflater inflater = LayoutInflater.from(fragment.getContext());
View root = inflater.inflate(fragment.getLayoutId(), null, false);
TextView declineBtn = root.findViewById(R.id.decline_btn);
declineBtn.setText(args.getInt(ARG_NEGATIVE_BUTTON_ID));
declineBtn.setOnClickListener(
v -> fragment.onNegativeClicked(DialogInterface.BUTTON_NEGATIVE));
TextView acceptBtn = root.findViewById(R.id.accept_btn);
acceptBtn.setText(args.getInt(ARG_POSITIVE_BUTTON_ID));
acceptBtn.setOnClickListener(
v -> fragment.onPositiveClicked(DialogInterface.BUTTON_POSITIVE));
TextView descriptionView = root.findViewById(R.id.description);
descriptionView.setText(args.getInt(ARG_MESSAGE_ID));
TextView titleView = root.findViewById(R.id.title);
titleView.setText(args.getInt(ARG_TITLE_ID));
ImageView imageView = root.findViewById(R.id.image);
boolean hasImage = args.containsKey(ARG_IMAGE_RES_ID);
imageView.setImageResource(hasImage ? args.getInt(ARG_IMAGE_RES_ID)
: R.drawable.ic_error_36px);
UiUtils.showIf(hasImage, imageView);
appCompatDialog.setContentView(root);
return appCompatDialog;
}
}
public enum FragManagerStrategyType
{
DEFAULT(new ChildFragmentManagerStrategy()),
ACTIVITY_FRAGMENT_MANAGER(new ActivityFragmentManagerStrategy());
@NonNull
private final ResolveFragmentManagerStrategy mStrategy;
FragManagerStrategyType(@NonNull ResolveFragmentManagerStrategy strategy)
{
mStrategy = strategy;
}
@NonNull
private ResolveFragmentManagerStrategy getValue()
{
return mStrategy;
}
}
public enum DialogViewStrategyType
{
DEFAULT(new AlertDialogStrategy()),
CONFIRMATION_DIALOG(new ConfirmationDialogStrategy());
@NonNull
private final ResolveDialogViewStrategy mStrategy;
DialogViewStrategyType(@NonNull ResolveDialogViewStrategy strategy)
{
mStrategy = strategy;
}
@NonNull
private ResolveDialogViewStrategy getValue()
{
return mStrategy;
}
}
}

View file

@ -0,0 +1,13 @@
package com.mapswithme.maps.dialog;
import android.support.annotation.NonNull;
public class ConfirmationDialogFactory implements DialogFactory
{
@NonNull
@Override
public AlertDialog createDialog()
{
return new DefaultConfirmationAlertDialog();
}
}

View file

@ -0,0 +1,12 @@
package com.mapswithme.maps.dialog;
import com.mapswithme.maps.R;
public class DefaultConfirmationAlertDialog extends AlertDialog
{
@Override
protected int getLayoutId()
{
return R.layout.fragment_confirmation;
}
}

View file

@ -0,0 +1,13 @@
package com.mapswithme.maps.dialog;
import android.support.annotation.NonNull;
class DefaultDialogFactory implements DialogFactory
{
@NonNull
@Override
public AlertDialog createDialog()
{
return new AlertDialog();
}
}

View file

@ -0,0 +1,9 @@
package com.mapswithme.maps.dialog;
import android.support.annotation.NonNull;
public interface DialogFactory
{
@NonNull
AlertDialog createDialog();
}

View file

@ -0,0 +1,11 @@
package com.mapswithme.maps.dialog;
import android.app.Dialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
public interface ResolveDialogViewStrategy
{
@NonNull
Dialog createView(@NonNull AlertDialog dialog, @NonNull Bundle args);
}

View file

@ -213,7 +213,7 @@ public class UgcRoutePropertiesFragment extends BaseMwmFragment implements Bookm
.setPositiveBtnId(R.string.try_again)
.setNegativeBtnId(R.string.cancel)
.setReqCode(REQ_CODE_LOAD_FAILED)
.setFragManagerStrategy(new AlertDialog.ActivityFragmentManagerStrategy())
.setFragManagerStrategyType(AlertDialog.FragManagerStrategyType.ACTIVITY_FRAGMENT_MANAGER)
.build();
dialog.setTargetFragment(this, REQ_CODE_LOAD_FAILED);
dialog.show(this, ERROR_LOADING_DIALOG_TAG);

View file

@ -109,7 +109,7 @@ public class UgcRouteTagsFragment extends BaseMwmFragment implements BookmarkMan
.setPositiveBtnId(R.string.try_again)
.setNegativeBtnId(R.string.cancel)
.setReqCode(ERROR_LOADING_DIALOG_REQ_CODE)
.setFragManagerStrategy(new AlertDialog.ActivityFragmentManagerStrategy())
.setFragManagerStrategyType(AlertDialog.FragManagerStrategyType.ACTIVITY_FRAGMENT_MANAGER)
.build();
dialog.setTargetFragment(this, ERROR_LOADING_DIALOG_REQ_CODE);
dialog.show(this, ERROR_LOADING_DIALOG_TAG);

View file

@ -31,6 +31,7 @@ import com.mapswithme.maps.bookmarks.data.CatalogTag;
import com.mapswithme.maps.bookmarks.data.CatalogTagsGroup;
import com.mapswithme.maps.dialog.AlertDialog;
import com.mapswithme.maps.dialog.AlertDialogCallback;
import com.mapswithme.maps.dialog.ConfirmationDialogFactory;
import com.mapswithme.maps.dialog.ProgressDialogFragment;
import com.mapswithme.maps.widget.ToolbarController;
import com.mapswithme.util.ConnectionState;
@ -51,6 +52,7 @@ public class UgcSharingOptionsFragment extends BaseMwmAuthorizationFragment impl
private static final int REQ_CODE_ERROR_EDITED_ON_WEB_DIALOG = 105;
private static final int REQ_CODE_ERROR_COMMON = 106;
private static final int REQ_CODE_ERROR_NOT_ENOUGH_BOOKMARKS = 107;
private static final int REQ_CODE_UPLOAD_CONFIRMATION_DIALOG = 108;
private static final String BUNDLE_CURRENT_MODE = "current_mode";
private static final String UPLOADING_PROGRESS_DIALOG_TAG = "uploading_progress_dialog";
private static final String NO_NETWORK_CONNECTION_DIALOG_TAG = "no_network_connection_dialog";
@ -58,6 +60,7 @@ public class UgcSharingOptionsFragment extends BaseMwmAuthorizationFragment impl
private static final String ERROR_BROKEN_FILE_DIALOG_TAG = "error_broken_file_dialog";
private static final String ERROR_EDITED_ON_WEB_DIALOG_REQ_TAG = "error_edited_on_web_dialog";
private static final String ERROR_COMMON_DIALOG_TAG = "error_common_dialog";
private static final String UPLOAD_CONFIRMATION_DIALOG_TAG = "upload_confirmation_dialog";
@SuppressWarnings("NullableProblems")
@NonNull
@ -223,7 +226,7 @@ public class UgcSharingOptionsFragment extends BaseMwmAuthorizationFragment impl
.setMessageId(R.string.common_check_internet_connection_dialog)
.setPositiveBtnId(R.string.try_again)
.setNegativeBtnId(R.string.cancel)
.setFragManagerStrategy(new AlertDialog.ActivityFragmentManagerStrategy())
.setFragManagerStrategyType(AlertDialog.FragManagerStrategyType.ACTIVITY_FRAGMENT_MANAGER)
.setReqCode(REQ_CODE_NO_NETWORK_CONNECTION_DIALOG)
.build();
dialog.setTargetFragment(this, REQ_CODE_NO_NETWORK_CONNECTION_DIALOG);
@ -512,7 +515,7 @@ public class UgcSharingOptionsFragment extends BaseMwmAuthorizationFragment impl
.setMessageId(subtitle)
.setPositiveBtnId(R.string.ok)
.setReqCode(reqCode)
.setFragManagerStrategy(new AlertDialog.ActivityFragmentManagerStrategy())
.setFragManagerStrategyType(AlertDialog.FragManagerStrategyType.ACTIVITY_FRAGMENT_MANAGER)
.build();
dialog.setTargetFragment(this, reqCode);
dialog.show(this, tag);
@ -542,4 +545,22 @@ public class UgcSharingOptionsFragment extends BaseMwmAuthorizationFragment impl
{
}
private void showUploadCatalogConfirmationDialog()
{
/*FIXME text later*/
AlertDialog dialog = new AlertDialog.Builder()
.setTitleId(R.string.common_check_internet_connection_dialog_title)
.setMessageId(R.string.common_check_internet_connection_dialog)
.setPositiveBtnId(R.string.try_again)
.setNegativeBtnId(R.string.cancel)
.setReqCode(REQ_CODE_UPLOAD_CONFIRMATION_DIALOG)
.setImageResId(R.drawable.ic_error_36px)
.setFragManagerStrategyType(AlertDialog.FragManagerStrategyType.ACTIVITY_FRAGMENT_MANAGER)
.setDialogViewStrategyType(AlertDialog.DialogViewStrategyType.CONFIRMATION_DIALOG)
.setDialogFactory(new ConfirmationDialogFactory())
.build();
dialog.setTargetFragment(this, REQ_CODE_UPLOAD_CONFIRMATION_DIALOG);
dialog.show(this, UPLOAD_CONFIRMATION_DIALOG_TAG);
}
}