mirror of
https://github.com/MaintainTeam/LastPipeBender.git
synced 2025-03-02 22:38:20 +03:00
searchfilters: 1st Ui: default dialog for search content and sort filters
This commit is contained in:
parent
9d9f7c49c8
commit
0578e0e64d
5 changed files with 583 additions and 0 deletions
|
@ -0,0 +1,55 @@
|
|||
// Created by evermind-zz 2022, licensed GNU GPL version 3 or later
|
||||
|
||||
package org.schabi.newpipe.fragments.list.search.filter;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.schabi.newpipe.databinding.SearchFilterDialogFragmentBinding;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
|
||||
/**
|
||||
* A search filter dialog that also looks like a dialog aka. 'dialog style'.
|
||||
*/
|
||||
public class SearchFilterDialogFragment extends BaseSearchFilterDialogFragment {
|
||||
|
||||
private SearchFilterDialogFragmentBinding binding;
|
||||
|
||||
public static DialogFragment newInstance(
|
||||
final int serviceId,
|
||||
final ArrayList<Integer> userSelectedContentFilter,
|
||||
final ArrayList<Integer> userSelectedSortFilter) {
|
||||
return initDialogArguments(
|
||||
new SearchFilterDialogFragment(),
|
||||
serviceId,
|
||||
userSelectedContentFilter,
|
||||
userSelectedSortFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseSearchFilterUiGenerator createSearchFilterDialogGenerator(
|
||||
final StreamingService service,
|
||||
final SearchFilterLogic.Callback callback) {
|
||||
return new SearchFilterDialogGenerator(service,
|
||||
binding.verticalScroll, requireContext(), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Toolbar getToolbar() {
|
||||
return binding.toolbarLayout.toolbar;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View getRootView(final LayoutInflater inflater,
|
||||
final ViewGroup container) {
|
||||
binding = SearchFilterDialogFragmentBinding
|
||||
.inflate(inflater, container, false);
|
||||
return binding.getRoot();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,272 @@
|
|||
// Created by evermind-zz 2022, licensed GNU GPL version 3 or later
|
||||
|
||||
package org.schabi.newpipe.fragments.list.search.filter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.GridLayout;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.chip.Chip;
|
||||
import com.google.android.material.chip.ChipGroup;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterGroup;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterItem;
|
||||
import org.schabi.newpipe.util.DeviceUtils;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.appcompat.view.ContextThemeWrapper;
|
||||
|
||||
public class SearchFilterDialogGenerator extends BaseSearchFilterUiDialogGenerator {
|
||||
private final GridLayout globalLayout;
|
||||
private final Map<Spinner, AdapterView.OnItemSelectedListener> spinners = new HashMap<>();
|
||||
|
||||
public SearchFilterDialogGenerator(final StreamingService service,
|
||||
final ViewGroup root,
|
||||
final Context context,
|
||||
final SearchFilterLogic.Callback callback) {
|
||||
super(service.getSearchQHFactory(), callback, context);
|
||||
this.globalLayout = createGridLayout();
|
||||
root.addView(globalLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
for (final Map.Entry<Spinner, AdapterView.OnItemSelectedListener> spinner
|
||||
: spinners.entrySet()) {
|
||||
spinner.getKey().setOnItemSelectedListener(spinner.getValue());
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
for (final Map.Entry<Spinner, AdapterView.OnItemSelectedListener> spinner
|
||||
: spinners.entrySet()) {
|
||||
spinner.getKey().setOnItemSelectedListener(null);
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createTitle(final String name,
|
||||
final List<View> titleViewElements) {
|
||||
final TextView titleView = createTitleText(name);
|
||||
final View separatorLine = createSeparatorLine();
|
||||
final View separatorLine2 = createSeparatorLine();
|
||||
|
||||
globalLayout.addView(separatorLine);
|
||||
globalLayout.addView(titleView);
|
||||
globalLayout.addView(separatorLine2);
|
||||
|
||||
titleViewElements.add(titleView);
|
||||
titleViewElements.add(separatorLine);
|
||||
titleViewElements.add(separatorLine2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createFilterGroup(final FilterGroup filterGroup,
|
||||
final UiWrapperMapDelegate wrapperDelegate,
|
||||
final UiSelectorDelegate selectorDelegate) {
|
||||
final GridLayout.LayoutParams layoutParams = getLayoutParamsViews();
|
||||
boolean doSpanDataOverMultipleCells = false;
|
||||
final UiItemWrapperViews viewsWrapper = new UiItemWrapperViews(
|
||||
filterGroup.getIdentifier());
|
||||
|
||||
if (filterGroup.getName() != null) {
|
||||
final TextView filterLabel = new TextView(context);
|
||||
|
||||
filterLabel.setId(filterGroup.getIdentifier());
|
||||
filterLabel.setText(
|
||||
ServiceHelper.getTranslatedFilterString(filterGroup.getName(), context));
|
||||
filterLabel.setGravity(Gravity.CENTER_VERTICAL);
|
||||
setDefaultMargin(layoutParams);
|
||||
setZeroPadding(filterLabel);
|
||||
|
||||
filterLabel.setLayoutParams(layoutParams);
|
||||
globalLayout.addView(filterLabel);
|
||||
viewsWrapper.add(filterLabel);
|
||||
} else {
|
||||
doSpanDataOverMultipleCells = true;
|
||||
}
|
||||
|
||||
if (filterGroup.isOnlyOneCheckable()) {
|
||||
|
||||
final Spinner filterDataSpinner = new Spinner(context, Spinner.MODE_DROPDOWN);
|
||||
|
||||
final GridLayout.LayoutParams spinnerLp =
|
||||
clipFreeRightColumnLayoutParams(doSpanDataOverMultipleCells);
|
||||
setDefaultMargin(spinnerLp);
|
||||
filterDataSpinner.setLayoutParams(spinnerLp);
|
||||
setZeroPadding(filterDataSpinner);
|
||||
|
||||
createUiElementsForSingleSelectableItemsFilterGroup(
|
||||
filterGroup, wrapperDelegate, selectorDelegate, filterDataSpinner);
|
||||
|
||||
viewsWrapper.add(filterDataSpinner);
|
||||
globalLayout.addView(filterDataSpinner);
|
||||
|
||||
} else { // multiple items in FilterGroup selectable
|
||||
final ChipGroup chipGroup = new ChipGroup(context);
|
||||
viewsWrapper.add(chipGroup);
|
||||
globalLayout.addView(chipGroup);
|
||||
chipGroup.setLayoutParams(
|
||||
clipFreeRightColumnLayoutParams(doSpanDataOverMultipleCells));
|
||||
chipGroup.setSingleLine(false);
|
||||
|
||||
createUiElementsForMultipleSelectableItemsFilterGroup(
|
||||
filterGroup, wrapperDelegate, selectorDelegate, chipGroup);
|
||||
}
|
||||
|
||||
wrapperDelegate.put(filterGroup.getIdentifier(), viewsWrapper);
|
||||
}
|
||||
|
||||
private void createUiElementsForSingleSelectableItemsFilterGroup(
|
||||
final FilterGroup filterGroup,
|
||||
final UiWrapperMapDelegate wrapperDelegate,
|
||||
final UiSelectorDelegate selectorDelegate,
|
||||
final Spinner filterDataSpinner) {
|
||||
filterDataSpinner.setAdapter(new SearchFilterDialogSpinnerAdapter(
|
||||
context, filterGroup, wrapperDelegate, filterDataSpinner));
|
||||
|
||||
final AdapterView.OnItemSelectedListener listener;
|
||||
listener = new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(final AdapterView<?> parent, final View view,
|
||||
final int position, final long id) {
|
||||
if (view != null) {
|
||||
selectorDelegate.selectFilter(view.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(final AdapterView<?> parent) {
|
||||
// we are only interested onItemSelected() -> no implementation here
|
||||
}
|
||||
};
|
||||
|
||||
filterDataSpinner.setOnItemSelectedListener(listener);
|
||||
spinners.put(filterDataSpinner, listener);
|
||||
}
|
||||
|
||||
private void createUiElementsForMultipleSelectableItemsFilterGroup(
|
||||
final FilterGroup filterGroup,
|
||||
final UiWrapperMapDelegate wrapperDelegate,
|
||||
final UiSelectorDelegate selectorDelegate,
|
||||
final ChipGroup chipGroup) {
|
||||
for (final FilterItem item : filterGroup.getFilterItems()) {
|
||||
final Chip chip = new Chip(new ContextThemeWrapper(
|
||||
context, R.style.Theme_MaterialComponents_Light));
|
||||
chip.setText(ServiceHelper.getTranslatedFilterString(item.getName(), context));
|
||||
chip.setId(item.getIdentifier());
|
||||
chip.setCheckable(true);
|
||||
final View.OnClickListener listener;
|
||||
listener = view -> selectorDelegate.selectFilter(view.getId());
|
||||
|
||||
chip.setOnClickListener(listener);
|
||||
chipGroup.addView(chip);
|
||||
viewListeners.put(chip, listener);
|
||||
wrapperDelegate.put(item.getIdentifier(), new UiItemWrapperChip(
|
||||
item, chip, chipGroup));
|
||||
}
|
||||
}
|
||||
|
||||
private View createSeparatorLine() {
|
||||
return createSeparatorLine(clipFreeRightColumnLayoutParams(true));
|
||||
}
|
||||
|
||||
private TextView createTitleText(final String name) {
|
||||
final TextView title = createTitleText(name,
|
||||
clipFreeRightColumnLayoutParams(true));
|
||||
title.setGravity(Gravity.CENTER);
|
||||
return title;
|
||||
}
|
||||
|
||||
private GridLayout createGridLayout() {
|
||||
final GridLayout layout = new GridLayout(context);
|
||||
|
||||
layout.setColumnCount(2);
|
||||
|
||||
final GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
|
||||
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
setDefaultMargin(layoutParams);
|
||||
layout.setLayoutParams(layoutParams);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private GridLayout.LayoutParams clipFreeRightColumnLayoutParams(final boolean doColumnSpan) {
|
||||
final GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
|
||||
// https://stackoverflow.com/questions/37744672/gridlayout-children-are-being-clipped
|
||||
layoutParams.width = 0;
|
||||
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
layoutParams.setGravity(Gravity.FILL_HORIZONTAL | Gravity.CENTER_VERTICAL);
|
||||
setDefaultMargin(layoutParams);
|
||||
|
||||
if (doColumnSpan) {
|
||||
layoutParams.columnSpec = GridLayout.spec(0, 2, 1.0f);
|
||||
}
|
||||
|
||||
return layoutParams;
|
||||
}
|
||||
|
||||
private GridLayout.LayoutParams getLayoutParamsViews() {
|
||||
final GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
|
||||
layoutParams.setGravity(Gravity.TOP);
|
||||
setDefaultMargin(layoutParams);
|
||||
return layoutParams;
|
||||
}
|
||||
|
||||
private GridLayout.LayoutParams setDefaultMargin(final GridLayout.LayoutParams layoutParams) {
|
||||
layoutParams.setMargins(
|
||||
DeviceUtils.dpToPx(4, context),
|
||||
DeviceUtils.dpToPx(2, context),
|
||||
DeviceUtils.dpToPx(4, context),
|
||||
DeviceUtils.dpToPx(2, context)
|
||||
);
|
||||
return layoutParams;
|
||||
}
|
||||
|
||||
private View setZeroPadding(final View view) {
|
||||
view.setPadding(0, 0, 0, 0);
|
||||
return view;
|
||||
}
|
||||
|
||||
public static class UiItemWrapperChip extends BaseUiItemWrapper {
|
||||
|
||||
private final ChipGroup chipGroup;
|
||||
|
||||
public UiItemWrapperChip(final FilterItem item,
|
||||
final View view,
|
||||
final ChipGroup chipGroup) {
|
||||
super(item, view);
|
||||
this.chipGroup = chipGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return ((Chip) view).isChecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(final boolean checked) {
|
||||
view.setSelected(checked);
|
||||
((Chip) view).setChecked(checked);
|
||||
|
||||
if (checked) {
|
||||
chipGroup.check(view.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
// Created by evermind-zz 2022, licensed GNU GPL version 3 or later
|
||||
|
||||
package org.schabi.newpipe.fragments.list.search.filter;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterContainer;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterGroup;
|
||||
import org.schabi.newpipe.extractor.search.filter.FilterItem;
|
||||
import org.schabi.newpipe.util.DeviceUtils;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class SearchFilterDialogSpinnerAdapter extends BaseAdapter {
|
||||
|
||||
private final Context context;
|
||||
private final FilterGroup group;
|
||||
private final BaseSearchFilterUiGenerator.UiWrapperMapDelegate wrapperDelegate;
|
||||
private final Spinner spinner;
|
||||
private final Map<Integer, Integer> id2PosMap = new HashMap<>();
|
||||
private final Map<Integer, UiItemWrapperSpinner>
|
||||
viewWrapperMap = new HashMap<>();
|
||||
|
||||
public SearchFilterDialogSpinnerAdapter(
|
||||
final Context context,
|
||||
final FilterGroup group,
|
||||
final BaseSearchFilterUiGenerator.UiWrapperMapDelegate wrapperDelegate,
|
||||
final Spinner filterDataSpinner) {
|
||||
this.context = context;
|
||||
this.group = group;
|
||||
this.wrapperDelegate = wrapperDelegate;
|
||||
this.spinner = filterDataSpinner;
|
||||
|
||||
createViewWrappers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return group.getFilterItems().length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(final int position) {
|
||||
return group.getFilterItems()[position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(final int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, final View convertView, final ViewGroup parent) {
|
||||
final FilterItem item = group.getFilterItems()[position];
|
||||
final TextView view;
|
||||
|
||||
if (convertView != null) {
|
||||
view = (TextView) convertView;
|
||||
} else {
|
||||
view = createViewItem();
|
||||
}
|
||||
|
||||
initViewWithData(position, item, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
private void initViewWithData(final int position,
|
||||
final FilterItem item,
|
||||
final TextView view) {
|
||||
final UiItemWrapperSpinner wrappedView =
|
||||
viewWrapperMap.get(position);
|
||||
Objects.requireNonNull(wrappedView);
|
||||
|
||||
view.setId(item.getIdentifier());
|
||||
view.setText(ServiceHelper.getTranslatedFilterString(item.getName(), context));
|
||||
view.setVisibility(wrappedView.getVisibility());
|
||||
view.setEnabled(wrappedView.isEnabled());
|
||||
|
||||
if (item instanceof FilterItem.DividerItem) {
|
||||
wrappedView.setEnabled(false);
|
||||
view.setEnabled(wrappedView.isEnabled());
|
||||
final String menuDividerTitle = ">>>"
|
||||
+ ServiceHelper.getTranslatedFilterString(item.getName(), context) + "<<<";
|
||||
view.setText(menuDividerTitle);
|
||||
}
|
||||
}
|
||||
|
||||
private void createViewWrappers() {
|
||||
int position = 0;
|
||||
for (final FilterItem item : this.group.getFilterItems()) {
|
||||
final int initialVisibility = View.VISIBLE;
|
||||
final boolean isInitialEnabled = true;
|
||||
|
||||
final UiItemWrapperSpinner wrappedView =
|
||||
new UiItemWrapperSpinner(
|
||||
item,
|
||||
initialVisibility,
|
||||
isInitialEnabled,
|
||||
spinner);
|
||||
|
||||
if (item instanceof FilterItem.DividerItem) {
|
||||
wrappedView.setEnabled(false);
|
||||
}
|
||||
|
||||
// store wrapper also locally as we refer here regularly
|
||||
viewWrapperMap.put(position, wrappedView);
|
||||
// store wrapper globally in SearchFilterLogic
|
||||
wrapperDelegate.put(item.getIdentifier(), wrappedView);
|
||||
id2PosMap.put(item.getIdentifier(), position);
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
private TextView createViewItem() {
|
||||
final TextView view = new TextView(context);
|
||||
view.setLayoutParams(new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
view.setGravity(Gravity.CENTER_VERTICAL);
|
||||
view.setPadding(
|
||||
DeviceUtils.dpToPx(8, context),
|
||||
DeviceUtils.dpToPx(4, context),
|
||||
DeviceUtils.dpToPx(8, context),
|
||||
DeviceUtils.dpToPx(4, context)
|
||||
);
|
||||
return view;
|
||||
}
|
||||
|
||||
public int getItemPositionForFilterId(final int id) {
|
||||
return id2PosMap.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(final int position) {
|
||||
final UiItemWrapperSpinner wrappedView =
|
||||
viewWrapperMap.get(position);
|
||||
Objects.nonNull(wrappedView);
|
||||
return wrappedView.isEnabled();
|
||||
}
|
||||
|
||||
private static class UiItemWrapperSpinner
|
||||
extends BaseItemWrapper {
|
||||
private final Spinner spinner;
|
||||
|
||||
/**
|
||||
* We have to store the visibility of the view and if it is enabled.
|
||||
* <p>
|
||||
* Reason: the Spinner adapter reuses {@link View} elements through the parameter
|
||||
* convertView in {@link SearchFilterDialogSpinnerAdapter#getView(int, View, ViewGroup)}
|
||||
* -> this is the Android Adapter's time saving characteristic to rather reuse
|
||||
* than to recreate a {@link View}.
|
||||
* -> so we reuse what Android gives us in above mentioned method.
|
||||
*/
|
||||
private int visibility;
|
||||
private boolean enabled;
|
||||
|
||||
UiItemWrapperSpinner(final FilterItem item,
|
||||
final int initialVisibility,
|
||||
final boolean isInitialEnabled,
|
||||
final Spinner spinner) {
|
||||
super(item);
|
||||
this.spinner = spinner;
|
||||
|
||||
this.visibility = initialVisibility;
|
||||
this.enabled = isInitialEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(final boolean visible) {
|
||||
if (visible) {
|
||||
visibility = View.VISIBLE;
|
||||
} else {
|
||||
visibility = View.GONE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return spinner.getSelectedItem() == item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(final boolean checked) {
|
||||
if (super.getItemId() != FilterContainer.ITEM_IDENTIFIER_UNKNOWN) {
|
||||
final SearchFilterDialogSpinnerAdapter adapter =
|
||||
(SearchFilterDialogSpinnerAdapter) spinner.getAdapter();
|
||||
spinner.setSelection(adapter.getItemPositionForFilterId(super.getItemId()));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public int getVisibility() {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
public void setVisibility(final int visibility) {
|
||||
this.visibility = visibility;
|
||||
}
|
||||
}
|
||||
}
|
23
app/src/main/res/layout/search_filter_dialog_fragment.xml
Normal file
23
app/src/main/res/layout/search_filter_dialog_fragment.xml
Normal file
|
@ -0,0 +1,23 @@
|
|||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<include
|
||||
android:id="@+id/toolbar_layout"
|
||||
layout="@layout/toolbar_layout" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/toolbar_layout">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/vertical_scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
</RelativeLayout>
|
15
app/src/main/res/menu/menu_search_filter_dialog_fragment.xml
Normal file
15
app/src/main/res/menu/menu_search_filter_dialog_fragment.xml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/reset"
|
||||
android:title="@string/playback_reset"
|
||||
android:icon="@drawable/ic_settings_backup_restore"
|
||||
app:showAsAction="always" />
|
||||
<item
|
||||
android:id="@+id/search"
|
||||
android:title="@string/search"
|
||||
android:icon="@drawable/ic_search"
|
||||
app:showAsAction="always" />
|
||||
|
||||
</menu>
|
Loading…
Add table
Reference in a new issue