stack Learner
stack Learner

Reputation: 1348

EditText giving error : TextView does not support text selection. Selection cancelled

I have RecyclerView.The element at position is 0 is header for EditText ,then all other elements are images.On long pressing on EditText it gives option paste.This works fine. But when I scroll the recycler view to the bottom and again come to top and long press it will not show the paste option and gives error . On Scrolling to the bottom and again coming to top passes call to onBindViewHolder.

TextView: TextView does not support text selection. Selection cancelled.

public class Someclass extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements View.OnClickListener {


    private static final int TYPE_EDIT = 0;
    private static final int TYPE_IMAGE = 1;
    List<String> msomelist = new ArrayList<String>();

    public void someMethod(List<String> somelist) {

        msomelist.clear();
        msomelist.addAll(somelist);
        notifyDataSetChanged();

    }




    public Someclass(Activity activity, List<String> somelist) {
        this.activity = activity;
        this.msomelist.clear();
        this.msomelist.addAll(somelist);
        mContext = activity;
    }

    @Override
    public int getItemViewType(int position) {

        if (position == 0)
            return TYPE_EDIT;

        return TYPE_IMAGE;
    }

    @Override
    public void onClick(View view) {
        int postition = (int) view.getTag();
        msomelist.remove(postition);
        notifyDataSetChanged();

    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
       ImageView img;

        public ViewHolder(View itemView) {
            super(itemView);

            img = (ImageView) itemView.findViewById(R.id.image);
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_IMAGE) {
            View view = LayoutInflater.from(mContext)
                    .inflate(somelayout, false);
            ViewHolder holder = new ViewHolder(view);
            return holder;
        } else {
            View view = LayoutInflater.from(mContext)
                    .inflate(someotherlayout, false);


            return new OtherHolder(view);
        }
    }

    class OtherHolder extends RecyclerView.ViewHolder {
        EditText editText;

        public OtherHolder(View itemView) {
            super(itemView);
            editText = (EditText) itemView.findViewById(R.id.ediItext);
            editText.requestFocus();
        }
    }

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {

        if (holder instanceof ViewHolder) {
            some function.....
        } else if (holder instanceof OtherHolder) {
            some function
        }
    }
}

Upvotes: 10

Views: 4801

Answers (3)

Lucca
Lucca

Reputation: 91

Long click on EditText will call Editor.performLongClick() to show selection popup window.

Before getInsertionController().show();

it will check mInsertionControllerEnabled,when you use setText(),TextView will call Editor.prepareCursorControllers() to reset mInsertionControllerEnabled like this:

boolean windowSupportsHandles = false;

ViewGroup.LayoutParams params = mTextView.getRootView().getLayoutParams();
if (params instanceof WindowManager.LayoutParams) {
    WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
    windowSupportsHandles = windowParams.type < WindowManager.LayoutParams.FIRST_SUB_WINDOW
            || windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW;
}

boolean enabled = windowSupportsHandles && mTextView.getLayout() != null;
mInsertionControllerEnabled = enabled && isCursorVisible();

as you see,rootView must be window type or mInsertionControllerEnabled will be false.

But when you setText() at onBindViewHolder(), the EditText is not attachToWindow yet,so we should setEnable() after EditText attachToWindow to force Editor reset mInsertionControllerEnabled value.Then selection will work now.

Upvotes: 4

Lisa Wray
Lisa Wray

Reputation: 2272

This is a known bug in the Android platform. I didn't believe it at first, but the code @user2246055 posted is an effective workaround!

I preferred to add this in my Adapter instead of subclassing TextView:

        @Override
        public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
            super.onViewAttachedToWindow(holder);

            // Bug workaround for losing text selection ability, see:
            // https://code.google.com/p/android/issues/detail?id=208169
            holder.textView.setEnabled(false);
            holder.textView.setEnabled(true);
        }

Upvotes: 24

Lucca
Lucca

Reputation: 91

Using following MyEditText.java can resolve your problem:

public class MyEditText extends EditText {
private boolean mEnabled; // is this edittext enabled

public MyEditText(Context context) {
    super(context);
}

public MyEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public MyEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    try {
        if (!mEnabled) return;
        super.setEnabled(false);
        super.setEnabled(mEnabled);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void setEnabled(boolean enabled) {
    this.mEnabled = enabled;
    super.setEnabled(enabled);
}}

Upvotes: 5

Related Questions