The Generic List Picker Form Cell¶
GenericListPickerFormCell
is an enhanced version of the older ListPickerFormCell
class.
Applications often present a long list of items and allow users to express their choice in either single or multiple selections.
GenericListPickerFormCell
is designed to handle such complex lists with ease and allow developers to:
- Inflate custom views to present the target items.
- Bind items by their position or custom id.
- Track user interactions and selections, and notify the application of the changes through callbacks.
The cell can easily be configured to allow:
- Single selection only – Presents the list of items with radio buttons and allows only one selection.
- Multi selection – Presents the list of items with check boxes and allows users to make multiple selections.
This Cell also allows you to perform paging for better performance. For example, if you have 100,000 elements to present, then GenericListPickerFormCell
allows
you to only fetch the initial 100 elements and then load new elements as the user scrolls the list.
Using the GenericListPickerFormCell
¶
This form cell can be used within your activity like any traditional Android view:
<com.sap.cloud.mobile.fiori.formcell.GenericListPickerFormCell
android:id="@+id/genericTextPicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
app:activityTitle="Choose Text"
app:bindViewById="true"
app:key="Pick Text Options" />
GenericListPickerFormCell
Activity¶
The GenericListPickerFormCell
depends on GenericListPickerFormCellActivity
to present the list items. GenericListPickerFormCellActivity
is an abstract class responsible for creating the list items, presenting them to a user, tracking the user actions, and informing the form cell about the changes made. Internally, it uses the GenericListPickerFormCell
Fragment to display the list picker.
As shown in the following example, GenericListPickerFormCellActivity
has two generic parameters:
-
V extends View
– Represents the type of views to be presented to user; for example,TextView
orObjectCell
-
T extends Serializable
– Represents the type of key used to identify two different elements in the list being presented; for example, position of the item in actual list or item id from your database
class GenericListPickerFormCellActivity<V extends View, T extends Serializable> extends ...
In order to create and bind the data, GenericListPickerFormCellActivity
follows the RecyclerView.Adapter
pattern. For the ease of usage, APIs of the Activity are named along the lines of RecyclerView.Adapter
APIs.
The following table lists the methods, with descriptions, that you have to override to set up the GenericListPickerFormCellActivity
.
Abstract Methods | Description |
---|---|
int getItemCount() |
Informs the GenericListPickerFormCellActivity about the number of items in the List. |
int getItemViewType(int position) |
Inflates different types of list item views. This method informs the GenericListPickerFormCellActivity about type of the view at a given position. |
V onCreateView(int viewType, @NonNull Context context) |
Given a view type, creates the View. |
void onBindView(@NonNull V view, int position) |
This is where you bind your view with data. Given position and view bind it to data. |
T getId(int pos) |
Given a position in adapter, return the id used for the item. |
-
You can use
app:value
XML attribute orsetValue(List<Integer>)
to set the already selected value on the cell. -
You can set
GenericListPickerFormCellActivity
usingsetPickerActivity(@Nullable GenericListPickerFormCellActivity<V, ?> pickerActivity)
method on the form cell.
The following is a basic example of how to use GenericListPickerFormCellActivity
:
GenericListPickerFormCell<TextView, String> genericTextPickerString = view.findViewById(R.id.genericTextPickerString);
genericTextPickerString.setSelectedItemLabel("Selected Items");
genericTextPickerString.setAllItemLabel("All Items");
genericTextPickerString.setPickerActivity(new GenericTextStringPickerActivity());
And then in GenericTextStringPickerActivity
public class GenericTextStringPickerActivity extends GenericListPickerFormCellActivity<TextView, String> {
@NonNull
private List<String> mItemList;
private List<String> mSelection;
private List<String> backup;
public GenericTextStringPickerActivity() {
mItemList = new ArrayList<>();
backup = new ArrayList<>();
setItemList(setupData());
}
public void setItemList(@NonNull List<String> itemList) {
mItemList.addAll(itemList.subList(0, itemList.size() / 4));
backup.addAll(itemList);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSelection = new ArrayList<>();
}
@Override
protected void onResume() {
super.onResume();
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(GenericListPickerFormCellFragment.TAG);
if (fragment != null) {
GenericListPickerFormCellFragment listPickerDialogFragment = (GenericListPickerFormCellFragment) fragment;
View view = listPickerDialogFragment.getView();
MaterialToolbar toolbar = view.findViewById(com.sap.cloud.mobile.fiori.R.id.list_picker_toolbar);
if (toolbar != null) {
Menu menu = toolbar.getMenu();
FioriSearchView mFioriSearchView = (FioriSearchView) menu.findItem(R.id.appbar_search_menu).getActionView();
if (mFioriSearchView != null) {
mFioriSearchView.setOnQueryTextFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
mSelection.clear();
mSelection.addAll(getSelections());
notifyDataSetChanged();
} else {
mItemList.clear();
mItemList.addAll(backup.subList(0, backup.size() / 4));
setSelections(mSelection);
notifyDataSetChanged();
}
});
mFioriSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
return false;
}
@Override
public boolean onQueryTextChange(String s) {
if (!s.isEmpty()) {
updateSearch(s);
}
return true;
}
});
}
}
}
}
@NonNull
@Override
public TextView onCreateView(int viewType, @NonNull Context context) {
TextView view = new TextView(this);
view.setTextAppearance(com.sap.cloud.mobile.fiori.R.style.TextAppearance_Fiori_Body1);
view.setPadding(view.getPaddingStart(), 0, view.getPaddingEnd(), 0);
return view;
}
@Override
protected void onBindView(@NonNull TextView view, String id) {
view.setText(id);
}
@Override
protected int getItemViewType(int position) {
return 0;
}
@Override
protected int getItemCount() {
return mItemList.size();
}
@Override
protected void restoreData(@Nullable Bundle bundle) {
mItemList = bundle == null ? new ArrayList<>() : bundle.getStringArrayList(String.valueOf("ItemList"));
}
@Override
protected Bundle saveData() {
Bundle bundle = new Bundle();
bundle.putStringArrayList(String.valueOf("ItemList"), (ArrayList<String>) mItemList);
return bundle;
}
void updateSearch(String s) {
List<String> temp = new ArrayList<>(backup);
mItemList.clear();
for (String str : temp) {
if (str.contains(s)) {
mItemList.add(str);
}
}
notifyDataSetChanged();
setNewSelection(s);
}
void setNewSelection(String query) {
List<String> newSelections = new ArrayList<>();
for (String selection : getSelections()) {
if (selection.contains(query)) {
newSelections.add(selection);
}
}
setSelections(newSelections);
}
@Override
protected void onBindPosition(int pos) {
// Load more data if you wish
}
@Override
public String getId(int position) {
return mItemList.get(position);
}
@Override
protected void onSelectionChanged(String id, boolean isSelected) {
if (isSelected && !mSelection.contains(id)) {
mSelection.add(id);
} else {
mSelection.remove(id);
}
}
private ArrayList<Integer> setupData() {
ArrayList<Integer> itemList = new ArrayList<>();
for (int it = 0; it < 1000; ++it) {
itemList.add(it);
}
return itemList;
}
}
GenericListPickerFormCell
Fragment¶
You can replace the GenericListPickerFormCellActivity
with GenericListPickerFormCellFragment
to present the items in a list. This opens the list picker as a Bottom Sheet
on a phone and as an Alert Dialog
on a tablet. The Bottom Sheet
list picker, by default, opens in half-expanded view and, when dragged, opens in fully-expanded view. It can be changed to open directly in fully-expanded view using the API:
GenericListPickerFormCellFragment<TextView, String> pickerFragment =
new GenericListPickerFormCellFragment.GenericListPickerFormCellFragmentBuilder()
.build();
pickerFragment.setShowExpanded(true);
Unlike GenericListPickerFormCellActivity
,
GenericListPickerFormCellFragment
itself is not responsible for creating the list items but depends on GenericListPickerFormCellAdapter
class for the same.
Like GenericListPickerFormCellActivity
, GenericListPickerFormCellAdapter
also has similar abstract methods and two generic parameters:
V extends View
– Represents the type of views to be presented to user; for example,TextView
orObjectCell
.T extends Serializable
– Represents the type of key used to identify two different elements in the list being presented; for example, position of the item in actual list or item id from your database.
Abstract Methods | Description |
---|---|
int getItemCount() |
Informs the GenericListPickerFormCellActivity about the number of items in the List. |
int getItemViewType(int position) |
Inflates different types of list item views. This method informs the GenericListPickerFormCellActivity about type of the view at a given position. |
V onCreateView(int viewType, @NonNull Context context) |
Given a view type, creates the View. |
void onBindView(@NonNull V view, int position) |
This is where you bind your view with data. Given position and view bind it to data. |
T getId(int pos) |
Given a position in adapter, return the id used for the item. |
Here is a small snippet demonstrating the implementation:
GenericListPickerFormCell<ObjectCell, String> genericObjectCellPicker = view.findViewById(R.id.genericObjectCellPicker);
genericObjectCellPicker.setOnClickListener(v -> {
GenericListPickerFormCellFragment<ObjectCell, String> pickerFragment =
new GenericListPickerFormCellFragment.GenericListPickerFormCellFragmentBuilder()
.setTitle("Pick Object Cell")
.build();
pickerFragment.setGenericListPickerAdapter(v.getContext(), new ObjectCellPickerAdapter());
pickerFragment.setOnSelectionsUpdatedListener(selections -> genericObjectCellPicker.setValue(selections));
pickerFragment.showNow(getChildFragmentManager(), GenericListPickerFormCellFragment.TAG);
});
Important
While using GenericListPickerFormCellFragment
, the SDK has no way of determining when or how to add the fragment. Hence, an app should add the fragment whenever required, preferably in the onClick
event on GenericListPickerFormCell
.
Generic Picker Fragment on Phone
Generic Picker Fragment on Tablet
Selection Section¶
The list picker form cell comes with a selection section which, when it is enabled, shows all the selected items on top of the list. It also allows all the unselected items to be selected with a single click by clicking the Select All button and deselect all the selected items with a single click by clicking the Deselect All button. A Floating Action Button(FAB)
is also displayed when the user scrolls away from the selected section. Clicking on this FAB
takes the user back up to the selected section. You can enable or disable the selection section with the setShowSelected(boolean)
method.
Show selected Section | Do not show selected section |
---|---|
![]() |
![]() |
Single select mode of the GenericListPickerFormCell
does not support the selected section.
Left To Right¶
GenericListPickerFormCell
allows you to position the selector (checkbox or radio) button on either left of right end of the item view. Using setLeftToRight
API on GenericListPickerFormCell
, you can position the selector on either end.
By default, selectors are positioned on the start or left end of the item.
Selector on Left | Selector on Right |
---|---|
![]() |
![]() |
Paging Using GenericListPickerFormCell
¶
If it is desired to present a long list of items to the user, then it is good practice to load the items when required. Loading only partial lists saves memory and computation resources.
You can override the void onBindPosition(int pos)
method in GenericListPickerFormCellActivity
class to be notified when the adapter position of the item for which onBindView(@NonNull V view, T id)
is called. This gives you an indication as to whether your current list is going to be exhausted and you can trigger network calls to download more items.
@Override
protected void onBindPosition(int pos) {
if(pos < getItemCount() - 10) {
// trigger the network call to load more items as we have only 10 more spare items to present
}
}
Editable and Non-Editable Modes¶
This form cell can be set to editable or non-editable modes. For the list picker form cell, editable and enabled attributes are the same: a non-editable form cell is not enabled.
By default, the list picker form cell is editable and enabled. You can control the editability of the cell by using XML attribute app:isEditable="false
. You can
also fetch the view in your activity and set it to be editable using Java APIs.
GenericListPickerFormCell mPickerFormCell = findViewById(R.id.pickerCell);
mPickerFormCell.setIsEditable(false);
For more information about the editable attribute, see FormCell
.
Exit Dialog¶
When the user makes some selections and clicks the Close button, an optional warning dialog can be displayed asking the user whether they would like to save their selections or discard them. This dialog is displayed by default but can be hidden with the following API:
GenericListPickerFormCell mPickerFormCell = findViewById(R.id.pickerCell);
mPickerFormCell.setShowExitDialog(false);
Search¶
The GenericListPickerFormCell
also supports search functionality that allows users to search the list for specific items and select the ones that satisfy the search criteria. Developers can enable search and are responsible for implementing the filtering logic based on the type of the items.
The following sample illustrates how to enable search using GenericListPickerFormCellActivity
:
GenericListPickerFormCell mPickerFormCell = findViewById(R.id.pickerCell);
mPickerFormCell.setSearchEnabled(true);
mPickerFormCell.setPickerActivity(new GenericTextStringPickerActivity());
And then in the GenericTextStringPickerActivity
class:
@Override
protected void onResume() {
super.onResume();
// Get the GenericListPickerFormCellFragment object associated with this GenericListPickerFormCellActivity
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(GenericListPickerFormCellFragment.TAG);
if (fragment != null) {
GenericListPickerFormCellFragment listPickerDialogFragment = (GenericListPickerFormCellFragment) fragment;
// Get the root view for the fragment
View view = listPickerDialogFragment.getView();
// Get the fragment toolbar
MaterialToolbar toolbar = view.findViewById(com.sap.cloud.mobile.fiori.R.id.list_picker_toolbar);
if (toolbar != null) {
// Get the fragment toolbar's menu
Menu menu = toolbar.getMenu();
// Get the FioriSearchView menu item
FioriSearchView mFioriSearchView = (FioriSearchView) menu.findItem(R.id.appbar_search_menu).getActionView();
if (mFioriSearchView != null) {
mFioriSearchView.setOnQueryTextFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
// Hide selected section so that users only see all items while searching
mSelection.clear();
mSelection.addAll(getSelections());
notifyDataSetChanged();
} else {
// Show both selected and all items section
mItemList.clear();
mItemList.addAll(mBackupItemList));
setSelections(mSelection);
notifyDataSetChanged();
}
});
mFioriSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
return false;
}
@Override
public boolean onQueryTextChange(String s) {
if (!s.isEmpty()) {
// The search filtering logic
updateSearch(s);
}
return true;
}
});
}
}
}
}
Important
The search logic should be implemented inside the onResume()
method of the GenericListPickerFormCellActivity
. Implementing it inside the onCreate()
method will not lead to the desired behavior, since the views will not yet have been instantiated.
The following sample illustrates how to implement a search using GenericListPickerFormCellFragment
:
GenericListPickerFormCell<ObjectCell, String> genericObjectCellPicker = view.findViewById(R.id.genericObjectCellPicker);
genericObjectCellPicker.setOnClickListener(v -> {
GenericListPickerFormCellFragment<ObjectCell, String> pickerFragment =
new GenericListPickerFormCellFragment.GenericListPickerFormCellFragmentBuilder()
.setTitle("Pick Object Cell")
.setSearchEnabled(true)
.build();
pickerFragment.setGenericListPickerAdapter(v.getContext(), new ObjectCellPickerAdapter());
pickerFragment.setSearchOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (!TextUtils.isEmpty(newText)) {
adapter.updateSearch(newText);
pickerFragment.notifyDataSetChanged();
}
return true;
}
});
pickerFragment.setSearchOnQueryTextFocusChangeListener((v1, hasFocus) -> {
if (!hasFocus) {
adapter.restoreDataFromBackup();
}
pickerFragment.notifyDataSetChanged();
});
pickerFragment.showNow(getChildFragmentManager(), GenericListPickerFormCellFragment.TAG);
});
Save and Dismiss on Single Select¶
In the case of single selection, the GenericListPickerFormCell
can be configured to save the selection and close the picker without the user having to click the Apply button. When this is enabled, the footer can also optionally be hidden so that the Apply button is not displayed. This can be achieved as follows:
GenericListPickerFormCell mPickerFormCell = findViewById(R.id.pickerCell);
mPickerFormCell.setSingleSelectOnly(true);
mPickerFormCell.setDismissOnSingleSelection(true);
// Optionally hide the footer
mPickerFormCell.setHideFooterWhenDismissOnSingleSelection(true);
Error and Helper¶
GenericListPickerFormCell
supports setting error and helper messages and icons that can be used for validating user input.
To set the error message:
GenericListPickerFormCell mPickerFormCell = findViewById(R.id.pickerCell);
mPickerFormCell.setErrorEnabled(true);
mPickerFormCell.setError("Error Message");
// Use default error icon
mPickerFormCell.setErrorIcon(null);
To set the helper message:
GenericListPickerFormCell mPickerFormCell = findViewById(R.id.pickerCell);
mPickerFormCell.setHelperEnabled(true);
mPickerFormCell.setHelperText("Success Message");
Drawable helperIcon = ResourcesCompat.getDrawable(getResources(), com.sap.cloud.mobile.fiori.R.drawable.ic_sap_icon_accept, context.getTheme());
int helperIconColor = MaterialColors.getColor(context, R.attr.sap_fiori_color_semantic_positive,
context.getResources().getColor(R.color.sap_ui_positive_semantic_color, context.getTheme()));
mPickerFormCell.setHelperTextIcon(helperIcon, helperIconColor);
Listening for Cell Value Changes¶
Like all FormCells
, GenericListPickerFormCell
notifies the application about changes through CellValueChangeListener
. To listen for updates to a cell value,
attach a CellValueChangeListener
using setCellValueChangeListener
:
mPickerFormCell.setCellValueChangeListener(new FormCell.CellValueChangeListener<List<T>>() {
@Override
protected void cellChangeHandler(@NonNull List<T> value) {
// Application logic here
}
});
Resetting Selections¶
Users can revert their current selections to the last saved selections by clicking the Reset button. This can be enabled by calling setResetEnabled(true)
on the GenericListPickerFormCell
when using the GenericListPickerFormCellActivity
or on the GenericListPickerFormCellFragmentBuilder
when using GenericListPickerFormCellFragment
.
While using GenericListPickerFormCellActivity
:
GenericListPickerFormCell<TextView, String> genericTextPickerString = view.findViewById(R.id.genericTextPickerString);
genericTextPickerString.setPickerActivity(new GenericTextStringPickerActivity());
genericTextPickerString.setResetEnabled(true);
While using GenericListPickerFormCellFragment
:
GenericListPickerFormCellFragment<TextView, String> pickerFragment =
new GenericListPickerFormCellFragment.GenericListPickerFormCellFragmentBuilder()
.setResetEnabled(true)
.build();
A default label is provided but application developers can change it by calling the setResetButtonLabel()
API.
Sections in List Picker¶
Items in the generic list picker can be displayed within different sections. This allows application developers to categorize the items and enable users to select or deselect all items belonging to a particular section or perform other actions on them.
When using the GenericListPickerFormCellActivity
, application developers need to override the List<GenericListPickerSection<T>> getSections()
and the void onBindSectionHeader()
methods. The GenericListPickerSection
class is used to define the section's id, the number of items belonging to the section, and whether the items are single or multi select. The items in the section need to be configured using the onCreateView()
, onBindView()
, getItemCount()
, and getId()
methods of the GenericListPickerFormCellActivity
. Following is a code snippet:
public class GenericTextStringPickerActivity extends GenericListPickerFormCellActivity<TextView, String> {
@NonNull
private List<String> mItemList;
private List<GenericListPickerSection<String>> mSectionsList;
private final static int TOTAL_NUMBER_OF_ITEMS = 12;
private final static int NUMBER_OF_ITEMS_IN_SECTION = 4;
public GenericTextStringPickerActivity() {
mItemList = new ArrayList<>(loadData());
mSectionsList = new ArrayList<>();
}
@NonNull
@Override
public TextView onCreateView(int viewType, @NonNull Context context) {
TextView view = new TextView(this);
view.setTextAppearance(com.sap.cloud.mobile.fiori.R.style.TextAppearance_Fiori_Body1);
view.setPadding(view.getPaddingStart(), 0, view.getPaddingEnd(), 0);
return view;
}
@Override
protected void onBindView(@NonNull TextView view, String id) {
view.setText(id);
}
@Override
protected int getItemViewType(int position) {
return 0;
}
@Override
protected int getItemCount() {
return TOTAL_NUMBER_OF_ITEMS;
}
@Override
public String getId(int position) {
return mItemList.get(position);
}
@Override
protected List<GenericListPickerSection<String>> getSections() {
if (mSectionsList.isEmpty()) {
for (int i = 0, j = 1; i < mItemList.size(); i = i + NUMBER_OF_ITEMS_IN_SECTION, j++) {
String sectionId = "Section " + j;
boolean isNotLastSection = i + NUMBER_OF_ITEMS_IN_SECTION < mItemList.size();
GenericListPickerSection<String> section = new GenericListPickerSection<>(sectionId, NUMBER_OF_ITEMS_IN_SECTION, false, isNotLastSection);
mSectionsList.add(section);
}
}
return mSectionsList;
}
@Override
protected void onBindSectionHeader(@NonNull AppCompatTextView mCompatTextView, @NonNull Button button, @NonNull String sectionId) {
mCompatTextView.setText(sectionId);
}
@NonNull
private ArrayList<String> loadData() {
ArrayList<String> itemList = new ArrayList<>();
for (int it = 0; it < TOTAL_NUMBER_OF_ITEMS; ++it) {
String text = "Item " +it;
itemList.add(text);
}
return itemList;
}
}
The same methods need to be overridden in the GenericListPickerFormCellAdapter
while using the GenericListPickerFormCellFragment
.
public class GenericListPickerSectionAdapter extends GenericListPickerFormCellAdapter<TextView, String> {
private final List<String> mItemList;
private final List<GenericListPickerSection<String>> mSectionsList;
private final static int TOTAL_NUMBER_OF_ITEMS = 12;
private final static int NUMBER_OF_ITEMS_IN_SECTION = 4;
GenericListPickerSectionAdapter() {
mItemList = new ArrayList<>(loadData());
mSectionsList = new ArrayList<>();
}
@NonNull
@Override
protected TextView onCreateView(int viewType, @NonNull Context context) {
TextView view = new TextView(this);
view.setTextAppearance(com.sap.cloud.mobile.fiori.R.style.TextAppearance_Fiori_Body1);
view.setPadding(view.getPaddingStart(), 0, view.getPaddingEnd(), 0);
return view;
}
@Override
protected void onBindView(@NonNull TextView view, String id) {
view.setText(id);
}
@Override
protected int getItemViewType(int position) {
return 0;
}
@Override
protected int getItemCount() {
return TOTAL_NUMBER_OF_ITEMS;
}
@Override
protected String getId(int pos) {
return mItemList.get(pos);
}
@Override
protected List<GenericListPickerSection<String>> getSections() {
if (mSectionsList.isEmpty()) {
for (int i = 0, j = 1; i < mItemList.size(); i = i + NUMBER_OF_ITEMS_IN_SECTION, j++) {
String sectionId = "Section " + j;
boolean isNotLastSection = i + NUMBER_OF_ITEMS_IN_SECTION < mItemList.size();
GenericListPickerSection<String> section = new GenericListPickerSection<>(sectionId, NUMBER_OF_ITEMS_IN_SECTION, true, isNotLastSection);
mSectionsList.add(section);
}
}
return mSectionsList;
}
@Override
protected void onBindSectionHeader(@NonNull AppCompatTextView mCompatTextView, @NonNull Button button, @NonNull String sectionId) {
mCompatTextView.setText(sectionId);
}
@NonNull
private ArrayList<String> loadData() {
ArrayList<String> itemList = new ArrayList<>();
for (int it = 0; it < TOTAL_NUMBER_OF_ITEMS; ++it) {
String text = "Item " +it;
itemList.add(text);
}
return itemList;
}
}
Progress Indicator in List Picker¶
While items are being fetched and loaded into the generic list picker, a circular progress indicator can be displayed which notifies the user of the item retrieval and loading process. Application developers can use the toggleFioriProgressBarVisibility()
method to toggle the circular progress indicator's visibility along with the onBindPosition()
method to load more items. Following is a code snippet when using the GenericListPickerFormCellFragment
and the same can be done with the GenericListPickerFormCellActivity
.
First, define the GenericListPickerFormCellAdapter
like this:
public class GenericListPickerStringAdapter extends GenericListPickerFormCellAdapter<TextView, String> {
@NonNull
private List<String> mItemList;
private ProgressIndicatorListener mProgressIndicatorListener;
private final static int TOTAL_NUMBER_OF_ITEMS = 40;
public GenericListPickerStringAdapter() {
mItemList = new ArrayList<>(loadData(0));
}
@NonNull
@Override
public TextView onCreateView(int viewType, @NonNull Context context) {
TextView view = new TextView(this);
view.setTextAppearance(com.sap.cloud.mobile.fiori.R.style.TextAppearance_Fiori_Body1);
view.setPadding(view.getPaddingStart(), 0, view.getPaddingEnd(), 0);
return view;
}
@Override
protected void onBindView(@NonNull TextView view, String id) {
view.setText(id);
}
@Override
protected int getItemViewType(int position) {
return 0;
}
@Override
protected int getItemCount() {
return TOTAL_NUMBER_OF_ITEMS;
}
@Override
public String getId(int position) {
return mItemList.get(position);
}
@Override
protected void onBindPosition(int pos) {
super.onBindPosition(pos);
// Load more data
if (pos >= mItemList.size() - 1 && mProgressIndicatorListener != null) {
mProgressIndicatorListener.onLastItemReached();
new Handler(Looper.getMainLooper()).postDelayed(() -> {
mItemList.addAll(loadData(mItemList.size()));
mProgressIndicatorListener.onMoreDataLoaded();
}, 5000);
}
}
@NonNull
private ArrayList<String> loadData(int start) {
ArrayList<String> itemList = new ArrayList<>();
for (int it = start; it < start + TOTAL_NUMBER_OF_ITEMS; ++it) {
String text = "Item " +it;
itemList.add(text);
}
return itemList;
}
interface ProgressIndicatorListener {
void onLastItemReached();
void onMoreDataLoaded();
}
}
And then with the GenericListPickerFormCellFragment
:
GenericListPickerFormCell<TextView, String> progressIndicatorListPicker = findViewById(R.id.generic_list_picker_progress_indicator);
GenericListPickerStringAdapter progressIndicatorPickerAdapter = new GenericListPickerStringAdapter();
progressIndicatorListPicker.setOnClickListener(v -> {
GenericListPickerFormCellFragment<TextView, String> pickerFragment =
new GenericListPickerFormCellFragment.GenericListPickerFormCellFragmentBuilder()
.build();
progressIndicatorPickerAdapter.setProgressIndicatorListener(new GenericListPickerStringAdapter.ProgressIndicatorListener() {
@Override
public void onLastItemReached() {
pickerFragment.toggleFioriProgressBarVisibility(true);
}
@Override
public void onMoreDataLoaded() {
// call notifyDataSetChanged so that adapter displays the newly loaded items
pickerFragment.notifyDataSetChanged();
pickerFragment.toggleFioriProgressBarVisibility(false);
}
});
pickerFragment.showNow(getSupportFragmentManager(), GenericListPickerFormCellFragment.TAG);
});
Required Field¶
A generic list picker can be marked as a required field by passing true
to the setIsRequired()
method or setting the isRequired
XML attribute to true. This will add an asterisk (*
) at the end of the label, to indicate that a value must be selected. Note that this does not validate whether a value has been chosen or not. To validate the requirement, refer to Error and Helper.
GenericListPickerFormCell mPickerFormCell = findViewById(R.id.pickerFormCellRequired);
mPickerFormCell.setIsRequired(true);
<com.sap.cloud.mobile.fiori.formcell.GenericListPickerFormCell
android:id="@+id/generic_list_picker_required"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:key="Required List Picker"
app:isRequired="true"/>
See also FormCell
.