initial commit QuickSearchSubCategoriesFragment

This commit is contained in:
veliymolfar 2020-04-16 19:07:40 +03:00
parent 91813d7ac5
commit 84e743ec84
6 changed files with 518 additions and 3 deletions

View file

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="?attr/activity_background_color"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/actionModeBackground"
android:minHeight="@dimen/dashboard_map_toolbar"
android:theme="?attr/toolbar_theme"
app:contentInsetLeft="54dp"
app:contentInsetStart="54dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="14dp"
android:layout_marginBottom="14dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/color_white"
android:textSize="@dimen/default_list_text_size_large"
tools:text="Education" />
</LinearLayout>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="@+id/search_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/card_row_min_height"
android:background="?attr/bg_color"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/search_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginEnd="@dimen/list_content_padding_large"
android:layout_marginRight="@dimen/list_content_padding_large"
tools:src="@drawable/ic_action_search_dark" />
<EditText
android:id="@+id/search"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@android:color/transparent"
android:hint="@string/search_poi_types"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size" />
<ImageView
android:id="@+id/search_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/list_item_button_padding"
android:layout_marginLeft="@dimen/list_item_button_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
tools:src="@drawable/ic_action_cancel" />
</LinearLayout>
<include layout="@layout/divider" />
</LinearLayout>
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"
android:dividerHeight="0dp"
android:drawSelectorOnTop="true" />
</LinearLayout>

View file

@ -55,6 +55,56 @@
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="@+id/search_container"
android:layout_width="match_parent"
android:focusableInTouchMode="true"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/card_row_min_height"
android:background="?attr/bg_color"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/search_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginEnd="@dimen/list_content_padding_large"
android:layout_marginRight="@dimen/list_content_padding_large"
tools:src="@drawable/ic_action_search_dark" />
<EditText
android:id="@+id/search"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@android:color/transparent"
android:hint="@string/search_poi_types"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size" />
<ImageView
android:id="@+id/search_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/list_item_button_padding"
android:layout_marginLeft="@dimen/list_item_button_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
tools:src="@drawable/ic_action_cancel" />
</LinearLayout>
<include layout="@layout/divider" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/list_shadow_header" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/context_menu_action_buttons_h"
android:background="?attr/bg_color">
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/select_all"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:letterSpacing="0.01"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:padding="@dimen/content_padding"
android:text="@string/shared_string_select_all"
android:textSize="@dimen/default_list_text_size" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="bottom"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:background="?attr/dashboard_divider" />
</FrameLayout>
</LinearLayout>

View file

@ -11,6 +11,8 @@
Thx - Hardy
-->
<string name="search_poi_types_descr">Combine POI types from different categories. Tap switch to select all, tap left side to category selection.</string>
<string name="search_poi_types">Search poi types</string>
<string name="wiki_menu_download_descr">Additional maps are needed to view Wikipedia POIs on the map.</string>
<string name="wikipedia_poi_languages_promo">Some Wikipedia articles may not be available in your name, select the languages in which Wikipedia articles will appear on the map.\nYou will be able to switch between all available languages while reading the article.</string>
<string name="shared_string_all_languages">All languages</string>

View file

@ -24,6 +24,7 @@ import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
@ -50,6 +51,8 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
public static final String TAG = "QuickSearchCustomPoiFragment";
private static final String QUICK_SEARCH_CUSTOM_POI_FILTER_ID_KEY = "quick_search_custom_poi_filter_id_key";
private OsmandApplication app;
private UiUtilities uiUtilities;
private View view;
private ListView listView;
private CategoryListAdapter listAdapter;
@ -73,7 +76,9 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.nightMode = getMyApplication().getSettings().OSMAND_THEME.get() == OsmandSettings.OSMAND_DARK_THEME;
app = getMyApplication();
uiUtilities = app.getUIUtilities();
this.nightMode = app.getSettings().OSMAND_THEME.get() == OsmandSettings.OSMAND_DARK_THEME;
setStyle(STYLE_NO_FRAME, nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme);
}
@ -131,8 +136,24 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PoiCategory category = listAdapter.getItem(position - listView.getHeaderViewsCount());
showDialog(category, false);
final PoiCategory category = listAdapter.getItem(position - listView.getHeaderViewsCount());
FragmentManager fm = getFragmentManager();
if (fm != null) {
QuickSearchSubCategoriesFragment.showInstance(fm, category, false, new QuickSearchSubCategoriesFragment.OnFiltersSelectedListener() {
@Override
public void onFiltersSelected(LinkedHashSet<String> filters) {
if (filter.getAcceptedSubtypes(category).size() == filters.size()) {
filter.selectSubTypesToAccept(category, null);
} else if (filters.size() == 0) {
filter.setTypeToAccept(category, false);
} else {
filter.selectSubTypesToAccept(category, filters);
}
saveFilter();
listAdapter.notifyDataSetChanged();
}
});
}
}
});

View file

@ -0,0 +1,291 @@
package net.osmand.plus.search;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.core.widget.CompoundButtonCompat;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.plus.render.RenderingIcons;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
public class QuickSearchSubCategoriesFragment extends BaseOsmAndDialogFragment {
public static final String TAG = QuickSearchSubCategoriesFragment.class.getName();
private static final String CATEGORY_NAME_KEY = "category_key";
private static final String ALL_SELECTED_KEY = "all_selected";
private OnFiltersSelectedListener listener;
private OsmandApplication app;
private UiUtilities uiUtilities;
private PoiCategory poiCategory;
private List<PoiType> poiTypeList;
private List<PoiType> selectedPoiTypeList;
private SubCategoriesAdapter adapter;
private EditText searchEditText;
private ListView listView;
private View headerSelectAll;
private View headerShadow;
private View footerShadow;
private boolean selectAll;
private boolean nightMode;
public static void showInstance(@NonNull FragmentManager fm, @NonNull PoiCategory poiCategory,
boolean selectAll, @NonNull OnFiltersSelectedListener listener) {
QuickSearchSubCategoriesFragment fragment = new QuickSearchSubCategoriesFragment();
fragment.setPoiCategory(poiCategory);
fragment.setSelectAll(selectAll);
fragment.setListener(listener);
fragment.show(fm, TAG);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = getMyApplication();
uiUtilities = app.getUIUtilities();
nightMode = !app.getSettings().isLightContent();
selectedPoiTypeList = new ArrayList<>();
if (savedInstanceState != null) {
poiCategory = app.getPoiTypes().getPoiCategoryByName(savedInstanceState.getString(CATEGORY_NAME_KEY));
selectAll = savedInstanceState.getBoolean(ALL_SELECTED_KEY);
}
poiTypeList = new ArrayList<>(poiCategory.getPoiTypes());
if (selectAll) {
selectedPoiTypeList.addAll(poiTypeList);
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(CATEGORY_NAME_KEY, poiCategory.getKeyName());
outState.putBoolean(ALL_SELECTED_KEY, selectAll);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_subcategories, container, false);
Toolbar toolbar = root.findViewById(R.id.toolbar);
Drawable icClose = app.getUIUtilities().getIcon(R.drawable.ic_arrow_back,
nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light);
toolbar.setNavigationIcon(icClose);
toolbar.setNavigationContentDescription(R.string.shared_string_close);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinkedHashSet<String> list = new LinkedHashSet<>();
for (PoiType poiType : selectedPoiTypeList) {
list.add(poiType.getKeyName());
}
listener.onFiltersSelected(list);
dismiss();
}
});
TextView title = root.findViewById(R.id.title);
title.setText(poiCategory.getTranslation());
listView = root.findViewById(R.id.list);
headerShadow = inflater.inflate(R.layout.list_shadow_header, listView, false);
footerShadow = inflater.inflate(R.layout.list_shadow_footer, listView, false);
headerSelectAll = inflater.inflate(R.layout.select_all_switch_list_item, listView, false);
final SwitchCompat selectAllSwitch = headerSelectAll.findViewById(R.id.select_all);
selectAllSwitch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
selectAll = !selectAll;
selectAllSwitch.setChecked(selectAll);
selectAll(selectAll);
}
});
listView.addFooterView(footerShadow);
listView.addHeaderView(headerSelectAll);
searchEditText = root.findViewById(R.id.search);
searchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
searchSubCategory(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
ImageView searchIcon = root.findViewById(R.id.search_icon);
searchIcon.setImageDrawable(uiUtilities.getIcon(R.drawable.ic_action_search_dark, nightMode));
ImageView searchCloseIcon = root.findViewById(R.id.search_close);
searchCloseIcon.setImageDrawable(uiUtilities.getIcon(R.drawable.ic_action_cancel, nightMode));
searchCloseIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
clearSearch();
}
});
Collections.sort(poiTypeList, new Comparator<PoiType>() {
@Override
public int compare(PoiType poiType, PoiType t1) {
return poiType.getTranslation().compareTo(t1.getTranslation());
}
});
adapter = new SubCategoriesAdapter(app, new ArrayList<PoiType>(poiTypeList));
listView.setAdapter(adapter);
return root;
}
private void clearSearch() {
searchEditText.setText("");
AndroidUtils.hideSoftKeyboard(requireActivity(), searchEditText);
}
private void selectAll(boolean selectAll) {
selectedPoiTypeList.clear();
if (selectAll) {
selectedPoiTypeList.addAll(poiTypeList);
}
adapter.notifyDataSetChanged();
}
private void searchSubCategory(String search) {
List<PoiType> result = new ArrayList<>();
if (search.isEmpty()) {
listView.removeHeaderView(headerShadow);
listView.removeHeaderView(headerSelectAll);
listView.addHeaderView(headerSelectAll);
result.addAll(new ArrayList<>(poiTypeList));
} else {
listView.removeHeaderView(headerSelectAll);
listView.removeHeaderView(headerShadow);
listView.removeFooterView(footerShadow);
listView.addHeaderView(headerShadow);
for (PoiType poiType : poiTypeList) {
if (poiType.getTranslation().toLowerCase().contains(search.toLowerCase())) {
result.add(poiType);
}
}
if (result.isEmpty()) {
listView.removeHeaderView(headerShadow);
listView.removeFooterView(footerShadow);
} else {
listView.addHeaderView(headerShadow);
listView.addFooterView(footerShadow);
}
}
adapter.clear();
adapter.addAll(result);
adapter.notifyDataSetChanged();
}
public void setSelectAll(boolean selectAll) {
this.selectAll = selectAll;
}
public void setPoiCategory(PoiCategory poiCategory) {
this.poiCategory = poiCategory;
}
public void setListener(OnFiltersSelectedListener listener) {
this.listener = listener;
}
private class SubCategoriesAdapter extends ArrayAdapter<PoiType> {
private UiUtilities uiUtilities;
private boolean nightMode;
private int activeColorRes;
private int secondaryColorRes;
public SubCategoriesAdapter(OsmandApplication app, List<PoiType> items) {
super(app, R.layout.profile_data_list_item_child, items);
uiUtilities = app.getUIUtilities();
nightMode = !app.getSettings().isLightContent();
activeColorRes = nightMode
? R.color.icon_color_active_dark
: R.color.icon_color_active_light;
secondaryColorRes = nightMode
? R.color.icon_color_secondary_dark
: R.color.icon_color_secondary_light;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
if (convertView == null) {
convertView = UiUtilities.getInflater(app, nightMode)
.inflate(R.layout.profile_data_list_item_child, parent, false);
}
final PoiType poiType = getItem(position);
final boolean selected = selectedPoiTypeList.contains(poiType);
int tintColorRes = selected ? activeColorRes : secondaryColorRes;
if (poiType != null) {
TextView title = convertView.findViewById(R.id.title_tv);
title.setText(poiType.getTranslation());
final CheckBox checkBox = convertView.findViewById(R.id.check_box);
checkBox.setChecked(selected);
checkBox.setClickable(false);
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, tintColorRes)));
convertView.findViewById(R.id.sub_title_tv).setVisibility(View.GONE);
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (selected) {
selectedPoiTypeList.remove(poiType);
} else {
selectedPoiTypeList.add(poiType);
}
notifyDataSetChanged();
}
});
ImageView icon = convertView.findViewById(R.id.icon);
int iconRes = RenderingIcons.getBigIconResourceId(poiType.getIconKeyName());
if (iconRes == 0) {
iconRes = RenderingIcons.getBigIconResourceId(poiType.getOsmTag() + "_" + poiType.getOsmValue());
if (iconRes == 0) {
// TODO: change default icon
iconRes = R.drawable.ic_person;
}
}
icon.setImageDrawable(uiUtilities.getIcon(iconRes, tintColorRes));
}
return convertView;
}
}
public interface OnFiltersSelectedListener {
void onFiltersSelected(LinkedHashSet<String> filters);
}
}