Context menu states in progress

This commit is contained in:
Alexey Kulish 2018-01-28 21:24:28 +03:00
parent 90ce687568
commit 2547b4b020
4 changed files with 198 additions and 42 deletions

View file

@ -8,7 +8,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@android:color/transparent"> android:background="@android:color/transparent">
<LinearLayout <net.osmand.plus.mapcontextmenu.InterceptorLinearLayout
android:id="@+id/context_menu_main" android:id="@+id/context_menu_main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -19,7 +19,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/bg_map_context_menu" android:background="?attr/bg_map_context_menu"
android:clickable="true"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
@ -398,7 +397,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:background="?selectableItemBackground" android:background="?selectableItemBackground"
android:clickable="true"
android:gravity="center" android:gravity="center"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="@dimen/context_menu_main_actions_padding_bottom" android:paddingBottom="@dimen/context_menu_main_actions_padding_bottom"
@ -581,7 +579,7 @@
android:foreground="@drawable/bg_contextmenu_shadow" android:foreground="@drawable/bg_contextmenu_shadow"
android:foregroundGravity="top|fill_horizontal"> android:foregroundGravity="top|fill_horizontal">
<ScrollView <net.osmand.plus.LockableScrollView
android:id="@+id/context_menu_bottom_scroll" android:id="@+id/context_menu_bottom_scroll"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -596,10 +594,11 @@
</LinearLayout> </LinearLayout>
</ScrollView> </net.osmand.plus.LockableScrollView>
</FrameLayout> </FrameLayout>
</LinearLayout> </net.osmand.plus.mapcontextmenu.InterceptorLinearLayout>
<FrameLayout <FrameLayout
android:id="@+id/context_menu_fab_container" android:id="@+id/context_menu_fab_container"

View file

@ -0,0 +1,56 @@
package net.osmand.plus;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ScrollView;
public class LockableScrollView extends ScrollView {
// true if we can scroll (not locked)
// false if we cannot scroll (locked)
private boolean mScrollable = true;
public LockableScrollView(Context context) {
super(context);
}
public LockableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollingEnabled(boolean enabled) {
mScrollable = enabled;
}
public boolean isScrollable() {
return mScrollable;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// if we can scroll pass the event to the superclass
if (mScrollable) {
return super.onTouchEvent(ev);
}
// only continue to handle the touch event if scrolling enabled
return mScrollable;
default:
return super.onTouchEvent(ev);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Don't do anything with intercepted touch events if
// we are not scrollable
if (!mScrollable) {
return false;
} else {
return super.onInterceptTouchEvent(ev);
}
}
}

View file

@ -0,0 +1,89 @@
package net.osmand.plus.mapcontextmenu;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.LinearLayout;
public class InterceptorLinearLayout extends LinearLayout {
private int mTouchSlop;
private boolean mIsScrolling;
private float mDownY;
private OnTouchListener listener;
public InterceptorLinearLayout(Context context) {
this(context, null);
}
public InterceptorLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
ViewConfiguration vc = ViewConfiguration.get(context);
mTouchSlop = vc.getScaledTouchSlop();
}
public InterceptorLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
ViewConfiguration vc = ViewConfiguration.get(context);
mTouchSlop = vc.getScaledTouchSlop();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public InterceptorLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
ViewConfiguration vc = ViewConfiguration.get(context);
mTouchSlop = vc.getScaledTouchSlop();
}
public int getTouchSlop() {
return mTouchSlop;
}
public boolean isScrolling() {
return mIsScrolling;
}
public void setListener(OnTouchListener listener) {
this.listener = listener;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean handled = false;
final int action = ev.getAction();
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
mIsScrolling = false;
handled = false;
} else {
switch (action) {
case MotionEvent.ACTION_DOWN:
mIsScrolling = false;
mDownY = ev.getRawY();
handled = false;
case MotionEvent.ACTION_MOVE:
if (mIsScrolling) {
handled = true;
} else {
final int yDiff = calculateDistanceY(ev);
if (Math.abs(yDiff) > mTouchSlop) {
mIsScrolling = true;
handled = true;
}
}
break;
}
}
if (listener != null) {
listener.onTouch(this, ev);
}
return handled;
}
private int calculateDistanceY(MotionEvent ev) {
return (int) (ev.getRawY() - mDownY);
}
}

View file

@ -37,6 +37,7 @@ import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
import net.osmand.data.QuadPoint; import net.osmand.data.QuadPoint;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.plus.LockableScrollView;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
@ -71,8 +72,10 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
public static final float SKIP_HALF_SCREEN_STATE_KOEF = .21f; public static final float SKIP_HALF_SCREEN_STATE_KOEF = .21f;
public static final int ZOOM_IN_STANDARD = 17; public static final int ZOOM_IN_STANDARD = 17;
public static final int CURRENT_Y_UNDEFINED = Integer.MAX_VALUE;
private View view; private View view;
private View mainView; private InterceptorLinearLayout mainView;
private View zoomButtonsView; private View zoomButtonsView;
private ImageButton zoomInButtonView; private ImageButton zoomInButtonView;
private ImageButton zoomOutButtonView; private ImageButton zoomOutButtonView;
@ -246,6 +249,7 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
final View.OnTouchListener slideTouchListener = new View.OnTouchListener() { final View.OnTouchListener slideTouchListener = new View.OnTouchListener() {
private float dy; private float dy;
private float dyMain; private float dyMain;
private float mDownY;
private VelocityTracker velocity; private VelocityTracker velocity;
private boolean slidingUp; private boolean slidingUp;
private boolean slidingDown; private boolean slidingDown;
@ -257,6 +261,7 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
if (event.getY() <= menuTopViewHeight) {
if (singleTapDetector.onTouchEvent(event)) { if (singleTapDetector.onTouchEvent(event)) {
moving = false; moving = false;
if (hasMoved) { if (hasMoved) {
@ -272,20 +277,24 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
} }
return true; return true;
} }
}
switch (event.getAction()) { switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
hasMoved = false; hasMoved = false;
mDownY = event.getRawY();
dy = event.getY(); dy = event.getY();
dyMain = getViewY(); dyMain = getViewY();
velocity = VelocityTracker.obtain(); velocity = VelocityTracker.obtain();
velocityY = 0; velocityY = 0;
maxVelocityY = 0; maxVelocityY = 0;
velocity.addMovement(event); velocity.addMovement(event);
moving = true;
break; break;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
if (Math.abs(event.getRawY() - mDownY) > mainView.getTouchSlop()) {
moving = true;
}
if (moving) { if (moving) {
hasMoved = true; hasMoved = true;
float y = event.getY(); float y = event.getY();
@ -328,20 +337,12 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
} }
}; };
View topView = view.findViewById(R.id.context_menu_top_view);
topView.setOnTouchListener(slideTouchListener);
View topShadowAllView = view.findViewById(R.id.context_menu_top_shadow_all); View topShadowAllView = view.findViewById(R.id.context_menu_top_shadow_all);
AndroidUtils.setBackground(getMapActivity(), topShadowAllView, nightMode, R.drawable.bg_map_context_menu_light, AndroidUtils.setBackground(getMapActivity(), topShadowAllView, nightMode, R.drawable.bg_map_context_menu_light,
R.drawable.bg_map_context_menu_dark); R.drawable.bg_map_context_menu_dark);
topShadowAllView.setOnTouchListener(new View.OnTouchListener() {
@Override ((InterceptorLinearLayout) mainView).setListener(slideTouchListener);
public boolean onTouch(View v, MotionEvent event) { mainView.setOnTouchListener(slideTouchListener);
if (event.getY() <= dpToPx(SHADOW_HEIGHT_TOP_DP) || event.getAction() != MotionEvent.ACTION_DOWN)
return slideTouchListener.onTouch(v, event);
else
return false;
}
});
buildHeader(); buildHeader();
@ -507,7 +508,9 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
buildBottomView(); buildBottomView();
view.findViewById(R.id.context_menu_bottom_scroll).setBackgroundColor(getResources() LockableScrollView bottomScrollView = (LockableScrollView) view.findViewById(R.id.context_menu_bottom_scroll);
bottomScrollView.setScrollingEnabled(false);
bottomScrollView.setBackgroundColor(getResources()
.getColor(nightMode ? R.color.ctx_menu_bottom_view_bg_dark : R.color.ctx_menu_bottom_view_bg_light)); .getColor(nightMode ? R.color.ctx_menu_bottom_view_bg_dark : R.color.ctx_menu_bottom_view_bg_light));
view.findViewById(R.id.context_menu_bottom_view).setBackgroundColor(getResources() view.findViewById(R.id.context_menu_bottom_view).setBackgroundColor(getResources()
.getColor(nightMode ? R.color.ctx_menu_bottom_view_bg_dark : R.color.ctx_menu_bottom_view_bg_light)); .getColor(nightMode ? R.color.ctx_menu_bottom_view_bg_dark : R.color.ctx_menu_bottom_view_bg_light));
@ -659,7 +662,7 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
private void applyPosY(final int currentY, final boolean needCloseMenu, boolean needMapAdjust, private void applyPosY(final int currentY, final boolean needCloseMenu, boolean needMapAdjust,
final int previousMenuState, final int newMenuState, int dZoom) { final int previousMenuState, final int newMenuState, int dZoom) {
final int posY = getPosY(needCloseMenu); final int posY = getPosY(currentY, needCloseMenu);
if (currentY != posY || dZoom != 0) { if (currentY != posY || dZoom != 0) {
if (posY < currentY) { if (posY < currentY) {
updateMainViewLayout(posY); updateMainViewLayout(posY);
@ -897,12 +900,6 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
if (view != null) { if (view != null) {
View bottomView = view.findViewById(R.id.context_menu_bottom_view); View bottomView = view.findViewById(R.id.context_menu_bottom_view);
if (menu.isExtended()) { if (menu.isExtended()) {
bottomView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
menu.build(bottomView); menu.build(bottomView);
} }
} }
@ -1244,10 +1241,10 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
} }
private int getPosY() { private int getPosY() {
return getPosY(false); return getPosY(CURRENT_Y_UNDEFINED, false);
} }
private int getPosY(boolean needCloseMenu) { private int getPosY(final int currentY, boolean needCloseMenu) {
if (needCloseMenu) { if (needCloseMenu) {
return screenHeight; return screenHeight;
} }
@ -1272,8 +1269,23 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
posY = Math.max(posY, minHalfY); posY = Math.max(posY, minHalfY);
break; break;
case MenuState.FULL_SCREEN: case MenuState.FULL_SCREEN:
if (currentY != CURRENT_Y_UNDEFINED) {
int maxPosY = viewHeight - menuFullHeightMax;
int minPosY = Math.max(maxPosY, minHalfY);
if (maxPosY > minPosY) {
maxPosY = minPosY;
}
if (currentY > minPosY) {
posY = minPosY;
} else if (currentY < maxPosY) {
posY = maxPosY;
} else {
posY = currentY;
}
} else {
posY = -dpToPx(SHADOW_HEIGHT_TOP_DP); posY = -dpToPx(SHADOW_HEIGHT_TOP_DP);
posY = addStatusBarHeightIfNeeded(posY); posY = addStatusBarHeightIfNeeded(posY);
}
break; break;
default: default:
break; break;