speed cameras alert ui

This commit is contained in:
veliymolfar 2020-06-05 18:22:15 +03:00
parent 9a4a2ee34e
commit 3c14562baf
11 changed files with 288 additions and 2 deletions

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="@dimen/content_padding">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:src="@drawable/img_speed_camera_warning" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding"
android:text="@string/speed_camera_pois"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/dialog_header_text_size"
osmand:typeface="@string/font_roboto_medium" />
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
tools:text="@string/speed_cameras_legal_descr" />
</LinearLayout>

View file

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/preference_switch" />
<LinearLayout
android:id="@+id/alert_bg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding_half"
android:gravity="center_vertical"
android:orientation="horizontal"
tools:background="?attr/activity_background_basic">
<ImageView
android:id="@+id/alert_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/bottom_sheet_image_text_margin_start"
android:layout_marginLeft="@dimen/bottom_sheet_image_text_margin_start"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
tools:src="@drawable/ic_action_alert"
tools:tint="@color/icon_color_default_dark" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding_small"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding_small"
android:orientation="vertical">
<TextView
android:id="@+id/alert_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/content_padding_small"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
tools:text="@string/speed_cameras_alert" />
<TextView
android:id="@+id/alert_subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/default_list_text_size"
tools:text="@string/read_more" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -11,6 +11,16 @@
Thx - Hardy Thx - Hardy
--> -->
<string name="speed_cameras_alert">Speed cameras alerts in some countries is prohibited by the law.</string>
<string name="shared_string_uninstall">Uninstall</string>
<string name="keep_active">Keep active</string>
<string name="speed_cameras_legal_descr">In some countries or regions, the use of speed camera warning applications is prohibited by law.
\n\nYou need to make a choice depending on the law of your country.
\n\nSelect %1$s and you will receive alerts and warnings about speed cameras.
\n\nSelect %2$s. All data related to speed cameras: alerts, notifications, POIs will be deleted until OsmAnd is completely reinstalled.</string>
<string name="speed_camera_pois">Speed camera POIs</string>
<string name="shared_string_legal">Legal</string>
<string name="uninstall_speed_cameras">Uninstall speed cameras</string>
<string name="screen_timeout">Screen timeout</string> <string name="screen_timeout">Screen timeout</string>
<string name="delete_all_actions_message_q">Are you sure you want to irrevocably delete %d quick actions?</string> <string name="delete_all_actions_message_q">Are you sure you want to irrevocably delete %d quick actions?</string>
<string name="shared_string_delete_all_q">Delete all?</string> <string name="shared_string_delete_all_q">Delete all?</string>

View file

@ -60,4 +60,15 @@
app:fragment="net.osmand.plus.settings.fragments.ProxySettingsFragment" app:fragment="net.osmand.plus.settings.fragments.ProxySettingsFragment"
tools:icon="@drawable/ic_action_proxy" /> tools:icon="@drawable/ic_action_proxy" />
<PreferenceCategory
android:key="legal"
android:layout="@layout/preference_category_with_descr"
android:title="@string/shared_string_legal" />
<Preference
android:key="uninstall_speed_cameras"
android:layout="@layout/preference_with_descr"
android:title="@string/uninstall_speed_cameras"
tools:icon="@drawable/ic_speed_camera_disabled" />
</PreferenceScreen> </PreferenceScreen>

View file

@ -28,7 +28,7 @@
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:key="show_cameras" android:key="show_cameras"
android:layout="@layout/preference_switch" android:layout="@layout/preference_switch_with_alert"
android:title="@string/show_cameras" /> android:title="@string/show_cameras" />
<SwitchPreferenceCompat <SwitchPreferenceCompat

View file

@ -46,7 +46,7 @@
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:key="speak_cameras" android:key="speak_cameras"
android:layout="@layout/preference_switch" android:layout="@layout/preference_switch_with_alert"
android:title="@string/speak_cameras" /> android:title="@string/speak_cameras" />
<SwitchPreferenceCompat <SwitchPreferenceCompat

View file

@ -1,10 +1,12 @@
package net.osmand.plus; package net.osmand.plus;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.RippleDrawable; import android.graphics.drawable.RippleDrawable;
import android.hardware.Sensor; import android.hardware.Sensor;
@ -12,6 +14,8 @@ import android.hardware.SensorManager;
import android.os.Build; import android.os.Build;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.view.Gravity; import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -31,6 +35,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat; import androidx.core.graphics.drawable.DrawableCompat;
@ -46,12 +51,16 @@ import net.osmand.AndroidUtils;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.views.DirectionDrawable; import net.osmand.plus.views.DirectionDrawable;
import net.osmand.plus.widgets.TextViewEx; import net.osmand.plus.widgets.TextViewEx;
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import java.lang.ref.WeakReference;
import gnu.trove.map.hash.TLongObjectHashMap; import gnu.trove.map.hash.TLongObjectHashMap;
public class UiUtilities { public class UiUtilities {
@ -645,4 +654,29 @@ public class UiUtilities {
return spannable; return spannable;
} }
} }
public static SpannableString setWordsMediumFont(@NonNull Context ctx, @NonNull String text, @NonNull String... textToStyle) {
SpannableString spannable = new SpannableString(text);
for (String t : textToStyle) {
try {
int startIndex = text.indexOf(t);
spannable.setSpan(
new CustomTypefaceSpan(FontCache.getRobotoMedium(ctx)),
startIndex,
startIndex + t.length(),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
} catch (RuntimeException e) {
LOG.error("Error trying to find index of " + t + " " + e);
}
}
return spannable;
}
public static GradientDrawable getRoundedBackgroundDrawable(@NonNull Context context, @ColorRes int colorRes, int radius) {
int r = AndroidUtils.dpToPx(context, radius);
GradientDrawable background = new GradientDrawable();
background.setColor(ContextCompat.getColor(context, colorRes));
background.setCornerRadius(r);
return background;
}
} }

View file

@ -0,0 +1,70 @@
package net.osmand.plus.dialogs;
import android.os.Bundle;
import android.text.SpannableString;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
public class SpeedCamerasBottomSheet extends MenuBottomSheetDialogFragment {
public static final String TAG = SpeedCamerasBottomSheet.class.getName();
private OsmandApplication app;
public static void showInstance(@NonNull FragmentManager fm) {
if (!fm.isStateSaved()) {
SpeedCamerasBottomSheet bottomSheet = new SpeedCamerasBottomSheet();
bottomSheet.show(fm, TAG);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = requiredMyApplication();
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
View root = UiUtilities.getInflater(app, nightMode).inflate(R.layout.bottom_sheet_speed_cameras, null);
((ImageView) root.findViewById(R.id.icon)).setImageResource(R.drawable.img_speed_camera_warning);
((TextView) root.findViewById(R.id.description)).setText(getDescriptionText());
items.add(new BaseBottomSheetItem.Builder().setCustomView(root).create());
}
@Override
protected void onRightBottomButtonClick() {
super.onRightBottomButtonClick();
}
@Override
protected void onDismissButtonClickAction() {
super.onDismissButtonClickAction();
}
@Override
protected int getDismissButtonTextId() {
return R.string.shared_string_uninstall;
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.keep_active;
}
private SpannableString getDescriptionText() {
String keepActive = getString(R.string.keep_active);
String uninstall = getString(R.string.shared_string_uninstall);
String text = getString(R.string.speed_cameras_legal_descr, keepActive, uninstall);
return UiUtilities.setWordsMediumFont(app, text, keepActive, uninstall);
}
}

View file

@ -14,6 +14,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.activities.SettingsGeneralActivity; import net.osmand.plus.activities.SettingsGeneralActivity;
import net.osmand.plus.dialogs.SendAnalyticsBottomSheetDialogFragment; import net.osmand.plus.dialogs.SendAnalyticsBottomSheetDialogFragment;
import net.osmand.plus.dialogs.SpeedCamerasBottomSheet;
import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.preferences.ListPreferenceEx; import net.osmand.plus.settings.preferences.ListPreferenceEx;
@ -26,6 +27,7 @@ public class GlobalSettingsFragment extends BaseSettingsFragment implements Send
private static final String SEND_ANONYMOUS_DATA_PREF_ID = "send_anonymous_data"; private static final String SEND_ANONYMOUS_DATA_PREF_ID = "send_anonymous_data";
private static final String DIALOGS_AND_NOTIFICATIONS_PREF_ID = "dialogs_and_notifications"; private static final String DIALOGS_AND_NOTIFICATIONS_PREF_ID = "dialogs_and_notifications";
private static final String UNINSTALL_SPEED_CAMERAS_PREF_ID = "uninstall_speed_cameras";
@Override @Override
protected void setupPreferences() { protected void setupPreferences() {
@ -36,6 +38,7 @@ public class GlobalSettingsFragment extends BaseSettingsFragment implements Send
setupSendAnonymousDataPref(); setupSendAnonymousDataPref();
setupDialogsAndNotificationsPref(); setupDialogsAndNotificationsPref();
setupEnableProxyPref(); setupEnableProxyPref();
setupUninstallSpeedCamerasPref();
} }
@Override @Override
@ -108,6 +111,18 @@ public class GlobalSettingsFragment extends BaseSettingsFragment implements Send
setupSendAnonymousDataPref(); setupSendAnonymousDataPref();
} }
@Override
public boolean onPreferenceClick(Preference preference) {
String prefId = preference.getKey();
if (UNINSTALL_SPEED_CAMERAS_PREF_ID.equals(prefId)) {
FragmentManager fm = getFragmentManager();
if (fm != null) {
SpeedCamerasBottomSheet.showInstance(fm);
}
}
return super.onPreferenceClick(preference);
}
private void setupDefaultAppModePref() { private void setupDefaultAppModePref() {
OsmandApplication app = getMyApplication(); OsmandApplication app = getMyApplication();
if (app == null) { if (app == null) {
@ -191,4 +206,9 @@ public class GlobalSettingsFragment extends BaseSettingsFragment implements Send
SwitchPreferenceEx enableProxy = (SwitchPreferenceEx) findPreference(settings.ENABLE_PROXY.getId()); SwitchPreferenceEx enableProxy = (SwitchPreferenceEx) findPreference(settings.ENABLE_PROXY.getId());
enableProxy.setIcon(getPersistentPrefIcon(R.drawable.ic_action_proxy)); enableProxy.setIcon(getPersistentPrefIcon(R.drawable.ic_action_proxy));
} }
private void setupUninstallSpeedCamerasPref() {
Preference uninstallSpeedCameras = (Preference) findPreference(UNINSTALL_SPEED_CAMERAS_PREF_ID);
uninstallSpeedCameras.setIcon(getPersistentPrefIcon(R.drawable.ic_speed_camera_disabled));
}
} }

View file

@ -6,19 +6,26 @@ import android.os.Build;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder; import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreferenceCompat; import androidx.preference.SwitchPreferenceCompat;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.dialogs.SpeedCamerasBottomSheet;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities;
import java.lang.ref.WeakReference;
import static net.osmand.plus.UiUtilities.CompoundButtonType.TOOLBAR; import static net.osmand.plus.UiUtilities.CompoundButtonType.TOOLBAR;
public class ScreenAlertsFragment extends BaseSettingsFragment { public class ScreenAlertsFragment extends BaseSettingsFragment {
@ -27,6 +34,7 @@ public class ScreenAlertsFragment extends BaseSettingsFragment {
private static final String SHOW_ROUTING_ALARMS_INFO = "show_routing_alarms_info"; private static final String SHOW_ROUTING_ALARMS_INFO = "show_routing_alarms_info";
private static final String SCREEN_ALERTS_IMAGE = "screen_alerts_image"; private static final String SCREEN_ALERTS_IMAGE = "screen_alerts_image";
private static final String SHOW_CAMERAS = "show_cameras";
@Override @Override
protected void setupPreferences() { protected void setupPreferences() {
@ -103,6 +111,8 @@ public class ScreenAlertsFragment extends BaseSettingsFragment {
deviceImage.setImageDrawable(getDeviceImage()); deviceImage.setImageDrawable(getDeviceImage());
warningIcon.setImageDrawable(getWarningIcon()); warningIcon.setImageDrawable(getWarningIcon());
} else if (SHOW_CAMERAS.equals(key)) {
setupSpeedCamerasAlert(app, requireMyActivity(), holder, isNightMode());
} }
} }
} }
@ -144,4 +154,36 @@ public class ScreenAlertsFragment extends BaseSettingsFragment {
return null; return null;
} }
public static void setupSpeedCamerasAlert(OsmandApplication app, FragmentActivity activity, PreferenceViewHolder holder, boolean nightMode) {
ImageView alertIcon = (ImageView) holder.itemView.findViewById(R.id.alert_icon);
TextView alertTitle = (TextView) holder.itemView.findViewById(R.id.alert_title);
TextView alertSubTitle = (TextView) holder.itemView.findViewById(R.id.alert_subtitle);
LinearLayout alertBg = (LinearLayout) holder.itemView.findViewById(R.id.alert_bg);
alertBg.setBackgroundDrawable(UiUtilities.getRoundedBackgroundDrawable(
app,
nightMode ? R.color.activity_background_color_dark : R.color.activity_background_color_light,
6));
alertIcon.setImageDrawable(app.getUIUtilities().getIcon(
R.drawable.ic_action_alert,
nightMode ? R.color.icon_color_default_dark : R.color.icon_color_default_light));
alertTitle.setText(R.string.speed_cameras_alert);
alertTitle.setTypeface(FontCache.getRobotoMedium(app));
alertSubTitle.setText(R.string.read_more);
alertSubTitle.setTypeface(FontCache.getRobotoMedium(app));
alertSubTitle.setTextColor(nightMode
? app.getResources().getColor(R.color.active_color_primary_dark)
: app.getResources().getColor(R.color.active_color_primary_light));
final WeakReference<FragmentActivity> weakActivity = new WeakReference<>(activity);
alertSubTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FragmentActivity a = weakActivity.get();
if (a != null) {
SpeedCamerasBottomSheet.showInstance(a.getSupportFragmentManager());
}
}
});
}
} }

View file

@ -252,6 +252,8 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment {
Object currentValue = ((ListPreferenceEx) preference).getValue(); Object currentValue = ((ListPreferenceEx) preference).getValue();
imageView.setEnabled(preference.isEnabled() && !OsmandSettings.VOICE_PROVIDER_NOT_USE.equals(currentValue)); imageView.setEnabled(preference.isEnabled() && !OsmandSettings.VOICE_PROVIDER_NOT_USE.equals(currentValue));
} }
} else if (settings.SPEAK_SPEED_CAMERA.getId().equals(preference.getKey())) {
ScreenAlertsFragment.setupSpeedCamerasAlert(app, requireMyActivity(), holder, isNightMode());
} }
} }