Merge pull request #1542 from GaidamakUA/dashboard_swipe_to_dismiss

Mostly fixes, and polishyng
This commit is contained in:
Yurii Mazurevich 2015-08-07 17:31:02 +03:00
commit 129edf1196
9 changed files with 205 additions and 53 deletions

View file

@ -5,12 +5,17 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/list_header_height"
android:paddingLeft="@dimen/dialog_content_margin"
android:paddingRight="@dimen/dialog_content_margin"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/text"
style="@style/DashboardSubHeader"
osmand:typeface="@string/font_roboto_medium"
android:layout_marginLeft="0dp"
android:textColor="@color/dashboard_black"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="@string/lorem_ipsum"/>
<include

View file

@ -2227,4 +2227,6 @@ Afghanistan, Albania, Algeria, Andorra, Angola, Anguilla, Antigua and Barbuda, A
<string name="try_again">Try again</string>
<string name="error_message_pattern">Error: {0}</string>
<string name="dahboard_options_dialog_title">Dashboard options</string>
<string name="shared_string_card_was_hidden">Card was hidden</string>
<string name="shared_string_undo">UNDO</string>
</resources>

View file

@ -15,6 +15,7 @@ import android.widget.FrameLayout;
import net.osmand.plus.OsmAndAppCustomization;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.widgets.InterceptorFrameLayout;
import net.osmand.plus.widgets.tools.SwipeDismissTouchListener;
@ -73,8 +74,6 @@ public abstract class DashBaseFragment extends Fragment {
public void onDismiss(View view, Object token, boolean isSwipeRight) {
if (isSwipeRight) {
getDismissCallback().onDismiss();
} else {
// TODO show settings card
}
}
});
@ -158,7 +157,7 @@ public abstract class DashBaseFragment extends Fragment {
private DismissListener defaultDismissListener;
private static class DefaultDismissListener implements DismissListener {
public static class DefaultDismissListener implements DismissListener {
private View parentView;
private DashboardOnMap dashboardOnMap;
private String fragmentTag;
@ -177,15 +176,15 @@ public abstract class DashBaseFragment extends Fragment {
dashboardOnMap.blacklistFragmentByTag(fragmentTag);
ViewCompat.setTranslationX(fragmentView, 0);
ViewCompat.setAlpha(fragmentView, 1);
Snackbar.make(parentView, "Card was hidden", Snackbar.LENGTH_LONG)
.setAction("UNDO", new View.OnClickListener() {
Snackbar.make(parentView, dashboardOnMap.getMyApplication().getResources()
.getString(R.string.shared_string_card_was_hidden), Snackbar.LENGTH_LONG)
.setAction(R.string.shared_string_undo, new View.OnClickListener() {
@Override
public void onClick(View view) {
DefaultDismissListener.this.onUndo();
}
})
.show();
}
public void onUndo() {

View file

@ -7,6 +7,8 @@ import android.graphics.Typeface;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -14,6 +16,7 @@ import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.Version;
@ -31,6 +34,8 @@ public class DashErrorFragment extends DashBaseFragment {
public static final String TAG = "DASH_ERROR_FRAGMENT";
private DismissListener dismissCallback;
@Override
public View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = getActivity().getLayoutInflater().inflate(R.layout.dash_error_fragment, container, false);
@ -47,7 +52,7 @@ public class DashErrorFragment extends DashBaseFragment {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, new String[] { "crash@osmand.net" }); //$NON-NLS-1$
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"crash@osmand.net"}); //$NON-NLS-1$
File file = getMyApplication().getAppPath(OsmandApplication.EXCEPTION_PATH);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
intent.setType("vnd.android.cursor.dir/email"); //$NON-NLS-1$
@ -67,6 +72,7 @@ public class DashErrorFragment extends DashBaseFragment {
text.append("\nApk Version : ").append(info.versionName).append(" ").append(info.versionCode); //$NON-NLS-1$ //$NON-NLS-2$
}
} catch (PackageManager.NameNotFoundException e) {
PlatformUtil.getLog(DashErrorFragment.class).error("", e);
}
intent.putExtra(Intent.EXTRA_TEXT, text.toString());
startActivity(Intent.createChooser(intent, getString(R.string.send_report)));
@ -85,10 +91,53 @@ public class DashErrorFragment extends DashBaseFragment {
}
}
});
dismissCallback = new ErrorDismissListener(getParentView(), dashboard, TAG, view);
return view;
}
@Override
public void onOpenDash() {
}
@Override
public DismissListener getDismissCallback() {
return dismissCallback;
}
private static class ErrorDismissListener implements DismissListener {
private View parentView;
private DashboardOnMap dashboardOnMap;
private String fragmentTag;
private View fragmentView;
public ErrorDismissListener(View parentView, DashboardOnMap dashboardOnMap,
String fragmentTag, View fragmentView) {
this.parentView = parentView;
this.dashboardOnMap = dashboardOnMap;
this.fragmentTag = fragmentTag;
this.fragmentView = fragmentView;
}
@Override
public void onDismiss() {
dashboardOnMap.hideFragmentByTag(fragmentTag);
ViewCompat.setTranslationX(fragmentView, 0);
ViewCompat.setAlpha(fragmentView, 1);
Snackbar.make(parentView, dashboardOnMap.getMyApplication().getResources()
.getString(R.string.shared_string_card_was_hidden), Snackbar.LENGTH_LONG)
.setAction(R.string.shared_string_undo, new View.OnClickListener() {
@Override
public void onClick(View view) {
ErrorDismissListener.this.onUndo();
}
})
.show();
}
public void onUndo() {
dashboardOnMap.unhideFragmentByTag(fragmentTag);
ViewCompat.setTranslationX(fragmentView, 0);
ViewCompat.setAlpha(fragmentView, 1);
}
}
}

View file

@ -5,6 +5,8 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@ -24,14 +26,13 @@ import java.util.Calendar;
*/
public class DashRateUsFragment extends DashBaseFragment {
public static final String TAG = "DASH_RATE_US_FRAGMENT";
// TODO move to resources
public static final String EMAIL = "support@osmand.net";
// Imported in shouldShow method
private static OsmandSettings settings;
private FragmentState state = FragmentState.INITIAL_STATE;
private RateUsDismissListener mRateUsDismissListener;
@Override
public void onOpenDash() {
@ -48,6 +49,7 @@ public class DashRateUsFragment extends DashBaseFragment {
new PositiveButtonListener(header, subheader, positiveButton, negativeButton));
negativeButton.setOnClickListener(
new NegativeButtonListener(header, subheader, positiveButton, negativeButton));
mRateUsDismissListener = new RateUsDismissListener(getParentView(), dashboard, TAG, view, settings);
return view;
}
@ -102,13 +104,15 @@ public class DashRateUsFragment extends DashBaseFragment {
// Initial state now
modifiedTime.add(Calendar.HOUR, -72);
bannerFreeRuns = 3;
if (modifiedTime.after(lastDisplayTime) && numberOfApplicationRuns >= bannerFreeRuns) {
toReturn = true;
}
return toReturn;
return modifiedTime.after(lastDisplayTime) && numberOfApplicationRuns >= bannerFreeRuns;
}
public class PositiveButtonListener implements View.OnClickListener {
@Override
public DismissListener getDismissCallback() {
return mRateUsDismissListener;
}
public class PositiveButtonListener implements View.OnClickListener {
private TextView header;
private TextView subheader;
private Button positiveButton;
@ -222,4 +226,52 @@ public class DashRateUsFragment extends DashBaseFragment {
&& super.shouldShow(settings, activity, tag);
}
}
private static class RateUsDismissListener implements DismissListener {
private View parentView;
private DashboardOnMap dashboardOnMap;
private String fragmentTag;
private View fragmentView;
private OsmandSettings settings;
private int exNumberOfRuns;
private long exLastDisplayTime;
public RateUsDismissListener(View parentView, DashboardOnMap dashboardOnMap,
String fragmentTag, View fragmentView, OsmandSettings settings) {
this.parentView = parentView;
this.dashboardOnMap = dashboardOnMap;
this.fragmentTag = fragmentTag;
this.fragmentView = fragmentView;
this.settings = settings;
}
@Override
public void onDismiss() {
dashboardOnMap.hideFragmentByTag(fragmentTag);
ViewCompat.setTranslationX(fragmentView, 0);
ViewCompat.setAlpha(fragmentView, 1);
Snackbar.make(parentView, dashboardOnMap.getMyApplication().getResources()
.getString(R.string.shared_string_card_was_hidden), Snackbar.LENGTH_LONG)
.setAction(R.string.shared_string_undo, new View.OnClickListener() {
@Override
public void onClick(View view) {
RateUsDismissListener.this.onUndo(exNumberOfRuns, exLastDisplayTime);
}
})
.show();
settings.RATE_US_STATE.set(RateUsState.IGNORED);
exNumberOfRuns = settings.NUMBER_OF_APPLICATION_STARTS.get();
settings.NUMBER_OF_APPLICATION_STARTS.set(0);
exLastDisplayTime = settings.LAST_DISPLAY_TIME.get();
settings.LAST_DISPLAY_TIME.set(System.currentTimeMillis());
}
public void onUndo(int numberOfRuns, long lastDisplayTime) {
dashboardOnMap.unhideFragmentByTag(fragmentTag);
ViewCompat.setTranslationX(fragmentView, 0);
ViewCompat.setAlpha(fragmentView, 1);
settings.NUMBER_OF_APPLICATION_STARTS.set(numberOfRuns);
settings.LAST_DISPLAY_TIME.set(lastDisplayTime);
}
}
}

View file

@ -82,15 +82,15 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks {
private static final DashFragmentData.ShouldShowFunction rateUsShouldShow = new DashRateUsFragment.RateUsShouldShow();
private static final DefaultShouldShow defaultShouldShow = new DefaultShouldShow();
private static final DefaultShouldShow errorShouldShow = new ErrorShouldShow();
private static final DefaultShouldShow firstTimeShouldShow = new FirstTimeShouldShow();
private static final DashFragmentData.ShouldShowFunction firstTimeShouldShow = new FirstTimeShouldShow();
private static final DefaultShouldShow simulateShouldShow = new SimulateShouldShow();
private static final DashFragmentData.ShouldShowFunction chooseAppDirShouldShow = new ChooseAppDirShouldShow();
private static final DashFragmentData[] fragmentsData = new DashFragmentData[]{
new DashFragmentData(DashRateUsFragment.TAG, DashRateUsFragment.class, "Rate us", rateUsShouldShow),
new DashFragmentData(DashFirstTimeFragment.TAG, DashFirstTimeFragment.class, "First time", firstTimeShouldShow),
new DashFragmentData(DashChooseAppDirFragment.TAG, DashChooseAppDirFragment.class, "Choose app dir", chooseAppDirShouldShow),
new DashFragmentData(DashErrorFragment.TAG, DashErrorFragment.class, "Error", errorShouldShow),
new DashFragmentData(DashRateUsFragment.TAG, DashRateUsFragment.class, "Rate us", rateUsShouldShow, true),
new DashFragmentData(DashFirstTimeFragment.TAG, DashFirstTimeFragment.class, "First time", firstTimeShouldShow, true),
new DashFragmentData(DashChooseAppDirFragment.TAG, DashChooseAppDirFragment.class, "Choose app dir", chooseAppDirShouldShow, true),
new DashFragmentData(DashErrorFragment.TAG, DashErrorFragment.class, "Error", errorShouldShow, true),
new DashFragmentData(DashNavigationFragment.TAG, DashNavigationFragment.class, "Navigation", defaultShouldShow),
new DashFragmentData(DashParkingFragment.TAG, DashParkingFragment.class, "Parking", defaultShouldShow),
new DashFragmentData(DashWaypointsFragment.TAG, DashWaypointsFragment.class, "Waypoints", defaultShouldShow),
@ -117,7 +117,7 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks {
private DashboardType visibleType;
private DashboardType previousVisibleType;
private boolean landscape;
private List<WeakReference<DashBaseFragment>> fragList = new LinkedList<WeakReference<DashBaseFragment>>();
private List<WeakReference<DashBaseFragment>> fragList = new LinkedList<>();
private net.osmand.Location myLocation;
private LatLon mapViewLocation;
private float heading;
@ -246,7 +246,7 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks {
lst.setVisibility(View.GONE);
ImageView back = (ImageView) dashboardView.findViewById(R.id.toolbar_back);
back.setImageDrawable(
((OsmandApplication) getMyApplication()).getIconsCache().getIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha));
getMyApplication().getIconsCache().getIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha));
back.setOnClickListener(new View.OnClickListener() {
@Override
@ -466,7 +466,7 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks {
scrollView.setVisibility(View.GONE);
listViewLayout.setVisibility(View.VISIBLE);
if (listView instanceof ObservableListView) {
onScrollChanged(((ObservableListView) listView).getScrollY(), false, false);
onScrollChanged(listView.getScrollY(), false, false);
}
if (refresh) {
refreshContent(false);
@ -600,7 +600,7 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks {
hideDashboard(false);
final Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization()
.getDownloadIndexActivity());
intent.putExtra(DownloadActivity.FILTER_KEY, f.toString());
intent.putExtra(DownloadActivity.FILTER_KEY, f);
intent.putExtra(DownloadActivity.TAB_TO_OPEN, DownloadActivity.DOWNLOAD_TAB);
mapActivity.startActivity(intent);
}
@ -824,9 +824,9 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks {
gradientToolbar.setAlpha((int) ((1 - t) * 255));
setAlpha(dashboardView, (int) (t * 128), 0);
if (t < 1) {
((Toolbar) dashboardView.findViewById(R.id.toolbar)).setBackgroundDrawable(gradientToolbar);
dashboardView.findViewById(R.id.toolbar).setBackgroundDrawable(gradientToolbar);
} else {
((Toolbar) dashboardView.findViewById(R.id.toolbar)).setBackgroundColor(0xff000000 | baseColor);
dashboardView.findViewById(R.id.toolbar).setBackgroundColor(0xff000000 | baseColor);
}
}
}
@ -905,23 +905,29 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks {
}
public void blacklistFragmentByTag(String tag) {
FragmentManager manager = mapActivity.getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment frag = manager.findFragmentByTag(tag);
transaction.hide(frag).commit();
hideFragmentByTag(tag);
getMyApplication().getSettings().registerBooleanPreference(SHOULD_SHOW + tag, true)
.makeGlobal().set(false);
}
public void hideFragmentByTag(String tag) {
FragmentManager manager = mapActivity.getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment frag = manager.findFragmentByTag(tag);
transaction.hide(frag).commit();
}
public void unblacklistFragmentClass(String tag) {
unhideFragmentByTag(tag);
getMyApplication().getSettings().registerBooleanPreference(SHOULD_SHOW + tag, true)
.makeGlobal().set(true);
}
public void unhideFragmentByTag(String tag) {
FragmentManager manager = mapActivity.getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment frag = manager.findFragmentByTag(tag);
transaction.show(frag).commit();
getMyApplication().getSettings().registerBooleanPreference(SHOULD_SHOW + tag, true)
.makeGlobal().set(true);
}
View getParentView() {
@ -935,11 +941,8 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks {
public static class SettingsShouldShow implements DashFragmentData.ShouldShowFunction {
@Override
public boolean shouldShow(OsmandSettings settings, MapActivity activity, String tag) {
Log.v(TAG, "shouldShow(" + "settings=" + settings + ", activity=" + activity + ", tag=" + tag + ")");
boolean shouldShow = settings.registerBooleanPreference(SHOULD_SHOW + tag, true)
return settings.registerBooleanPreference(SHOULD_SHOW + tag, true)
.makeGlobal().get();
Log.v(TAG, "shouldShow=" + shouldShow);
return shouldShow;
}
}
public static class DefaultShouldShow extends SettingsShouldShow {
@ -958,10 +961,11 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks {
}
}
private static class FirstTimeShouldShow extends DefaultShouldShow {
private static class FirstTimeShouldShow extends SettingsShouldShow {
@Override
public boolean shouldShow(OsmandSettings settings, MapActivity activity, String tag) {
return !super.shouldShow(settings, activity, tag);
return activity.getMyApplication().getAppInitializer().isFirstTime(activity)
&& super.shouldShow(settings, activity, tag);
}
}

View file

@ -9,6 +9,17 @@ public final class DashFragmentData {
public final Class<? extends DashBaseFragment> fragmentClass;
public final String title;
public final ShouldShowFunction shouldShowFunction;
public final boolean customDeletionLogic;
public DashFragmentData(String tag, Class<? extends DashBaseFragment> fragmentClass,
String title, ShouldShowFunction shouldShowFunction,
boolean customDeletionLogic) {
this.tag = tag;
this.fragmentClass = fragmentClass;
this.title = title;
this.shouldShowFunction = shouldShowFunction;
this.customDeletionLogic = customDeletionLogic;
}
public DashFragmentData(String tag, Class<? extends DashBaseFragment> fragmentClass,
String title, ShouldShowFunction shouldShowFunction) {
@ -16,6 +27,7 @@ public final class DashFragmentData {
this.fragmentClass = fragmentClass;
this.title = title;
this.shouldShowFunction = shouldShowFunction;
customDeletionLogic = false;
}
public interface ShouldShowFunction {

View file

@ -20,15 +20,23 @@ import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dashboard.DashboardOnMap;
import java.util.ArrayList;
public class DashboardSettingsDialogFragment extends DialogFragment {
private static final String CHECKED_ITEMS = "checked_items";
private MapActivity mapActivity;
private DashFragmentData[] fragmentsData;
private DashFragmentAdapter adapter;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mapActivity = (MapActivity) activity;
fragmentsData = mapActivity.getDashboard().getFragmentsData();
ArrayList<DashFragmentData> fragmentsList = new ArrayList<>();
for(DashFragmentData fragmentData : mapActivity.getDashboard().getFragmentsData()) {
if (!fragmentData.customDeletionLogic) fragmentsList.add(fragmentData);
}
fragmentsData = fragmentsList.toArray(new DashFragmentData[fragmentsList.size()]);
}
@NonNull
@ -36,9 +44,13 @@ public class DashboardSettingsDialogFragment extends DialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final OsmandSettings settings = mapActivity.getMyApplication().getSettings();
final DashFragmentAdapter adapter =
new DashFragmentAdapter(getActivity(), fragmentsData,
settings);
if (savedInstanceState != null && savedInstanceState.containsKey(CHECKED_ITEMS)) {
adapter = new DashFragmentAdapter(getActivity(), fragmentsData,
savedInstanceState.getBooleanArray(CHECKED_ITEMS));
} else {
adapter = new DashFragmentAdapter(getActivity(), fragmentsData,
settings);
}
builder.setTitle(R.string.dahboard_options_dialog_title)
.setAdapter(adapter, null)
.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
@ -52,14 +64,25 @@ public class DashboardSettingsDialogFragment extends DialogFragment {
}
mapActivity.getDashboard().refreshDashboardFragments();
}
});
final AlertDialog dialog = builder.create();
return dialog;
})
.setNegativeButton(R.string.shared_string_cancel, null);
return builder.create();
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putBooleanArray(CHECKED_ITEMS, adapter.getCheckedItems());
super.onSaveInstanceState(outState);
}
private static class DashFragmentAdapter extends ArrayAdapter<DashFragmentData> {
private final boolean[] checkedItems;
public DashFragmentAdapter(Context context, DashFragmentData[] objects, boolean[] checkedItems) {
super(context, 0, objects);
this.checkedItems = checkedItems;
}
public DashFragmentAdapter(Context context, DashFragmentData[] objects, OsmandSettings settings) {
super(context, 0, objects);
checkedItems = new boolean[objects.length];
@ -83,16 +106,21 @@ public class DashboardSettingsDialogFragment extends DialogFragment {
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
Integer position = (Integer) compoundButton.getTag();
checkedItems[position] = b;
DashViewHolder localViewHolder = (DashViewHolder) compoundButton.getTag();
checkedItems[localViewHolder.position] = b;
localViewHolder.textView.setTextColor(
checkedItems[localViewHolder.position] ? 0xFF212121
: 0xFF8c8c8c);
}
});
} else {
viewHolder = (DashViewHolder) convertView.getTag();
}
viewHolder.compoundButton.setTag(position);
viewHolder.position = position;
viewHolder.compoundButton.setTag(viewHolder);
viewHolder.compoundButton.setChecked(checkedItems[position]);
viewHolder.textView.setText(dashFragmentData.title);
viewHolder.textView.setTextColor(checkedItems[position] ? 0xFF212121 : 0xFF8c8c8c);
convertView.setTag(viewHolder);
return convertView;
}
@ -104,6 +132,7 @@ public class DashboardSettingsDialogFragment extends DialogFragment {
private class DashViewHolder {
TextView textView;
CompoundButton compoundButton;
int position;
}
}
}