Make the multi-selection menu scrollable

This commit is contained in:
Alexander Sytnyk 2018-03-05 17:36:30 +02:00
parent 17f27d6cce
commit 355dd82908
4 changed files with 113 additions and 50 deletions

View file

@ -15,7 +15,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
<com.github.ksoichiro.android.observablescrollview.ObservableListView
android:clipToPadding="false"
android:paddingBottom="@dimen/bottom_sheet_content_padding_small"
android:id="@+id/list"

View file

@ -15,9 +15,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
<com.github.ksoichiro.android.observablescrollview.ObservableListView
android:clipToPadding="false"
android:paddingBottom="@dimen/bottom_sheet_content_padding_small"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
@ -35,7 +34,7 @@
android:id="@+id/cancel_row"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_cancel_button_height"
android:background="?attr/selectableItemBackground">
android:foreground="?attr/selectableItemBackground">
<TextView
android:id="@+id/cancel_row_text"

View file

@ -1,17 +1,27 @@
package net.osmand.plus.mapcontextmenu.other;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.AbsListView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
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.plus.R;
import net.osmand.plus.activities.MapActivity;
@ -41,22 +51,105 @@ public class MapMultiSelectionMenuFragment extends Fragment implements MultiSele
AndroidUtils.setBackground(view.getContext(), view, !menu.isLight(),
R.drawable.multi_selection_menu_bg_light_land, R.drawable.multi_selection_menu_bg_dark_land);
} else {
AndroidUtils.setBackground(view.getContext(), view, !menu.isLight(),
R.drawable.multi_selection_menu_bg_light, R.drawable.multi_selection_menu_bg_dark);
AndroidUtils.setBackground(view.getContext(), view.findViewById(R.id.cancel_row), !menu.isLight(),
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) {
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.setListener(this);
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;
@Override
public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
if (scrollY <= 0) {
if (initialScroll) {
initialScroll = false;
} else {
dismissMenu();
}
}
}
@Override
public void onDownMotionEvent() {
}
@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()
? R.color.multi_selection_menu_divider_light : R.color.multi_selection_menu_divider_dark));
@ -111,6 +204,12 @@ public class MapMultiSelectionMenuFragment extends Fragment implements MultiSele
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) {
if (mapActivity.isActivityDestroyed()) {
@ -137,45 +236,6 @@ public class MapMultiSelectionMenuFragment extends Fragment implements MultiSele
.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() {
final List<MenuObject> items = new LinkedList<>(menu.getObjects());
return new MultiSelectionArrayAdapter(menu, R.layout.menu_obj_list_item, items);

View file

@ -38,6 +38,10 @@ public class MultiSelectionArrayAdapter extends ArrayAdapter<MapMultiSelectionMe
}
final MapMultiSelectionMenu.MenuObject item = getItem(position);
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() {
@Override
public void onClick(View view) {