From 76f7e284c8b1d7e5d33f0b80427d2a818aa332c4 Mon Sep 17 00:00:00 2001 From: Alexey Kulish Date: Mon, 11 Jan 2016 18:27:12 +0300 Subject: [PATCH] Fix - no dividers between Waypoint rows --- .../osmand/plus/dashboard/DashboardOnMap.java | 5 +- .../plus/helpers/WaypointDialogHelper.java | 90 +++++++++++++++++++ .../MapContextMenuFragment.java | 51 ++++++----- .../plus/views/controls/DynamicListView.java | 46 ++++++++++ .../plus/views/controls/ListDividerShape.java | 59 ++++++++++++ .../views/controls/StableArrayAdapter.java | 22 ++++- 6 files changed, 245 insertions(+), 28 deletions(-) create mode 100644 OsmAnd/src/net/osmand/plus/views/controls/ListDividerShape.java diff --git a/OsmAnd/src/net/osmand/plus/dashboard/DashboardOnMap.java b/OsmAnd/src/net/osmand/plus/dashboard/DashboardOnMap.java index c226bcb3f1..31ceb787bf 100644 --- a/OsmAnd/src/net/osmand/plus/dashboard/DashboardOnMap.java +++ b/OsmAnd/src/net/osmand/plus/dashboard/DashboardOnMap.java @@ -224,6 +224,7 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks, DynamicLis stableAdapter.getObjects().remove(item); activeObjPos = stableAdapter.getActiveObjects().indexOf(item); stableAdapter.getActiveObjects().remove(item); + stableAdapter.refreshData(); stableAdapter.notifyDataSetChanged(); } else { @@ -240,7 +241,7 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks, DynamicLis stableAdapter.insert(item, position); stableAdapter.getObjects().add(position, item); stableAdapter.getActiveObjects().add(activeObjPos, item); - stableAdapter.updateIdMap(); + stableAdapter.refreshData(); onItemsSwapped(stableAdapter.getActiveObjects()); } @@ -252,7 +253,7 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks, DynamicLis public void onHidePopup() { if (listAdapter instanceof StableArrayAdapter) { StableArrayAdapter stableAdapter = (StableArrayAdapter) listAdapter; - stableAdapter.updateIdMap(); + stableAdapter.refreshData(); onItemsSwapped(stableAdapter.getActiveObjects()); } } diff --git a/OsmAnd/src/net/osmand/plus/helpers/WaypointDialogHelper.java b/OsmAnd/src/net/osmand/plus/helpers/WaypointDialogHelper.java index cfb130a2d0..b604345791 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/WaypointDialogHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/WaypointDialogHelper.java @@ -1,9 +1,14 @@ package net.osmand.plus.helpers; import android.app.Activity; +import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnDismissListener; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.Shape; import android.os.AsyncTask; import android.support.v4.app.FragmentActivity; import android.support.v7.app.AlertDialog; @@ -30,6 +35,7 @@ import net.osmand.plus.activities.IntermediatePointsDialog; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.WaypointHelper.LocationPointWrapper; import net.osmand.plus.poi.PoiUIFilter; +import net.osmand.plus.views.controls.ListDividerShape; import net.osmand.plus.views.controls.StableArrayAdapter; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; @@ -161,6 +167,85 @@ public class WaypointDialogHelper { return activePoints; } + private List getCustomDividers(Context ctx, List points, boolean nightMode) { + int color; + int pointColor; + if (nightMode) { + color = ctx.getResources().getColor(R.color.dashboard_divider_dark); + pointColor = ctx.getResources().getColor(R.color.dashboard_divider_dark); + } else { + color = ctx.getResources().getColor(R.color.dashboard_divider_light); + pointColor = ctx.getResources().getColor(R.color.ctx_menu_info_divider_light); + } + + Shape fullDividerShape = new ListDividerShape(color, 0); + Shape halfDividerShape = new ListDividerShape(color, AndroidUtils.dpToPx(ctx, 56f)); + Shape halfPointDividerShape = new ListDividerShape(color, AndroidUtils.dpToPx(ctx, 56f), + pointColor, AndroidUtils.dpToPx(ctx, 1.5f), true); + Shape headerDividerShape = new ListDividerShape(color, AndroidUtils.dpToPx(ctx, 16f)); + + final ShapeDrawable fullDivider = new ShapeDrawable(fullDividerShape); + final ShapeDrawable halfDivider = new ShapeDrawable(halfDividerShape); + final ShapeDrawable halfPointDivider = new ShapeDrawable(halfPointDividerShape); + final ShapeDrawable headerDivider = new ShapeDrawable(headerDividerShape); + final Drawable startingPointDivider = app.getIconsCache().getIcon(R.drawable.bg_shadow_list_bottom); + + int divHeight = AndroidUtils.dpToPx(ctx, 1f); + fullDivider.setIntrinsicHeight(divHeight); + halfDivider.setIntrinsicHeight(divHeight); + halfPointDivider.setIntrinsicHeight(divHeight); + headerDivider.setIntrinsicHeight(divHeight); + + List res = new ArrayList<>(); + for (int i = 0; i < points.size(); i++) { + Object obj = points.get(i); + Object objNext = i + 1 < points.size() ? points.get(i + 1) : null; + + if (objNext == null) { + break; + } + + boolean labelView = (obj instanceof Integer); + boolean bottomDividerViewNext = (objNext instanceof Boolean) && !((Boolean) objNext); + + boolean locationPoint = (obj instanceof LocationPointWrapper); + boolean locationPointNext = (objNext instanceof LocationPointWrapper); + + Drawable d = null; + + if (locationPointNext) { + if (locationPoint) { + LocationPointWrapper w = (LocationPointWrapper) obj; + if (w.type == WaypointHelper.TARGETS && ((TargetPoint) w.point).start) { + d = startingPointDivider; // starting point divider + } else { + if (w.type == WaypointHelper.TARGETS) { + d = halfPointDivider; + } else { + d = halfDivider; + } + } + } else { + LocationPointWrapper w = (LocationPointWrapper) objNext; + if (w.type == WaypointHelper.TARGETS) { + if (!((TargetPoint) w.point).start) { + d = fullDivider; + } + } else { + d = fullDivider; + } + } + } else if (objNext instanceof RadiusItem && labelView) { + d = headerDivider; + } else if (locationPoint && !bottomDividerViewNext) { + d = fullDivider; + } + + res.add(d); + } + return res; + } + public StableArrayAdapter getWaypointsDrawerAdapter( final boolean edit, final List deletedPoints, final MapActivity ctx, final int[] running, final boolean flat, final boolean nightMode) { @@ -176,6 +261,11 @@ public class WaypointDialogHelper { return new StableArrayAdapter(ctx, R.layout.waypoint_reached, R.id.title, points, activePoints) { + @Override + public void buildDividers() { + dividers = getCustomDividers(ctx, getObjects(), nightMode); + } + @Override public boolean isEnabled(int position) { Object obj = getItem(position); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java index 4250fd1783..a6163d1003 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java @@ -287,40 +287,43 @@ public class MapContextMenuFragment extends Fragment implements DownloadEvents { break; case MotionEvent.ACTION_MOVE: - hasMoved = true; - float y = event.getY(); - float newY = getViewY() + (y - dy); - setViewY((int) newY, false, false); + if (moving) { + hasMoved = true; + float y = event.getY(); + float newY = getViewY() + (y - dy); + setViewY((int) newY, false, false); - menuFullHeight = view.getHeight() - (int) newY + 10; - if (!oldAndroid()) { - ViewGroup.LayoutParams lp = mainView.getLayoutParams(); - lp.height = Math.max(menuFullHeight, menuTitleHeight); - mainView.setLayoutParams(lp); - mainView.requestLayout(); + menuFullHeight = view.getHeight() - (int) newY + 10; + if (!oldAndroid()) { + ViewGroup.LayoutParams lp = mainView.getLayoutParams(); + lp.height = Math.max(menuFullHeight, menuTitleHeight); + mainView.setLayoutParams(lp); + mainView.requestLayout(); + } + + velocity.addMovement(event); + velocity.computeCurrentVelocity(1000); + velocityY = Math.abs(velocity.getYVelocity()); + if (velocityY > maxVelocityY) + maxVelocityY = velocityY; } - velocity.addMovement(event); - velocity.computeCurrentVelocity(1000); - velocityY = Math.abs(velocity.getYVelocity()); - if (velocityY > maxVelocityY) - maxVelocityY = velocityY; - break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - moving = false; - int currentY = getViewY(); + if (moving) { + moving = false; + int currentY = getViewY(); - slidingUp = Math.abs(maxVelocityY) > 500 && (currentY - dyMain) < -50; - slidingDown = Math.abs(maxVelocityY) > 500 && (currentY - dyMain) > 50; + slidingUp = Math.abs(maxVelocityY) > 500 && (currentY - dyMain) < -50; + slidingDown = Math.abs(maxVelocityY) > 500 && (currentY - dyMain) > 50; - velocity.recycle(); - - boolean skipHalfScreenState = Math.abs(currentY - dyMain) > skipHalfScreenStateLimit; - changeMenuState(currentY, skipHalfScreenState, slidingUp, slidingDown); + velocity.recycle(); + boolean skipHalfScreenState = Math.abs(currentY - dyMain) > skipHalfScreenStateLimit; + changeMenuState(currentY, skipHalfScreenState, slidingUp, slidingDown); + } break; } diff --git a/OsmAnd/src/net/osmand/plus/views/controls/DynamicListView.java b/OsmAnd/src/net/osmand/plus/views/controls/DynamicListView.java index b4028c18c6..2c7f6efe07 100644 --- a/OsmAnd/src/net/osmand/plus/views/controls/DynamicListView.java +++ b/OsmAnd/src/net/osmand/plus/views/controls/DynamicListView.java @@ -27,6 +27,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; @@ -245,6 +246,51 @@ public class DynamicListView extends ObservableListView { if (mHoverCell != null) { mHoverCell.draw(canvas); } + + // Draw dividers + StableArrayAdapter stableAdapter = getStableAdapter(); + if (stableAdapter != null && stableAdapter.hasDividers()) { + List dividers = stableAdapter.getDividers(); + + final int count = getChildCount(); + final int first = getFirstVisiblePosition(); + final int headerCount = getHeaderViewsCount(); + final int itemCount = getCount(); + final int footerLimit = (itemCount - getFooterViewsCount()); + + final Rect bounds = new Rect(); + bounds.left = getPaddingLeft(); + bounds.right = getRight() - getLeft() - getPaddingRight(); + + final int listBottom = getBottom() - getTop() + getScrollY(); + for (int i = 0; i < count; i++) { + final int itemIndex = (first + i); + final boolean isHeader = (itemIndex < headerCount); + final boolean isFooter = (itemIndex >= footerLimit); + if (!isHeader && !isFooter && itemIndex < dividers.size()) { + Drawable divider = dividers.get(itemIndex - headerCount); + if (divider != null) { + final View child = getChildAt(i); + int bottom = child.getBottom(); + final boolean isLastItem = (i == (count - 1)); + + if (bottom < listBottom && !isLastItem) { + final int nextIndex = (itemIndex + 1); + if (nextIndex >= headerCount && nextIndex < footerLimit) { + bounds.top = bottom; + bounds.bottom = bottom + divider.getIntrinsicHeight(); + drawDivider(canvas, divider, bounds); + } + } + } + } + } + } + } + + void drawDivider(Canvas canvas, Drawable divider, Rect bounds) { + divider.setBounds(bounds); + divider.draw(canvas); } @Override diff --git a/OsmAnd/src/net/osmand/plus/views/controls/ListDividerShape.java b/OsmAnd/src/net/osmand/plus/views/controls/ListDividerShape.java new file mode 100644 index 0000000000..63471912d6 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/controls/ListDividerShape.java @@ -0,0 +1,59 @@ +package net.osmand.plus.views.controls; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.drawable.shapes.Shape; + +public class ListDividerShape extends Shape { + private RectF mRect = new RectF(); + private int lineColor; + private int paddingLeft; + private int pointColor; + private float pointRadius; + private boolean drawPoint; + + public ListDividerShape(int lineColor, int paddingLeft) { + this.lineColor = lineColor; + this.paddingLeft = paddingLeft; + this.pointColor = 0; + this.pointRadius = 0f; + this.drawPoint = false; + } + + public ListDividerShape(int lineColor, int paddingLeft, int pointColor, float pointRadius, boolean drawPoint) { + this.lineColor = lineColor; + this.paddingLeft = paddingLeft; + this.pointColor = pointColor; + this.pointRadius = pointRadius; + this.drawPoint = drawPoint; + } + + @Override + public void draw(Canvas canvas, Paint paint) { + paint.setColor(lineColor); + mRect.left = paddingLeft; + canvas.drawRect(mRect, paint); + if (paddingLeft > 0 && drawPoint) { + paint.setColor(pointColor); + canvas.drawCircle(paddingLeft / 2f, (mRect.bottom - mRect.top) / 2f, pointRadius, paint); + } + } + + @Override + protected void onResize(float width, float height) { + mRect.set(0, 0, width, height); + } + + @Override + public ListDividerShape clone() throws CloneNotSupportedException { + final ListDividerShape shape = (ListDividerShape) super.clone(); + shape.mRect = new RectF(mRect); + shape.lineColor = lineColor; + shape.paddingLeft = paddingLeft; + shape.pointColor = pointColor; + shape.pointRadius = pointRadius; + shape.drawPoint = drawPoint; + return shape; + } +} diff --git a/OsmAnd/src/net/osmand/plus/views/controls/StableArrayAdapter.java b/OsmAnd/src/net/osmand/plus/views/controls/StableArrayAdapter.java index c3c9f2d649..871ae0a768 100644 --- a/OsmAnd/src/net/osmand/plus/views/controls/StableArrayAdapter.java +++ b/OsmAnd/src/net/osmand/plus/views/controls/StableArrayAdapter.java @@ -1,6 +1,7 @@ package net.osmand.plus.views.controls; import android.content.Context; +import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.widget.ArrayAdapter; @@ -17,6 +18,7 @@ public class StableArrayAdapter extends ArrayAdapter { List objects; List activeObjects; HashMap mIdMap = new HashMap<>(); + protected List dividers; public StableArrayAdapter(Context context, int textViewResourceId, int titleId, List objects, List activeObjects) { @@ -32,13 +34,21 @@ public class StableArrayAdapter extends ArrayAdapter { return activeObjects; } + public List getDividers() { + return dividers; + } + + public boolean hasDividers() { + return dividers != null && dividers.size() > 0; + } + public void updateObjects(List objects, List activeObjects) { this.objects = objects; this.activeObjects = activeObjects; - updateIdMap(); + refreshData(); } - public void updateIdMap() { + private void updateIdMap() { HashMap idMap = new HashMap<>(); for (int i = 0; i < objects.size(); ++i) { idMap.put(objects.get(i), i); @@ -46,6 +56,14 @@ public class StableArrayAdapter extends ArrayAdapter { mIdMap = idMap; } + public void refreshData() { + updateIdMap(); + buildDividers(); + } + + public void buildDividers() { + } + @Override public Object getItem(int position) { return objects.get(position);