Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8371661
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 9, 20262026-06-09T14:13:04+00:00 2026-06-09T14:13:04+00:00

I’d like to have a TextView display text, and when you click/longclick on it,

  • 0

I’d like to have a TextView display text, and when you click/longclick on it, a textbox should “show up” and allow editing of said text. When you’re done editing (onkey enter i suppose) it should revert back to a textview with the updated text…

I’m wondering if it’s feasable to implement such a widget or should I hack a workaround? Tips and suggestions are very welcome.

If you need further idea of what I mean, just go to your e.g. (windows) skype profile and see for yourself.

EDIT:
Clarification: I’m specifically asking for a widget or such which is a textview until clicked on, then transforms to an edittext containing the same text; once done editing it transforms back to a textview representing the new changed text. Thats what i mean by “edittext on demand widget”.

But I’m hoping to get something better than

public class Widget {
     TextView text;
     EditText edit;
     String   textToRepresent;
     //...
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-09T14:13:06+00:00Added an answer on June 9, 2026 at 2:13 pm

    Like I said on thursday… Yul was pretty close but not quite close. He did have a general same idea but (theoretically) rushed into code too early 😉

    The TextBoxOnDemand code supplied below is production-ready. The idea is similar to what I wanted to avoid in the OP and what Yul suggested, but with optimal implementation (using a ViewSwitcher instead of a RelativeLayout for instance)

    I gathered the resources needed for this in the following articles:

    Creating custom view from xml

    Declaring a custom android UI element using XML

    Defining custom attrs

    How to pass custom component parameters in java and xml

    http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/

    and decided to post them here because the official Google “training” docs are useless and are either obsolete (deprecated) or do not cover what I needed. I hope you don’t mind me claiming my own bounty, but this is the solution I wanted (and expected, ergo the bounty).
    I guess the code will have to do 😉

    TextBoxOnDemand.java:

        package com.skype.widget;
    
    import android.content.Context;
    import android.content.res.ColorStateList;
    import android.content.res.TypedArray;
    import android.text.SpannableString;
    import android.text.style.UnderlineSpan;
    import android.text.util.Linkify;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.KeyEvent;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnFocusChangeListener;
    import android.view.View.OnHoverListener;
    import android.view.View.OnLongClickListener;
    import android.widget.EditText;
    import android.widget.ImageButton;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    import android.widget.TextView.OnEditorActionListener;
    import android.widget.ViewSwitcher;
    
    import com.skype.ref.R;
    import com.skype.ref.RemoteKeys;
    
    public class TextBoxOnDemand extends ViewSwitcher implements OnClickListener, OnLongClickListener, OnFocusChangeListener, OnHoverListener,
            OnEditorActionListener
    {
        public static final String  LOGTAG          = "TextBoxOnDemand";
    
        private View                btmGuard;
        private ImageButton         cancel, accept;
        private EditText            editor;
        private RelativeLayout      editorLayout;
        private TextView            face;
        private String              hint            = new String();
        private boolean             inEditMode      = false;                    //normally this is in textview mode
        private boolean             inputReady      = false;
        private String              ourData         = new String();
        private String              prefillData     = new String();
        private String              tag             = new String();         //usually tag is empty.
        private View                topGuard;
        private int                 autoLinkMask;// = Linkify.EMAIL_ADDRESSES;  //Linkify.ALL;
        private ColorStateList      textColor, hintColor = null;
    
        public TextBoxOnDemand(Context context)
        {
            super(context);
            build(context);
            setEditable(false); //init
        }
    
        public TextBoxOnDemand(Context context, AttributeSet attrs)
        {
            super(context, attrs);
            build(context);
            init(context, attrs);
            setEditable(false); //init
        }
    
        public String getPrefillData()
        {
            return prefillData;
        }
    
        public String getTag()
        {
            return tag;
        }
    
        public String getText()
        {
            Log.d(LOGTAG, "getText() returning '" + ourData + "'");
            return ourData;
        }
    
        public boolean hasPrefillData()
        {
            return prefillData.isEmpty();
        }
    
        public boolean isEditable()
        {
            Log.d(LOGTAG, "isEditable() returning " + inEditMode);
            return inEditMode;
        }
    
        @Override
        public void onClick(View v)
        {
            Log.d(LOGTAG, "onClick(" + v + ")");
            if (inEditMode)
            {
                if (v.equals(accept))
                {
                    if (editor.getEditableText().length() == 0 || editor.getEditableText().length() > 5)
                        ourData = editor.getEditableText().toString();
    
                    setEditable(false);
                } else if (v.equals(cancel))
                {
                    setEditable(false);
                }
            }
        }
    
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
        {
            //      Log.d(LOGTAG, "onEditorAction(" + v + ", " + actionId + ", " + event + ") fired!");
            Log.d(LOGTAG, "onEditorAction() fired, inputReady = " + inputReady);
            if (editor.getEditableText().length() > 0 && editor.getEditableText().length() < (prefillData.length() + 2)) return true;   //the user needs to enter something
    
    
            if (inputReady && (event.getKeyCode() == RemoteKeys.ENTER.keycode() || event.getKeyCode() == KeyEvent.KEYCODE_ENTER))   //always is
            {
                if (editor.getEditableText().length() > prefillData.length() || editor.getEditableText().length() == 0)
                    ourData = editor.getEditableText().toString();
    
                setEditable(false);
                return false;
            }
    
            if ((editor.getEditableText().toString().compareToIgnoreCase(ourData) == 0 || editor.getEditableText().toString()
                    .compareToIgnoreCase(prefillData) == 0)
                    && !inputReady) //means we didn't just keep on holding enter
                return true;
            else
                inputReady = true;
    
            return true;
        }
    
        @Override
        public void onFocusChange(View v, boolean hasFocus)
        {
            Log.d(LOGTAG, "onFocusChange(" + v + ", " + hasFocus + ")\tinEditMode = " + inEditMode);
            if (inEditMode)
            {
                if (hasFocus && (v.equals(topGuard) || v.equals(btmGuard)))
                {
                    setEditable(false);
                    requestFocus();
                }
    
                if (hasFocus && (v.equals(editor) || v.equals(accept) || v.equals(cancel)))
                {
                    //do nothing, you should be able to browse freely here
                    if (ourData.isEmpty() && editor.getEditableText().length() < prefillData.length())
                    {
                        Log.d(LOGTAG, "adding prefill, before = " + editor.getEditableText());
                        editor.setText("");
                        editor.append(prefillData);
                        Log.d(LOGTAG, "now is = " + editor.getEditableText());
                    }
                }
            } else
            {
                String text = (ourData.isEmpty()) ? hint : ourData;
                ColorStateList color;
                if (hintColor != null && ourData.isEmpty())
                    color = hintColor;
                else
                    color = textColor;
                face.setTextColor(color);
                if (hasFocus)
                {
                    SpannableString ss = new SpannableString(text);
                    ss.setSpan(new UnderlineSpan(), 0, text.length(), 0);
                    face.setText(ss);
                } else
                    face.setText(text);
            }
        }
    
        @Override
        public boolean onHover(View v, MotionEvent event)
        {
            //      Log.d(LOGTAG, "onHover()");
            String text = (ourData.isEmpty()) ? hint : ourData;
            ColorStateList color;
            if (hintColor != null && ourData.isEmpty())
                color = hintColor;
            else
                color = textColor;
            face.setTextColor(color);
            switch (event.getAction())
            {
                case MotionEvent.ACTION_HOVER_ENTER:
                    SpannableString ss = new SpannableString(text);
                    ss.setSpan(new UnderlineSpan(), 0, text.length(), 0);
                    face.setText(ss);
                    break;
                case MotionEvent.ACTION_HOVER_EXIT:
                    face.setText(text);
                    break;
            }
            return true;
        }
    
        @Override
        public boolean onLongClick(View v)
        {
            Log.d(LOGTAG, "onLongClick()\tinEditMode = " + inEditMode);
            if (!inEditMode) //implies that getDisplayedChild() == 0, meaning the textview
            {
                setEditable(true);
                return true;
            } else
                return false;
        }
    
        public void setEditable(boolean value)
        {
            Log.d(LOGTAG, "setEditable(" + value + ")");
            inEditMode = value;
            if (inEditMode)
            {
                //display the editorLayout
                face.setOnLongClickListener(null);
                face.setOnHoverListener(null);
                face.setOnFocusChangeListener(null);    //because of GC.
                face.setOnClickListener(null);
                face.setVisibility(View.GONE);
                setDisplayedChild(1);
                editorLayout.setVisibility(View.VISIBLE);
                editor.setOnFocusChangeListener(this);
                editor.setOnEditorActionListener(this);
                cancel.setOnClickListener(this);
                accept.setOnClickListener(this);
                accept.setOnFocusChangeListener(this);
                cancel.setOnFocusChangeListener(this);
            } else
            {
                editor.setOnFocusChangeListener(null);
                editor.setOnEditorActionListener(null);
                cancel.setOnClickListener(null);
                accept.setOnClickListener(null);
                accept.setOnFocusChangeListener(null);
                cancel.setOnFocusChangeListener(null);
                editorLayout.setVisibility(View.GONE);
                setDisplayedChild(0);
                face.setVisibility(View.VISIBLE);
                face.setOnLongClickListener(this);
                face.setOnHoverListener(this);
                face.setOnFocusChangeListener(this);
                face.setOnClickListener(this);
                face.setFocusable(true);
                face.setFocusableInTouchMode(true);
            }
            updateViews();
        }
    
        @Override
        public void setNextFocusDownId(int nextFocusDownId)
        {
            super.setNextFocusDownId(nextFocusDownId);
            face.setNextFocusDownId(nextFocusDownId);
            //      editor.setNextFocusDownId(nextFocusDownId);
            accept.setNextFocusDownId(nextFocusDownId);
            cancel.setNextFocusDownId(nextFocusDownId);
        }
    
        @Override
        public void setNextFocusForwardId(int nextFocusForwardId)
        {
            super.setNextFocusForwardId(nextFocusForwardId);
            face.setNextFocusForwardId(nextFocusForwardId);
            editor.setNextFocusForwardId(nextFocusForwardId);
        }
    
        @Override
        public void setNextFocusLeftId(int nextFocusLeftId)
        {
            super.setNextFocusLeftId(nextFocusLeftId);
            face.setNextFocusLeftId(nextFocusLeftId);
            editor.setNextFocusLeftId(nextFocusLeftId);
        }
    
        @Override
        public void setNextFocusRightId(int nextFocusRightId)
        {
            super.setNextFocusRightId(nextFocusRightId);
            face.setNextFocusRightId(nextFocusRightId);
            cancel.setNextFocusRightId(nextFocusRightId);
        }
    
        @Override
        public void setNextFocusUpId(int nextFocusUpId)
        {
            super.setNextFocusUpId(nextFocusUpId);
            face.setNextFocusUpId(nextFocusUpId);
            //      editor.setNextFocusUpId(nextFocusUpId);
            accept.setNextFocusUpId(nextFocusUpId);
            cancel.setNextFocusUpId(nextFocusUpId);
        }
    
        public void setPrefillData(String prefillData)
        {
            this.prefillData = new String(prefillData);
        }
    
        public String setTag()
        {
            return tag;
        }
    
        public void setText(String text)
        {
            Log.d(LOGTAG, "setText(" + text + ")");
            ourData = text;
            updateViews();
        }
    
        private void build(Context context)
        {
            Log.d(LOGTAG, "build()");
            addView(View.inflate(context, R.layout.textboxondemand, null));
            setFocusable(true);
            setFocusableInTouchMode(true);
            setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
            setOnFocusChangeListener(this);
            setOnLongClickListener(this);
    
            face = (TextView) findViewById(R.id.TBOD_textview);
            editorLayout = (RelativeLayout) findViewById(R.id.TBOD_layout);
            editor = (EditText) findViewById(R.id.TBOD_edittext);
            accept = (ImageButton) findViewById(R.id.TBOD_accept);
            cancel = (ImageButton) findViewById(R.id.TBOD_cancel);
            topGuard = (View) findViewById(R.id.TBOD_top);
            btmGuard = (View) findViewById(R.id.TBOD_bottom);
    
            face.setFocusable(true);
            face.setFocusableInTouchMode(true);
    
            face.setOnLongClickListener(this);
            face.setOnHoverListener(this);
            face.setOnFocusChangeListener(this);
            face.setOnClickListener(this);
    
            editor.setOnFocusChangeListener(this);
            editor.setOnEditorActionListener(this);
            editor.setHint(hint);
            editor.setFocusable(true);
            editor.setFocusableInTouchMode(true);
    
            accept.setOnClickListener(this);
            accept.setOnFocusChangeListener(this);
            accept.setFocusable(true);
            cancel.setFocusable(true);
            cancel.setOnFocusChangeListener(this);
            cancel.setOnClickListener(this);
    
            topGuard.setFocusable(true);
            topGuard.setOnFocusChangeListener(this);
            btmGuard.setFocusable(true);
            btmGuard.setOnFocusChangeListener(this);
    
            editor.setNextFocusRightId(R.id.TBOD_accept);
            editor.setNextFocusDownId(R.id.TBOD_bottom);
            editor.setNextFocusUpId(R.id.TBOD_top);
    
            accept.setNextFocusLeftId(R.id.TBOD_edittext);
            accept.setNextFocusRightId(R.id.TBOD_cancel);
            cancel.setNextFocusLeftId(R.id.TBOD_accept);
        }
    
        private void init(Context context, AttributeSet attrs)
        {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextBoxOnDemand);
            //Use a
            Log.d(LOGTAG, "init()");
            if (a == null) Log.d(LOGTAG, "Did you include 'xmlns:app=\"http://schemas.android.com/apk/res-auto\"' in your root layout?");
    
            final int N = a.getIndexCount();
            for (int i = 0; i < N; ++i)
            {
                int attr = a.getIndex(i);
                switch (attr)
                {
                    case R.styleable.TextBoxOnDemand_android_hint:
                        hint = new String(a.getString(attr));
                        editor.setHint(a.getString(attr));
                        break;
                    case R.styleable.TextBoxOnDemand_android_text:
                        ourData = new String(a.getString(attr));
                        break;
                    case R.styleable.TextBoxOnDemand_android_inputType:
                        int inputType = a.getInt(attr, -1);
                        if (inputType != -1) editor.setInputType(inputType);
                        break;
                    case R.styleable.TextBoxOnDemand_android_textColor:
                        textColor = a.getColorStateList(attr);
                        face.setTextColor(textColor);
                        break;
                    case R.styleable.TextBoxOnDemand_android_linksClickable:
                        face.setLinksClickable(a.getBoolean(attr, true));
                        break;
                    case R.styleable.TextBoxOnDemand_android_textColorHint:
                        hintColor = a.getColorStateList(attr);
                        break;
                    case R.styleable.TextBoxOnDemand_android_autoLink:
                        autoLinkMask = a.getInt(attr, 0);
                        face.setAutoLinkMask(autoLinkMask);
                        break;
    
                    default:
                        Log.d(LOGTAG, "Skipping attribute " + attr);
                }
            }
    
            //Don't forget this
            a.recycle();
        }
    
        private void updateViews()
        {
            Log.d(LOGTAG, "updateViews()");
            //      if (getDisplayedChild() == 0)   //first child - textview
            if (!inEditMode)    //first child - textview
            {
                if (ourData.isEmpty())
                {
                    if (hintColor != null) face.setTextColor(hintColor);
                    face.setText(hint);
                } else
                {
                    face.setTextColor(textColor);
                    face.setText(ourData);
                }
                face.setFocusable(true);
                face.setFocusableInTouchMode(true);
                face.setAutoLinkMask(autoLinkMask);
            } else
            {   //second child - edittext
                editor.setFocusable(true);
                editor.setFocusableInTouchMode(true);
                if (ourData.startsWith(prefillData) || ourData.length() >= prefillData.length())
                    editor.setText("");
                else
                    editor.setText(prefillData);
    
                editor.append(ourData);
                inputReady = false;
    
                editor.requestFocus();
            }
        }
    
        public void setAutoLinkMask(LinkifyEnum linkifyEnumConstant)
        {
            switch (linkifyEnumConstant)
            {
                case ALL:
                    autoLinkMask = Linkify.ALL;
                    break;
                case EMAIL_ADDRESSES:
                    autoLinkMask = Linkify.EMAIL_ADDRESSES;
                    break;
                case MAP_ADDRESSES:
                    autoLinkMask = Linkify.MAP_ADDRESSES;
                    break;
                case PHONE_NUMBERS:
                    autoLinkMask = Linkify.PHONE_NUMBERS;
                    break;
                case WEB_URLS:
                    autoLinkMask = Linkify.WEB_URLS;
                    break;
    
                case NONE:
                default:
                    autoLinkMask = 0;
                    break;
            }
            //set it now
            face.setAutoLinkMask(autoLinkMask);
        }
    
        public enum LinkifyEnum
        {
            ALL, EMAIL_ADDRESSES, MAP_ADDRESSES, PHONE_NUMBERS, WEB_URLS, NONE
        };
    
    }
    

    I’m still working out some focus-related issues but this works as intended. When I use onFocuslistener 1, you can’t focus from one TextBox to the other; when the textbox itself is focusable, I can focus from one to the other just fine, but I cannot inter-focus thru children and thus can’t focus on the edittext to type.

    the XML file:

        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
    
        <TextView
            android:id="@+id/TBOD_textview"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:autoLink="email"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:linksClickable="true"
            android:textAppearance="?android:attr/textAppearanceMedium" />
    
        <RelativeLayout
            android:id="@+id/TBOD_layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
    
            <EditText
                android:id="@+id/TBOD_edittext"
                android:layout_width="300dp"
                android:layout_height="30dp"
                android:layout_below="@+id/TBOD_textview"
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:imeOptions="actionDone"
                android:inputType="none"
                android:maxLines="1"
                android:padding="2dp"
                android:singleLine="true"
                android:textColor="@android:color/black"
                android:textSize="14dp" />
    
            <ImageButton
                android:id="@+id/TBOD_accept"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignTop="@+id/TBOD_edittext"
                android:layout_marginLeft="15dp"
                android:layout_toRightOf="@+id/TBOD_edittext"
                android:background="@drawable/button_accept_selector" />
    
            <ImageButton
                android:id="@+id/TBOD_cancel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignTop="@+id/TBOD_edittext"
                android:layout_marginLeft="5dp"
                android:layout_toRightOf="@+id/TBOD_accept"
                android:background="@drawable/button_cancel_selector" />
    
            <View
                android:id="@+id/TBOD_top"
                android:layout_width="fill_parent"
                android:layout_height="0dp"
                android:layout_alignParentTop="true"
                android:background="@android:color/transparent" />
    
            <View
                android:id="@+id/TBOD_bottom"
                android:layout_width="fill_parent"
                android:layout_height="0dp"
                android:layout_alignParentBottom="true"
                android:background="@android:color/transparent" />
        </RelativeLayout>
    
    </RelativeLayout>
    

    and finally, the attrs.xml file:

     <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <declare-styleable name="TextBoxOnDemand">
            <attr name="android:text" />
            <attr name="android:inputType" />
            <attr name="android:hint" />
            <attr name="android:textColor" />
            <attr name="android:textColorHint" />
            <attr name="android:linksClickable" />
            <attr name="android:autoLink" />
        </declare-styleable>
    
    </resources>
    

    This is how I used it in my main xml (after including the required namespace add):

     <com.shark.widget.TextBoxOnDemand
        android:id="@+id/profile_email2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/profile_skypename"
        android:layout_below="@+id/profile_email_placeholder"
        android:hint="@string/add_email"
        android:inputType="textEmailAddress"
        android:textColor="@android:color/white"
        android:textColorHint="@color/skype_blue" />
    

    EDIT: I’ve debugged the focus issues. It turns out that giving focus to children is difficult unless you call

    setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
    

    Which kinda remedies the issue but still doesn’t solve it. After some while of playing around with the onFocusChange() listener still trying to get the perfect behaviour, I threw in the towel and put in added two focus guards. I realized I cannot track the loss of focus only on my container (due to it never receiving focus) but I might as well track the idea of wanting to move away from the edit field… So i went the dirty route and added two invisible bar-like views to sandwitch the edittext in between. Once they got the focus, I could hide the component and ensure they transition properly.

    And there it is, now it works as it should. Thanks to all who participated.

    EDIT3: final polished version, i dumped the custom tags because they simply don’t work reliably enough. Lesson to be learned: if there is an android tag for something, don’t bother cloning it.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
For some reason, after submitting a string like this Jack’s Spindle from a text
I have a text area in my form which accepts all possible characters from
I have a reasonable size flat file database of text documents mostly saved in
I would like my Web page http://www.gmarks.org/math_in_e-mail.txt on my Apache 2.2.14 server to display
I have two tables with like below codes: Table: Accounts id | username |
I have a bunch of posts stored in text files formatted in yaml/textile (from
I have a .ini file as follows: [playlist] numberofentries=2 File1=http://87.230.82.17:80 Title1=(#1 - 365/1400) Example
I would like to count the length of a string with PHP. The string
link Im having trouble converting the html entites into html characters, (&# 8217;) i

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.