Here is a settings menu that allows the user to choose multiple settings. To begin the selection, the user has to long press any setting. Then they can tap any setting to choose more.
Activity
package com.locuslabs.android.sdk;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.selection.ItemDetailsLookup;
import androidx.recyclerview.selection.Selection;
import androidx.recyclerview.selection.SelectionPredicates;
import androidx.recyclerview.selection.SelectionTracker;
import androidx.recyclerview.selection.StableIdKeyProvider;
import androidx.recyclerview.selection.StorageStrategy;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.Gson;
import com.locuslabs.android.sdk.api.ConfigurationExperiments;
import com.locuslabs.android.sdk.api.MapExperiments;
import com.locuslabs.android.sdk.api.MapViewExperiments;
import com.locuslabs.android.sdk.api.PositionExperiments;
import com.locuslabs.android.sdk.api.VenueExperiments;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
public class SettingsActivity extends Activity {
private static final String TAG = "SettingsActivity";
SelectionTracker<Long> selectedSettingTracker;
private RecyclerView settingsRecyclerView;
private List<String> listOfUsableApis;
private ApiSettings mApiSettings;
private void setApiSettings(List<String> settingNamesSelected) {
for (String settingName : settingNamesSelected) {
if (settingName.equals(getResources().getString(R.string.api_setting_draw_line)))
mApiSettings.mDrawLine = true;
if (settingName.equals(getResources().getString(R.string.api_setting_search)))
mApiSettings.mLogSearch = true;
/* omitted rest of options for brevity */
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mApiSettings = new ApiSettings();
setContentView(R.layout.activity_settings);
settingsRecyclerView = findViewById(R.id.settingsRecyclerView);
settingsRecyclerView.setLayoutManager(new LinearLayoutManager(this));
Button backButton = findViewById(R.id.settings_back_button);
Button saveButton = findViewById(R.id.settings_apply_button);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setApiSettings(getSettingNamesSelected());
Intent intent = new Intent();
intent.putExtra("apiSettings", new Gson().toJson(mApiSettings));
setResult(RESULT_OK, intent);
finish();
}
});
listOfUsableApis = /* omitted for brevity */
final SettingsAdapter settingsAdapter = new SettingsAdapter();
settingsRecyclerView.setAdapter(settingsAdapter);
// Handle selection of settings
selectedSettingTracker = new SelectionTracker.Builder<Long>(
"selectedSettingTrackerId",
settingsRecyclerView,
new StableIdKeyProvider(settingsRecyclerView),
new SettingsDetailsLookup(),
StorageStrategy.createLongStorage()
).
withSelectionPredicate(SelectionPredicates.<Long>createSelectAnything()).
build();
}
private List<String> getSettingNamesSelected() {
Selection<Long> settingsSelection = selectedSettingTracker.getSelection();
Iterator<Long> settingSelectionIterator = settingsSelection.iterator();
List<String> settingNamesSelected = new ArrayList<>();
while (settingSelectionIterator.hasNext()) {
Long settingSelectionId = settingSelectionIterator.next();
String settingNameSelected = listOfUsableApis.get(settingSelectionId.intValue());
settingNamesSelected.add(settingNameSelected);
}
return settingNamesSelected;
}
public static class ApiSettings {
public boolean mDrawLine = false;
public boolean mWalkSimulator = false;
/* omitted most options for brevity */
public ApiSettings() {
}
}
private class SettingsAdapter extends RecyclerView.Adapter<SettingsAdapter.SettingViewHolder> {
public SettingsAdapter() {
setHasStableIds(true);
}
@NonNull
@Override
public SettingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
TextView textView = (TextView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.setting_list_item, parent, false);
SettingViewHolder settingViewHolder = new SettingViewHolder(textView);
return settingViewHolder;
}
@Override
public void onBindViewHolder(@NonNull SettingViewHolder holder, final int position) {
holder.textView.setText(listOfUsableApis.get(position));
holder.textView.setActivated(selectedSettingTracker.isSelected((long) position));
holder.position = position;
}
@Override
public int getItemCount() {
return listOfUsableApis.size();
}
@Override
public long getItemId(int position) {
return Long.valueOf(position);
}
public class SettingViewHolder extends RecyclerView.ViewHolder {
public int position;
public TextView textView;
public SettingViewHolder(TextView v) {
super(v);
textView = v;
}
}
}
private class SettingsDetailsLookup extends ItemDetailsLookup<Long> {
@Nullable
@Override
public ItemDetails<Long> getItemDetails(@NonNull MotionEvent event) {
View view = settingsRecyclerView.findChildViewUnder(event.getX(), event.getY());
if (view != null) {
final RecyclerView.ViewHolder viewHolder = settingsRecyclerView.getChildViewHolder(view);
if (viewHolder instanceof SettingsAdapter.SettingViewHolder) {
final SettingsAdapter.SettingViewHolder settingViewHolder = (SettingsAdapter.SettingViewHolder) viewHolder;
return new ItemDetailsLookup.ItemDetails<Long>() {
@Override
public int getPosition() {
return viewHolder.getAdapterPosition();
}
@Nullable
@Override
public Long getSelectionKey() {
return Long.valueOf(settingViewHolder.position);
}
};
}
}
return null;
}
}
}
Layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:baselineAligned="false"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#454545"
android:weightSum="100">
<Button
android:id="@+id/settings_back_button"
android:background="#454545"
android:drawableStart="@drawable/arrow_white"
android:drawableLeft="@drawable/arrow_white"
android:layout_gravity="start"
android:layout_width="@dimen/ll_mdu_10"
android:layout_height="@dimen/ll_mdu_10"
android:layout_weight="5"/>
<Space
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="90"
/>
<Button
android:id="@+id/settings_apply_button"
android:background="#454545"
android:drawableStart="@android:drawable/ic_menu_save"
android:drawableLeft="@android:drawable/ic_menu_save"
android:layout_gravity="end"
android:layout_width="@dimen/ll_mdu_10"
android:layout_height="@dimen/ll_mdu_10"
android:layout_weight="5"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Long-press for first setting, then tap other settings for multiple selection"
app:layout_constraintBottom_toTopOf="@+id/settingsRecyclerView"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/settingsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</LinearLayout>
</LinearLayout>
Layout setting_list_item.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setting_list_item_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/setting_background"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:textAppearance="?android:attr/textAppearanceListItemSmall" />
Background drawable setting_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/holo_green_dark" android:state_activated="true" />
<item android:drawable="@android:color/white" />
</selector>
References: