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:background="@android:color/transparent">
<LinearLayout
<net.osmand.plus.mapcontextmenu.InterceptorLinearLayout
android:id="@+id/context_menu_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -19,7 +19,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/bg_map_context_menu"
android:clickable="true"
android:orientation="vertical">
<LinearLayout
@ -398,7 +397,6 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?selectableItemBackground"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:paddingBottom="@dimen/context_menu_main_actions_padding_bottom"
@ -581,7 +579,7 @@
android:foreground="@drawable/bg_contextmenu_shadow"
android:foregroundGravity="top|fill_horizontal">
<ScrollView
<net.osmand.plus.LockableScrollView
android:id="@+id/context_menu_bottom_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -596,10 +594,11 @@
</LinearLayout>
</ScrollView>
</net.osmand.plus.LockableScrollView>
</FrameLayout>
</LinearLayout>
</net.osmand.plus.mapcontextmenu.InterceptorLinearLayout>
<FrameLayout
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.QuadPoint;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.LockableScrollView;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
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 int ZOOM_IN_STANDARD = 17;
public static final int CURRENT_Y_UNDEFINED = Integer.MAX_VALUE;
private View view;
private View mainView;
private InterceptorLinearLayout mainView;
private View zoomButtonsView;
private ImageButton zoomInButtonView;
private ImageButton zoomOutButtonView;
@ -246,6 +249,7 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
final View.OnTouchListener slideTouchListener = new View.OnTouchListener() {
private float dy;
private float dyMain;
private float mDownY;
private VelocityTracker velocity;
private boolean slidingUp;
private boolean slidingDown;
@ -257,35 +261,40 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
@Override
public boolean onTouch(View v, MotionEvent event) {
if (singleTapDetector.onTouchEvent(event)) {
moving = false;
if (hasMoved) {
applyPosY(getViewY(), false, false, 0, 0, 0);
if (event.getY() <= menuTopViewHeight) {
if (singleTapDetector.onTouchEvent(event)) {
moving = false;
if (hasMoved) {
applyPosY(getViewY(), false, false, 0, 0, 0);
}
openMenuHalfScreen();
return true;
}
openMenuHalfScreen();
return true;
}
if (menu.isLandscapeLayout()) {
if (swipeDetector.onTouchEvent(event)) {
menu.close();
if (menu.isLandscapeLayout()) {
if (swipeDetector.onTouchEvent(event)) {
menu.close();
}
return true;
}
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
hasMoved = false;
mDownY = event.getRawY();
dy = event.getY();
dyMain = getViewY();
velocity = VelocityTracker.obtain();
velocityY = 0;
maxVelocityY = 0;
velocity.addMovement(event);
moving = true;
break;
case MotionEvent.ACTION_MOVE:
if (Math.abs(event.getRawY() - mDownY) > mainView.getTouchSlop()) {
moving = true;
}
if (moving) {
hasMoved = true;
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);
AndroidUtils.setBackground(getMapActivity(), topShadowAllView, nightMode, R.drawable.bg_map_context_menu_light,
R.drawable.bg_map_context_menu_dark);
topShadowAllView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getY() <= dpToPx(SHADOW_HEIGHT_TOP_DP) || event.getAction() != MotionEvent.ACTION_DOWN)
return slideTouchListener.onTouch(v, event);
else
return false;
}
});
((InterceptorLinearLayout) mainView).setListener(slideTouchListener);
mainView.setOnTouchListener(slideTouchListener);
buildHeader();
@ -507,7 +508,9 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
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));
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));
@ -659,7 +662,7 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
private void applyPosY(final int currentY, final boolean needCloseMenu, boolean needMapAdjust,
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 (posY < currentY) {
updateMainViewLayout(posY);
@ -897,12 +900,6 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
if (view != null) {
View bottomView = view.findViewById(R.id.context_menu_bottom_view);
if (menu.isExtended()) {
bottomView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
menu.build(bottomView);
}
}
@ -1244,10 +1241,10 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
}
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) {
return screenHeight;
}
@ -1272,8 +1269,23 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
posY = Math.max(posY, minHalfY);
break;
case MenuState.FULL_SCREEN:
posY = -dpToPx(SHADOW_HEIGHT_TOP_DP);
posY = addStatusBarHeightIfNeeded(posY);
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 = addStatusBarHeightIfNeeded(posY);
}
break;
default:
break;