SagePawan
SagePawan

Reputation: 364

Android edittext cursor not seen despite edittext.isCursorVisible() returning true

In my xml I have already added following attributes.

           <com.project.current.widget.AutoResizeEditText
                    android:id="@+id/edittext_add_text_new"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:focusable="true"
                    android:focusableInTouchMode="true"
                    android:hint="@string/text_sticker_hint"
                    android:inputType="textNoSuggestions|textVisiblePassword|textMultiLine"
                    android:isScrollContainer="false"
                    android:padding="@dimen/dimen_margin_small"
                    android:textColor="@color/black"
                    android:textColorHint="@color/blue_popover"
                    android:textSize="@dimen/text_font_edit_text_default"
                    android:layout_alignParentTop="true"
                    android:layout_centerHorizontal="true"
                    android:background="@drawable/bg_text_sticker"
                    android:layout_toRightOf="@+id/resize_icon_left"
                    android:cursorVisible="true"
                    android:textCursorDrawable="@null"
                    android:textIsSelectable="true" />

I have set Focusable and FocusableOnTouch to true. I also have cursorVisible set to true. And just to make sure the cursor isn't taking white color(the background is whitish), I have set the textCursorDrawable to '@null'

But the cursor still isnt visible in the view. I have a touchListener implemented to the edittext (since I also need to move it around the parent layout). So I have set the keyboard to pop up at ACTION_UP. At that point I when I check

editTextViewNew.isCursorVisible()

It returns true. But the cursor is actually not visible. How do I make it visible and the text within my edittext selectable? (The long press option to 'paste' copied text also doesn't work.)

I am using the following Custom AutoResizeEditText to resize the text within editText as per my need.

public class AutoResizeEditText extends android.support.v7.widget.AppCompatEditText {
private static final int NO_LINE_LIMIT = -1;
private final RectF _availableSpaceRect = new RectF();
private final SparseIntArray _textCachedSizes = new SparseIntArray();
private final SizeTester _sizeTester;
private float _maxTextSize;
private float _spacingMult = 1.0f;
private float _spacingAdd = 0.0f;
private float _minTextSize;
private int _widthLimit;
private int _maxLines;
private boolean _enableSizeCache = true;
private boolean _initiallized = false;
private TextPaint paint;

//set Boolean for disabling auto-resize when user is resizing using controls
public static boolean isUserTyping = false;

//disable autoresizing when user is not typing text
public static void checkIfUserTyping(boolean isActive){
    isUserTyping = isActive;
}

private interface SizeTester {
    /**
     * AutoResizeEditText
     *
     * @param suggestedSize
     *            Size of text to be tested
     * @param availableSpace
     *            available space in which text must fit
     * @return an integer < 0 if after applying {@code suggestedSize} to
     *         text, it takes less space than {@code availableSpace}, > 0
     *         otherwise
     */
    public int onTestSize(int suggestedSize, RectF availableSpace);
}

public AutoResizeEditText(final Context context) {
    this(context, null, 0);
}

public AutoResizeEditText(final Context context, final AttributeSet attrs) {
    this(context, attrs, 0);
}

public AutoResizeEditText(final Context context, final AttributeSet attrs,
                          final int defStyle) {
    super(context, attrs, defStyle);
    // using the minimal recommended font size

    _minTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
            12, getResources().getDisplayMetrics());
    _maxTextSize = getTextSize();
    if (_maxLines == 0)
        // no value was assigned during construction
        _maxLines = NO_LINE_LIMIT;
    // prepare size tester:
    _sizeTester = new SizeTester() {
        final RectF textRect = new RectF();

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        @Override
        public int onTestSize(final int suggestedSize,
                              final RectF availableSPace) {
            paint.setTextSize(suggestedSize);
            final String text = getText().toString();
            final boolean singleline = getMaxLines() == 1;
            if (singleline) {
                textRect.bottom = paint.getFontSpacing();
                textRect.right = paint.measureText(text);
            } else {
                final StaticLayout layout = new StaticLayout(text, paint,
                        _widthLimit, Layout.Alignment.ALIGN_NORMAL, _spacingMult,
                        _spacingAdd, true);
                // return early if we have more lines
                Log.d("NLN", "Current Lines = " + Integer.toString(layout.getLineCount()));
                Log.d("NLN", "Max Lines = " + Integer.toString(getMaxLines()));
                if (getMaxLines() != NO_LINE_LIMIT
                        && layout.getLineCount() > getMaxLines())
                    return 1;
                textRect.bottom = layout.getHeight();
                int maxWidth = -1;
                for (int i = 0; i < layout.getLineCount(); i++)
                    if (maxWidth < layout.getLineWidth(i))
                        maxWidth = (int) layout.getLineWidth(i);
                textRect.right = maxWidth;
            }
            textRect.offsetTo(0, 0);
            if (availableSPace.contains(textRect))
                // may be too small, don't worry we will find the best match
                return -1;
            // else, too big
            return 1;
        }
    };

    setEnabled(true);
    setFocusableInTouchMode(true);
    setFocusable(true);
    setEnableSizeCache(false);
    setMovementMethod(null);
    _initiallized = true;

}

@Override
public void setTypeface(final Typeface tf) {
    if (paint == null)
        paint = new TextPaint(getPaint());
    paint.setTypeface(tf);
    super.setTypeface(tf);
}

@Override
public void setTextSize(final float size) {
    _maxTextSize = size;
    _textCachedSizes.clear();
    adjustTextSize();
}

@Override
public void setMaxLines(final int maxlines) {
    super.setMaxLines(maxlines);
    _maxLines = maxlines;
    reAdjust();
}

@Override
public int getMaxLines() {
    return _maxLines;
}

@Override
public void setSingleLine() {
    super.setSingleLine();
    _maxLines = 1;
    reAdjust();
}

@Override
public void setSingleLine(final boolean singleLine) {
    super.setSingleLine(singleLine);
    if (singleLine)
        _maxLines = 1;
    else
        _maxLines = NO_LINE_LIMIT;
    reAdjust();
}

@Override
public void setLines(final int lines) {
    super.setLines(lines);
    _maxLines = lines;
    reAdjust();
}

@Override
public void setTextSize(final int unit, final float size) {
    final Context c = getContext();
    Resources r;
    if (c == null)
        r = Resources.getSystem();
    else
        r = c.getResources();
    _maxTextSize = TypedValue.applyDimension(unit, size,
            r.getDisplayMetrics());
    _textCachedSizes.clear();
    adjustTextSize();
}


@Override
public void setLineSpacing(final float add, final float mult) {
    super.setLineSpacing(add, mult);
    _spacingMult = mult;
    _spacingAdd = add;
}

/**
 * Set the lower text size limit and invalidate the view
 *
 * @param

 */
public void setMinTextSize(final float minTextSize) {
    _minTextSize = minTextSize;
    reAdjust();
}

private void reAdjust() {
    adjustTextSize();
}

private void adjustTextSize() {
    if (!_initiallized)
        return;

    Log.d("IsUserTyping"," "+isUserTyping);
    if(!isUserTyping)
        return;

    final int startSize = (int) _minTextSize;
    /*final int heightLimit = getMeasuredHeight()
            - getCompoundPaddingBottom() - getCompoundPaddingTop();
    _widthLimit = getMeasuredWidth() - getCompoundPaddingLeft()
            - getCompoundPaddingRight();*/

    //User maxWidth and maxHeight the textBox can attain to calculate resize values

    final int heightLimit = getMaxHeight()
            - getCompoundPaddingBottom() - getCompoundPaddingTop();
    _widthLimit = getMaxWidth() - getCompoundPaddingLeft()
            - getCompoundPaddingRight();

    if (_widthLimit <= 0)
        return;
    _availableSpaceRect.right = _widthLimit;
    _availableSpaceRect.bottom = heightLimit;
    super.setTextSize(
            TypedValue.COMPLEX_UNIT_PX,
            efficientTextSizeSearch(startSize, (int) _maxTextSize,
                    _sizeTester, _availableSpaceRect));
}

/**
 * Enables or disables size caching, enabling it will improve performance
 * where you are animating a value inside TextView. This stores the font
 * size against getText().length() Be careful though while enabling it as 0
 * takes more space than 1 on some fonts and so on.
 *
 * @param enable
 *            enable font size caching
 */
public void setEnableSizeCache(final boolean enable) {
    _enableSizeCache = enable;
    _textCachedSizes.clear();
    adjustTextSize();
}

private int efficientTextSizeSearch(final int start, final int end,
                                    final SizeTester sizeTester, final RectF availableSpace) {
    if (!_enableSizeCache)
        return binarySearch(start, end, sizeTester, availableSpace);
    final String text = getText().toString();
    final int key = text == null ? 0 : text.length();
    int size = _textCachedSizes.get(key);
    if (size != 0)
        return size;
    size = binarySearch(start, end, sizeTester, availableSpace);
    _textCachedSizes.put(key, size);
    return size;
}

private int binarySearch(final int start, final int end,
                         final SizeTester sizeTester, final RectF availableSpace) {
    int lastBest = start;
    int lo = start;
    int hi = end - 1;
    int mid = 0;
    while (lo <= hi) {
        mid = lo + hi >>> 1;
        final int midValCmp = sizeTester.onTestSize(mid, availableSpace);
        if (midValCmp < 0) {
            lastBest = lo;
            lo = mid + 1;
        } else if (midValCmp > 0) {
            hi = mid - 1;
            lastBest = hi;
        } else
            return mid;
    }
    // make sure to return last best
    // this is what should always be returned
    return lastBest;
}

@Override
protected void onTextChanged(final CharSequence text, final int start,
                             final int before, final int after) {
    super.onTextChanged(text, start, before, after);
    reAdjust();
}

@Override
protected void onSizeChanged(final int width, final int height,
                             final int oldwidth, final int oldheight) {
    _textCachedSizes.clear();
    super.onSizeChanged(width, height, oldwidth, oldheight);
    if (width != oldwidth || height != oldheight)
        reAdjust();
}

}

I found these details implemented here, which was easy to emulate on my end.

Upvotes: 1

Views: 554

Answers (2)

Prakhar Gupta
Prakhar Gupta

Reputation: 131

Please remove the line that has setMovementMethod from null, this will appear the cursor to change the cursor drawable you can use textCursorDrawable

Upvotes: 0

Mekuanent Getachew
Mekuanent Getachew

Reputation: 22

android:textIsSelectable="true"

Set it to false if you wanna see your cursor

you don't have to set textCursorDrawable to @null because the color only depends on your choice of accent color

Upvotes: 1

Related Questions