Skip to content

Instantly share code, notes, and snippets.

@ar-android
Last active October 31, 2017 13:06
Show Gist options
  • Save ar-android/32fdc2168b71886ff35af02f6ca0adb9 to your computer and use it in GitHub Desktop.
Save ar-android/32fdc2168b71886ff35af02f6ca0adb9 to your computer and use it in GitHub Desktop.
<?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="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="EditSpinner"
android:gravity="center"
android:textSize="20dp"
android:layout_marginTop="40dp"/>
<com.ocittwo.editspinner.EditableSpinner
android:id="@+id/edit_spinner_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:hint="enter security question"
android:textColorHint="#aa828282"
android:textSize="18dp"
android:padding="8dp"
app:dropDownDrawable="@drawable/picker"
app:dropDownDrawableSpacing="15dp"
app:dropDownDrawableWidth="25dp"
app:dropDownDrawableHeight="25dp"
app:dropDownAnimStyle="@style/CustomPopupAnimation"
/>
<com.ocittwo.editspinner.EditableSpinner
android:id="@+id/edit_spinner_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="@drawable/custom_editor_bkg"
android:hint="enter custom text here"
android:textColorHint="#aa828282"
android:textSize="18dp"
android:padding="8dp"
/>
</LinearLayout>
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.Selection;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListPopupWindow;
import android.widget.PopupWindow;
/**
* EditSpinner
* modified from {@link android.widget.AutoCompleteTextView}
*
* @author xyxyLiu [email protected]
*/
public class EditableSpinner extends EditText {
private static final boolean DEBUG = BuildConfig.DEBUG_LOG;
private static final String TAG = "EditSpinner";
private static final long TIMEOUT_POPUP_DISMISS = 200l;
private ListPopupWindow mPopup;
private ListAdapter mAdapter;
private int mDropDownAnchorId;
private Drawable mDropDownDrawable;
private PopupWindow.OnDismissListener mOnDismissListener;
private OnShowListener mOnShowListener;
private AdapterView.OnItemClickListener mItemClickListener;
private AdapterView.OnItemSelectedListener mItemSelectedListener;
private ItemConverter mItemConverter;
private boolean mDropDownDismissedOnCompletion = true;
private long mLastDismissTime = 0l;
private boolean mDropDownTouchedDown = false;
private boolean mOpenBefore;
private boolean mIsEditable = true;
private KeyListener mKeyListener;
public EditSpinner(Context context) {
super(context);
}
public EditSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
initFromAttributes(context, attrs, 0);
}
public EditSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initFromAttributes(context, attrs, defStyleAttr);
}
private void initFromAttributes(Context context, AttributeSet attrs, int defStyleAttr) {
final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.EditSpinner, defStyleAttr, 0);
mPopup = new ListPopupWindow(context, attrs);
mPopup.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
mPopup.setPromptPosition(ListPopupWindow.POSITION_PROMPT_BELOW);
Drawable selector = a.getDrawable(R.styleable.EditSpinner_dropDownSelector);
if (selector != null) {
mPopup.setListSelector(selector);
}
int dropDownAnimStyleResId = a.getResourceId(R.styleable.EditSpinner_dropDownAnimStyle, -1);
if (dropDownAnimStyleResId > 0) {
setDropDownAnimationStyle(dropDownAnimStyleResId);
}
mDropDownDrawable = a.getDrawable(R.styleable.EditSpinner_dropDownDrawable);
int dropDownDrawableSpacing = a.getDimensionPixelOffset(R.styleable.EditSpinner_dropDownDrawableSpacing, 0);
if (mDropDownDrawable != null) {
int dropDownDrawableWidth = a.getDimensionPixelOffset(R.styleable.EditSpinner_dropDownDrawableWidth, -1);
int dropDownDrawableHeight = a.getDimensionPixelOffset(R.styleable.EditSpinner_dropDownDrawableHeight, -1);
setDropDownDrawable(mDropDownDrawable, dropDownDrawableWidth, dropDownDrawableHeight);
setDropDownDrawableSpacing(dropDownDrawableSpacing);
}
// Get the anchor's id now, but the view won't be ready, so wait to actually get the
// view and store it in mDropDownAnchorView lazily in getDropDownAnchorView later.
// Defaults to NO_ID, in which case the getDropDownAnchorView method will simply return
// this TextView, as a default anchoring point.
mDropDownAnchorId = a.getResourceId(R.styleable.EditSpinner_dropDownAnchor,
View.NO_ID);
// For dropdown width, the developer can specify a specific width, or MATCH_PARENT
// (for full screen width) or WRAP_CONTENT (to match the width of the anchored view).
mPopup.setWidth(a.getLayoutDimension(R.styleable.EditSpinner_dropDownWidth,
ViewGroup.LayoutParams.WRAP_CONTENT));
mPopup.setHeight(a.getLayoutDimension(R.styleable.EditSpinner_dropDownHeight,
ViewGroup.LayoutParams.WRAP_CONTENT));
mPopup.setOnItemClickListener(new DropDownItemClickListener());
mPopup.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
mLastDismissTime = SystemClock.elapsedRealtime();
if (mOnDismissListener != null) {
mOnDismissListener.onDismiss();
}
}
});
a.recycle();
mIsEditable = getKeyListener() != null;
setFocusable(true);
addTextChangedListener(new MyWatcher());
}
/**
* set whether it can be edited
* @param isEditable isEditable
*/
public void setEditable(boolean isEditable) {
if (mIsEditable == isEditable) return;
mIsEditable = isEditable;
if (isEditable) {
if (mKeyListener != null) {
setKeyListener(mKeyListener);
}
} else {
mKeyListener = getKeyListener();
setKeyListener(null);
}
}
public int getDropDownWidth() {
return mPopup.getWidth();
}
/**
* <p>Sets the current width for the auto-complete drop down list. This can
* be a fixed width, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill the screen, or
* {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p>
* @param width the width to use
*/
public void setDropDownWidth(int width) {
mPopup.setWidth(width);
}
public int getDropDownHeight() {
return mPopup.getHeight();
}
/**
* <p>Sets the current height for the auto-complete drop down list. This can
* be a fixed height, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill
* the screen, or {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the height
* of the drop down's content.</p>
* @param height the height to use
*/
public void setDropDownHeight(int height) {
mPopup.setHeight(height);
}
/**
* <p>Returns the id for the view that the auto-complete drop down list is anchored to.</p>
* @return the view's id, or {@link View#NO_ID} if none specified
*/
public int getDropDownAnchor() {
return mDropDownAnchorId;
}
/**
* <p>Sets the view to which the auto-complete drop down list should anchor. The view
* corresponding to this id will not be loaded until the next time it is needed to avoid
* loading a view which is not yet instantiated.</p>
* @param id the id to anchor the drop down list view to
*/
public void setDropDownAnchor(int id) {
mDropDownAnchorId = id;
mPopup.setAnchorView(null);
}
public Drawable getDropDownBackground() {
return mPopup.getBackground();
}
/**
* <p>Sets the background of the auto-complete drop-down list.</p>
* @param d the drawable to set as the background
*/
public void setDropDownBackgroundDrawable(Drawable d) {
mPopup.setBackgroundDrawable(d);
}
/**
* <p>Sets the background of the auto-complete drop-down list.</p>
* @param id the id of the drawable to set as the background
*/
public void setDropDownBackgroundResource(int id) {
mPopup.setBackgroundDrawable(getContext().getResources().getDrawable(id));
}
public int getDropDownVerticalOffset() {
return mPopup.getVerticalOffset();
}
/**
* <p>Sets the vertical offset used for the auto-complete drop-down list.</p>
* @param offset the vertical offset
*/
public void setDropDownVerticalOffset(int offset) {
mPopup.setVerticalOffset(offset);
}
public int getDropDownHorizontalOffset() {
return mPopup.getHorizontalOffset();
}
/**
* <p>Sets the horizontal offset used for the auto-complete drop-down list.</p>
* @param offset the horizontal offset
*/
public void setDropDownHorizontalOffset(int offset) {
mPopup.setHorizontalOffset(offset);
}
public int getDropDownAnimationStyle() {
return mPopup.getAnimationStyle();
}
/**
* <p>Sets the animation style of the auto-complete drop-down list.</p>
*
* <p>If the drop-down is showing, calling this method will take effect only
* the next time the drop-down is shown.</p>
* @param animationStyle animation style to use when the drop-down appears
* and disappears. Set to -1 for the default animation, 0 for no
* animation, or a resource identifier for an explicit animation.
*/
public void setDropDownAnimationStyle(int animationStyle) {
mPopup.setAnimationStyle(animationStyle);
}
/**
* Checks whether the drop-down is dismissed when a item is clicked.
* @return isDropDownDismissedOnCompletion
*/
public boolean isDropDownDismissedOnCompletion() {
return mDropDownDismissedOnCompletion;
}
/**
* Sets whether the drop-down is dismissed when a suggestion is clicked. This is
* true by default.
* @param dropDownDismissedOnCompletion Whether to dismiss the drop-down.
*/
public void setDropDownDismissedOnCompletion(boolean dropDownDismissedOnCompletion) {
mDropDownDismissedOnCompletion = dropDownDismissedOnCompletion;
}
public void clearListSelection() {
mPopup.clearListSelection();
}
public int getListSelection() {
return mPopup.getSelectedItemPosition();
}
public void setListSelection(int position) {
mPopup.setSelection(position);
}
public void selectItem(int index) {
if (mAdapter != null && index >= 0 && index < mAdapter.getCount()) {
selectItem(mAdapter.getItem(index));
}
}
private void selectItem(Object selectedItem) {
if (selectedItem != null) {
replaceText(convertSelectionToString(selectedItem));
}
}
public void setDropDownDrawable(Drawable drawable) {
setDropDownDrawable(drawable, -1, -1);
}
public void setDropDownDrawable(Drawable drawable, int width, int height) {
mDropDownDrawable = drawable;
if (width >= 0 && height >= 0) {
drawable.setBounds(new Rect(0, 0, width, height));
setCompoundDrawables(null, null, drawable, null);
} else {
setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null);
}
}
public boolean isPopupShowing() {
return mPopup.isShowing();
}
public void showDropDown() {
if (mPopup.getAnchorView() == null) {
if (mDropDownAnchorId != View.NO_ID) {
mPopup.setAnchorView(getRootView().findViewById(mDropDownAnchorId));
} else {
mPopup.setAnchorView(this);
}
}
if (!isPopupShowing()) {
// Make sure the list does not obscure the IME when shown for the first time.
mPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NEEDED);
}
requestFocus();
mPopup.show();
mPopup.getListView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);
if (mOnShowListener != null) {
mOnShowListener.onShow();
}
}
public void dismissDropDown() {
mPopup.dismiss();
}
public void setAdapter(ListAdapter adapter) {
mAdapter = adapter;
mPopup.setAdapter(mAdapter);
}
public void setDropDownDrawableSpacing(int spacing) {
setCompoundDrawablePadding(spacing);
}
public int getDropDownDrawableSpacing() {
return getCompoundDrawablePadding();
}
public void setOnDismissListener(final PopupWindow.OnDismissListener dismissListener) {
mOnDismissListener = dismissListener;
}
public void setOnShowListener(final OnShowListener showListener) {
mOnShowListener = showListener;
}
public void setOnItemClickListener(AdapterView.OnItemClickListener l) {
mItemClickListener = l;
}
public void setItemConverter(ItemConverter itemConverter) {
mItemConverter = itemConverter;
}
protected void performCompletion() {
performCompletion(null, -1, -1);
}
protected void performCompletion(View selectedView, int position, long id) {
if (isPopupShowing()) {
Object selectedItem;
if (position < 0) {
selectedItem = mPopup.getSelectedItem();
} else {
selectedItem = mAdapter.getItem(position);
}
if (selectedItem == null) {
if (DEBUG) {
Log.w(TAG, "performCompletion: no selected item");
}
return;
}
selectItem(selectedItem);
if (mItemClickListener != null) {
final ListPopupWindow list = mPopup;
if (selectedView == null || position < 0) {
selectedView = list.getSelectedView();
position = list.getSelectedItemPosition();
id = list.getSelectedItemId();
}
mItemClickListener.onItemClick(list.getListView(), selectedView, position, id);
}
}
if (mDropDownDismissedOnCompletion) {
dismissDropDown();
}
}
protected void replaceText(CharSequence text) {
clearComposingText();
setText(text);
// make sure we keep the caret at the end of the text view
Editable spannable = getText();
Selection.setSelection(spannable, spannable.length());
}
protected CharSequence convertSelectionToString(Object selectedItem) {
if (mItemConverter != null) {
return mItemConverter.convertItemToString(selectedItem);
} else {
return selectedItem.toString();
}
}
@Override
protected void onDisplayHint(int hint) {
super.onDisplayHint(hint);
switch (hint) {
case INVISIBLE:
dismissDropDown();
break;
}
}
@Override
protected boolean setFrame(final int l, int t, final int r, int b) {
boolean result = super.setFrame(l, t, r, b);
if (isPopupShowing()) {
showDropDown();
}
return result;
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (!focused) {
dismissDropDown();
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
dismissDropDown();
super.onDetachedFromWindow();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (DEBUG) {
Log.d(TAG, "onTouchEvent() event = " + event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
if (isInDropDownClickArea(event)) {
mDropDownTouchedDown = true;
return true;
} else {
mDropDownTouchedDown = false;
}
break;
}
case MotionEvent.ACTION_UP: {
if (mDropDownTouchedDown && isInDropDownClickArea(event)) {
if (SystemClock.elapsedRealtime() - mLastDismissTime > TIMEOUT_POPUP_DISMISS) {
clearFocus();
showDropDown();
return true;
} else {
dismissDropDown();
}
}
}
}
return super.onTouchEvent(event);
}
private boolean isInDropDownClickArea(MotionEvent event) {
int areaLeft = mIsEditable ? getWidth() - getCompoundPaddingRight() : 0;
int areaRight = getWidth();
int areaTop = 0;
int areaBottom = getHeight();
if (DEBUG) {
Log.d(TAG, String.format("x = %d, y = %d, areaLeft = %d, areaRight = %d, areaTop = %d, areaBottom = %d",
(int) event.getX(), (int) event.getY(), areaLeft, areaRight, areaTop, areaBottom));
}
if (event.getX() > areaLeft && event.getX() < areaRight && event.getY() > areaTop && event.getY() < areaBottom) {
return true;
} else {
return false;
}
}
void doBeforeTextChanged() {
// when text is changed, inserted or deleted, we attempt to show
// the drop down
mOpenBefore = isPopupShowing();
if (DEBUG) {
Log.v(TAG, "before text changed: open=" + mOpenBefore);
}
}
void doAfterTextChanged() {
// if the list was open before the keystroke, but closed afterwards,
// then something in the keystroke processing (an input filter perhaps)
// called performCompletion() and we shouldn't do any more processing.
if (DEBUG) {
Log.v(TAG, "after text changed: openBefore=" + mOpenBefore
+ " open=" + isPopupShowing());
}
if (mOpenBefore && !isPopupShowing()) {
return;
}
if (isPopupShowing()) {
dismissDropDown();
}
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && isPopupShowing()) {
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
KeyEvent.DispatcherState state = getKeyDispatcherState();
if (state != null) {
state.startTracking(event, this);
}
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
KeyEvent.DispatcherState state = getKeyDispatcherState();
if (state != null) {
state.handleUpEvent(event);
}
if (event.isTracking() && !event.isCanceled()) {
dismissDropDown();
return true;
}
}
}
return super.onKeyPreIme(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
boolean consumed = mPopup.onKeyUp(keyCode, event);
if (consumed) {
switch (keyCode) {
// if the list accepts the key events and the key event
// was a click, the text view gets the selected item
// from the drop down as its content
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_TAB:
if (event.hasNoModifiers()) {
performCompletion();
}
return true;
}
}
if (isPopupShowing() && keyCode == KeyEvent.KEYCODE_TAB && event.hasNoModifiers()) {
performCompletion();
return true;
}
return super.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mPopup.onKeyDown(keyCode, event)) {
return true;
}
if (isPopupShowing() && keyCode == KeyEvent.KEYCODE_TAB && event.hasNoModifiers()) {
return true;
}
boolean handled = super.onKeyDown(keyCode, event);
if (handled && isPopupShowing()) {
clearListSelection();
}
return handled;
}
@Override
public void setCompoundDrawables(@Nullable Drawable left, @Nullable Drawable top,
@Nullable Drawable right, @Nullable Drawable bottom) {
super.setCompoundDrawables(left, top, mDropDownDrawable != null ? mDropDownDrawable : right, bottom);
}
/**
* Convert list item to string, which will be showed in EditText
*/
public interface ItemConverter {
String convertItemToString(Object selectedItem);
}
/**
* Callback when popup window showed
*/
public interface OnShowListener {
void onShow();
}
/**
* This is used to watch for edits to the text view.
*/
private class MyWatcher implements TextWatcher {
public void afterTextChanged(Editable s) {
doAfterTextChanged();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
doBeforeTextChanged();
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
private class DropDownItemClickListener implements AdapterView.OnItemClickListener {
public void onItemClick(AdapterView parent, View v, int position, long id) {
performCompletion(v, position, id);
}
}
}
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
EditableSpinner mEditSpinner1;
EditableSpinner mEditSpinner2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// EditSpinner 1:
mEditableSpinner = (EditableSpinner) findViewById(R.id.edit_spinner_1);
ListAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item,
getResources().getStringArray(R.array.edits_array_1));
mEditableSpinner.setAdapter(adapter);
// triggered when dropdown popup window dismissed
mEditableSpinner.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
Log.d(TAG, "mEditSpinner1 popup window dismissed!");
}
});
// triggered when dropdown popup window shown
mEditableSpinner.setOnShowListener(new EditableSpinner.OnShowListener() {
@Override
public void onShow() {
// maybe you want to hide the soft input panel when the popup window is showing.
hideSoftInputPanel();
}
});
// other optional configurations:
// use setEditable() to dynamically set whether it can be Edited.
// Notice: it won't work if you set android:editable="false" in xml.
// mEditableSpinner.setEditable(false);
// set the dropdown drawable on the right of EditText and its size
// mEditableSpinner.setDropDownDrawable(getResources().getDrawable(R.drawable.picker), 60, 60);
// set the spacing bewteen Edited area and DropDown click area
// mEditableSpinner.setDropDownDrawableSpacing(50);
// set DropDown animation of the popup window
// mEditableSpinner.setDropDownAnimationStyle(R.style.CustomPopupAnimation);
// set DropDown popup window background
// mEditableSpinner.setDropDownBackgroundResource(R.drawable.your_custom_dropdown_bkg);
// set the selection
// mEditableSpinner.selectItem(1);
// see more in EditSpinner
// EditSpinner 2:
final String[] stringArray2 = getResources().getStringArray(R.array.edits_array_2);
iEditableSpinner = (EditableSpinner) findViewById(R.id.edit_spinner_2);
iEditableSpinner.setDropDownDrawable(getResources().getDrawable(R.drawable.spinner), 25, 25);
iEditableSpinner.setDropDownDrawableSpacing(50);
iEditableSpinner.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, stringArray2));
// it converts the item in the list to a string shown in EditText.
iEditableSpinner.setItemConverter(new EditableSpinner.ItemConverter() {
@Override
public String convertItemToString(Object selectedItem) {
if (selectedItem.toString().equals(stringArray2[stringArray2.length - 1])) {
return "";
} else {
return selectedItem.toString();
}
}
});
// triggered when one item in the list is clicked
iEditableSpinner.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "onItemClick() position = " + position);
if (position == stringArray2.length - 1) {
showSoftInputPanel(mEditSpinner2);
}
}
});
iEditableSpinner.setOnShowListener(new EditableSpinner.OnShowListener() {
@Override
public void onShow() {
hideSoftInputPanel();
}
});
// select the first item initially
iEditableSpinner.selectItem(0);
}
private void hideSoftInputPanel() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(mEditSpinner1.getWindowToken(), 0);
}
}
private void showSoftInputPanel(View view) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.showSoftInput(view, 0);
}
}
}
<resources>
<string name="app_name">EditableSpinner</string>
<string name="action_settings">Settings</string>
<string-array name="edits_array_1">
<item>What is your favorite color?</item>
<item>When is your dad\'s birthday?</item>
<item>When was your first date?</item>
<item>Who was your childhood hero?</item>
<item>What is GF/BF\'s nickname?</item>
</string-array>
<string-array name="edits_array_2">
<item>text one</item>
<item>text two</item>
<item>text three</item>
<item>custom text</item>
</string-array>
</resources>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment