Merge pull request #5103 from osmandapp/scrollable_multiselection_menu
Scrollable multiselection menu
This commit is contained in:
commit
9bfc6a6d20
4 changed files with 111 additions and 50 deletions
|
@ -15,7 +15,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ListView
|
<com.github.ksoichiro.android.observablescrollview.ObservableListView
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="@dimen/bottom_sheet_content_padding_small"
|
android:paddingBottom="@dimen/bottom_sheet_content_padding_small"
|
||||||
android:id="@+id/list"
|
android:id="@+id/list"
|
||||||
|
|
|
@ -15,9 +15,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<ListView
|
<com.github.ksoichiro.android.observablescrollview.ObservableListView
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="@dimen/bottom_sheet_content_padding_small"
|
|
||||||
android:id="@+id/list"
|
android:id="@+id/list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
@ -35,7 +34,7 @@
|
||||||
android:id="@+id/cancel_row"
|
android:id="@+id/cancel_row"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/bottom_sheet_cancel_button_height"
|
android:layout_height="@dimen/bottom_sheet_cancel_button_height"
|
||||||
android:background="?attr/selectableItemBackground">
|
android:foreground="?attr/selectableItemBackground">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/cancel_row_text"
|
android:id="@+id/cancel_row_text"
|
||||||
|
|
|
@ -1,17 +1,27 @@
|
||||||
package net.osmand.plus.mapcontextmenu.other;
|
package net.osmand.plus.mapcontextmenu.other;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewTreeObserver;
|
||||||
|
import android.widget.AbsListView;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.github.ksoichiro.android.observablescrollview.ObservableListView;
|
||||||
|
import com.github.ksoichiro.android.observablescrollview.ObservableScrollViewCallbacks;
|
||||||
|
import com.github.ksoichiro.android.observablescrollview.ScrollState;
|
||||||
|
|
||||||
import net.osmand.AndroidUtils;
|
import net.osmand.AndroidUtils;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
|
@ -41,22 +51,103 @@ public class MapMultiSelectionMenuFragment extends Fragment implements MultiSele
|
||||||
AndroidUtils.setBackground(view.getContext(), view, !menu.isLight(),
|
AndroidUtils.setBackground(view.getContext(), view, !menu.isLight(),
|
||||||
R.drawable.multi_selection_menu_bg_light_land, R.drawable.multi_selection_menu_bg_dark_land);
|
R.drawable.multi_selection_menu_bg_light_land, R.drawable.multi_selection_menu_bg_dark_land);
|
||||||
} else {
|
} else {
|
||||||
AndroidUtils.setBackground(view.getContext(), view, !menu.isLight(),
|
AndroidUtils.setBackground(view.getContext(), view.findViewById(R.id.cancel_row), !menu.isLight(),
|
||||||
R.drawable.multi_selection_menu_bg_light, R.drawable.multi_selection_menu_bg_dark);
|
R.color.ctx_menu_bg_light, R.color.ctx_menu_bg_dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView listView = (ListView) view.findViewById(R.id.list);
|
final ListView listView = (ListView) view.findViewById(R.id.list);
|
||||||
if (menu.isLandscapeLayout() && Build.VERSION.SDK_INT >= 21) {
|
if (menu.isLandscapeLayout() && Build.VERSION.SDK_INT >= 21) {
|
||||||
AndroidUtils.addStatusBarPadding21v(getActivity(), listView);
|
AndroidUtils.addStatusBarPadding21v(getActivity(), listView);
|
||||||
}
|
}
|
||||||
View headerView = inflater.inflate(R.layout.menu_obj_selection_header, listView, false);
|
|
||||||
headerView.setOnClickListener(null);
|
|
||||||
listView.addHeaderView(headerView);
|
|
||||||
listAdapter = createAdapter();
|
listAdapter = createAdapter();
|
||||||
listAdapter.setListener(this);
|
listAdapter.setListener(this);
|
||||||
listView.setAdapter(listAdapter);
|
listView.setAdapter(listAdapter);
|
||||||
|
|
||||||
runLayoutListener();
|
if (!menu.isLandscapeLayout()) {
|
||||||
|
final Context context = getContext();
|
||||||
|
|
||||||
|
FrameLayout paddingView = new FrameLayout(context);
|
||||||
|
paddingView.setLayoutParams(new AbsListView.LayoutParams(
|
||||||
|
AbsListView.LayoutParams.MATCH_PARENT, getPaddingViewHeight())
|
||||||
|
);
|
||||||
|
paddingView.setClickable(true);
|
||||||
|
paddingView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
dismissMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
FrameLayout shadowContainer = new FrameLayout(context);
|
||||||
|
shadowContainer.setLayoutParams(new FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, Gravity.BOTTOM
|
||||||
|
));
|
||||||
|
|
||||||
|
ImageView shadow = new ImageView(context);
|
||||||
|
shadow.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.bg_shadow_onmap));
|
||||||
|
shadow.setLayoutParams(new FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM
|
||||||
|
));
|
||||||
|
shadow.setScaleType(ImageView.ScaleType.FIT_XY);
|
||||||
|
|
||||||
|
shadowContainer.addView(shadow);
|
||||||
|
paddingView.addView(shadowContainer);
|
||||||
|
listView.addHeaderView(paddingView);
|
||||||
|
|
||||||
|
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||||
|
@Override
|
||||||
|
public void onGlobalLayout() {
|
||||||
|
float titleHeight = getResources().getDimension(R.dimen.multi_selection_header_height);
|
||||||
|
int maxHeight = (int) (titleHeight);
|
||||||
|
for (int i = 0; i < 3 && i < listAdapter.getCount(); i++) {
|
||||||
|
View childView = listAdapter.getView(0, null, (ListView) view.findViewById(R.id.list));
|
||||||
|
childView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
|
||||||
|
maxHeight += childView.getMeasuredHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
listView.setSelectionFromTop(0, -maxHeight);
|
||||||
|
|
||||||
|
ViewTreeObserver obs = view.getViewTreeObserver();
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
obs.removeOnGlobalLayoutListener(this);
|
||||||
|
} else {
|
||||||
|
obs.removeGlobalOnLayoutListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
((ObservableListView) listView).setScrollViewCallbacks(new ObservableScrollViewCallbacks() {
|
||||||
|
|
||||||
|
boolean initialScroll = true;
|
||||||
|
int minHeight = getResources().getDimensionPixelSize(R.dimen.multi_selection_header_height)
|
||||||
|
+ getResources().getDimensionPixelSize(R.dimen.list_item_height);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
|
||||||
|
if (scrollY <= minHeight && !initialScroll) {
|
||||||
|
dismissMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDownMotionEvent() {
|
||||||
|
initialScroll = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpOrCancelMotionEvent(ScrollState scrollState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
View headerView = inflater.inflate(R.layout.menu_obj_selection_header, listView, false);
|
||||||
|
if (!menu.isLandscapeLayout()) {
|
||||||
|
AndroidUtils.setBackground(getContext(), headerView, !menu.isLight(), R.color.ctx_menu_bg_light, R.color.ctx_menu_bg_dark);
|
||||||
|
}
|
||||||
|
headerView.setOnClickListener(null);
|
||||||
|
listView.addHeaderView(headerView);
|
||||||
|
|
||||||
view.findViewById(R.id.divider).setBackgroundColor(ContextCompat.getColor(getContext(), menu.isLight()
|
view.findViewById(R.id.divider).setBackgroundColor(ContextCompat.getColor(getContext(), menu.isLight()
|
||||||
? R.color.multi_selection_menu_divider_light : R.color.multi_selection_menu_divider_dark));
|
? R.color.multi_selection_menu_divider_light : R.color.multi_selection_menu_divider_dark));
|
||||||
|
@ -111,6 +202,12 @@ public class MapMultiSelectionMenuFragment extends Fragment implements MultiSele
|
||||||
menu.getMapActivity().getMapLayers().getMapControlsLayer().setControlsClickable(true);
|
menu.getMapActivity().getMapLayers().getMapControlsLayer().setControlsClickable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getPaddingViewHeight() {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
return AndroidUtils.getScreenHeight(activity)
|
||||||
|
- activity.getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height);
|
||||||
|
}
|
||||||
|
|
||||||
public static void showInstance(final MapActivity mapActivity) {
|
public static void showInstance(final MapActivity mapActivity) {
|
||||||
|
|
||||||
if (mapActivity.isActivityDestroyed()) {
|
if (mapActivity.isActivityDestroyed()) {
|
||||||
|
@ -137,45 +234,6 @@ public class MapMultiSelectionMenuFragment extends Fragment implements MultiSele
|
||||||
.addToBackStack(TAG).commitAllowingStateLoss();
|
.addToBackStack(TAG).commitAllowingStateLoss();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runLayoutListener() {
|
|
||||||
ViewTreeObserver vto = view.getViewTreeObserver();
|
|
||||||
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onGlobalLayout() {
|
|
||||||
|
|
||||||
if (!menu.isLandscapeLayout() && listAdapter.getCount() > 3) {
|
|
||||||
View contentView = view.findViewById(R.id.content);
|
|
||||||
float headerHeight = contentView.getResources().getDimension(R.dimen.multi_selection_header_height);
|
|
||||||
float cancelRowHeight = contentView.getResources().getDimension(R.dimen.bottom_sheet_cancel_button_height);
|
|
||||||
int maxHeight = (int) (headerHeight + cancelRowHeight);
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
View childView = listAdapter.getView(0, null, (ListView) contentView.findViewById(R.id.list));
|
|
||||||
childView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
|
|
||||||
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
|
|
||||||
maxHeight += childView.getMeasuredHeight();
|
|
||||||
}
|
|
||||||
int height = contentView.getHeight();
|
|
||||||
|
|
||||||
if (height > maxHeight) {
|
|
||||||
ViewGroup.LayoutParams lp = contentView.getLayoutParams();
|
|
||||||
lp.height = maxHeight;
|
|
||||||
contentView.setLayoutParams(lp);
|
|
||||||
contentView.requestLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewTreeObserver obs = view.getViewTreeObserver();
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
|
||||||
obs.removeOnGlobalLayoutListener(this);
|
|
||||||
} else {
|
|
||||||
obs.removeGlobalOnLayoutListener(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private MultiSelectionArrayAdapter createAdapter() {
|
private MultiSelectionArrayAdapter createAdapter() {
|
||||||
final List<MenuObject> items = new LinkedList<>(menu.getObjects());
|
final List<MenuObject> items = new LinkedList<>(menu.getObjects());
|
||||||
return new MultiSelectionArrayAdapter(menu, R.layout.menu_obj_list_item, items);
|
return new MultiSelectionArrayAdapter(menu, R.layout.menu_obj_list_item, items);
|
||||||
|
|
|
@ -38,6 +38,10 @@ public class MultiSelectionArrayAdapter extends ArrayAdapter<MapMultiSelectionMe
|
||||||
}
|
}
|
||||||
final MapMultiSelectionMenu.MenuObject item = getItem(position);
|
final MapMultiSelectionMenu.MenuObject item = getItem(position);
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
|
if (!menu.isLandscapeLayout()) {
|
||||||
|
AndroidUtils.setBackground(convertView.getContext(), convertView, !menu.isLight(),
|
||||||
|
R.color.ctx_menu_bg_light, R.color.ctx_menu_bg_dark);
|
||||||
|
}
|
||||||
convertView.setOnClickListener(new View.OnClickListener() {
|
convertView.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
|
|
Loading…
Reference in a new issue