在文本和带有 customview android 的下划线之间给出 space

give space between text and underline with customview android

我想在 OPTING 下方添加下划线,如下所示,但是当我创建它时,将借助自定义视图,下划线出现在选项下方,但我想要在文本和线条之间添加一些 space,例如图像

我创建了一个自定义视图,如果找到一个词,将在其中搜索字符串,然后相应的文本将被加下划线,但我唯一想要的是在下划线之间添加一些 space和文字,

我的class如下,

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.AppCompatTextView;
import android.text.Layout;
import android.util.AttributeSet;
import android.view.Display;
import android.view.WindowManager;
import android.widget.TextView;


public class UnderLine  extends AppCompatTextView {

private Rect mRect;
private Paint mPaint;
private int mColor;
private float density;
private float mStrokeWidth;
private String stringSeach;

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

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

public UnderLine(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs, defStyleAttr);
}

private void init(Context context, AttributeSet attributeSet, int defStyle) {

    density = context.getResources().getDisplayMetrics().density;

    TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.UnderLine, defStyle, 0);
    mColor = typedArray.getColor(R.styleable.UnderLine_underlineColorr, 0xFFFF0000);
    stringSeach = typedArray.getString(R.styleable.UnderLine_underlineTextt);
    mStrokeWidth = typedArray.getDimension(R.styleable.UnderLine_underlineWidthh, density * 2);
    typedArray.recycle();

    mRect = new Rect();
    mPaint = new Paint();
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setColor(mColor); //line mColor
    mPaint.setStrokeWidth(mStrokeWidth);
}

public int getUnderLineColor() {
    return mColor;
}

public void setUnderLineColor(int mColor) {
    this.mColor = mColor;
    invalidate();
}

public float getUnderlineWidth() {
    return mStrokeWidth;
}

public void setUnderlineWidth(float mStrokeWidth) {
    this.mStrokeWidth = mStrokeWidth;
    invalidate();
}

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    setMeasuredDimension( getMeasuredWidth(), getMeasuredHeight()+110);
}

@Override
protected void onDraw(Canvas canvas) {
    TextView parentTextView = this;
    Rect parentTextViewRect = new Rect();

    String targetWord = stringSeach.toLowerCase();
    int startOffsetOfClickedText = this.getText().toString().toLowerCase().indexOf(targetWord);
    int endOffsetOfClickedText = startOffsetOfClickedText + targetWord.length();

    // Initialize values for the computing of clickedText position
    Layout textViewLayout = parentTextView.getLayout();

    double startXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal((int)startOffsetOfClickedText);
    double endXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal((int)endOffsetOfClickedText);

    // Get the rectangle of the clicked text
    int currentLineStartOffset = textViewLayout.getLineForOffset((int)startOffsetOfClickedText);
    int currentLineEndOffset = textViewLayout.getLineForOffset((int)endOffsetOfClickedText);
    boolean keywordIsInMultiLine = currentLineStartOffset != currentLineEndOffset;
    textViewLayout.getLineBounds(currentLineStartOffset, parentTextViewRect);

    // Update the rectangle position to his real position on screen
    int[] parentTextViewLocation = {0,0};
    parentTextView.getLocationOnScreen(parentTextViewLocation);

    double parentTextViewTopAndBottomOffset = (
            //parentTextViewLocation[1] -
            parentTextView.getScrollY() +
                    parentTextView.getCompoundPaddingTop()
    );

    parentTextViewRect.top += parentTextViewTopAndBottomOffset;
    parentTextViewRect.bottom += parentTextViewTopAndBottomOffset;

    // In the case of multi line text, we have to choose what rectangle take
    if (keywordIsInMultiLine){

        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();

        int screenHeight = display.getHeight();
        int dyTop = parentTextViewRect.top;
        int dyBottom = screenHeight - parentTextViewRect.bottom;
        boolean onTop = dyTop > dyBottom;

        if (onTop){
            endXCoordinatesOfClickedText = textViewLayout.getLineRight(currentLineStartOffset);
        }
        else{
            parentTextViewRect = new Rect();
            textViewLayout.getLineBounds(currentLineEndOffset, parentTextViewRect);
            parentTextViewRect.top += parentTextViewTopAndBottomOffset;
            parentTextViewRect.bottom += parentTextViewTopAndBottomOffset;
            startXCoordinatesOfClickedText = textViewLayout.getLineLeft(currentLineEndOffset);
        }

    }

    parentTextViewRect.left += (
            parentTextViewLocation[0] +
                    startXCoordinatesOfClickedText +
                    parentTextView.getCompoundPaddingLeft() -
                    parentTextView.getScrollX()
    );
    parentTextViewRect.right = (int) (
            parentTextViewRect.left +
                    endXCoordinatesOfClickedText -
                    startXCoordinatesOfClickedText
    );


   canvas.drawLine(parentTextViewRect.left,parentTextViewRect.bottom+mStrokeWidth, parentTextViewRect.right,
            parentTextViewRect.bottom+mStrokeWidth, mPaint);
    super.onDraw(canvas);
}

}

attrs.xml如下,

  <declare-styleable name="UnderLine" >
    <attr name="underlineWidthh" format="dimension" />
    <attr name="underlineColorr" format="color" />
    <attr name="underlineTextt" format="string" />
</declare-styleable>

示例布局如下,

    <UnderLine
    style="@style/textView"
    android:gravity="top|center"
    app:underlineColorr="@color/signup_bottom_darkWhite"
    app:underlineWidthh="2dp"
    app:underlineTextt="OPTING"
    android:text="ON FREE PARKING + DISCOUNTED RATES \n BY OPTING IN"/>

我是 customview 的初学者,我是在 Whosebug 上的一些答案的帮助下创建的。请不要建议任何其他方式来做到这一点。

任何帮助将不胜感激。

我提出了自己的看法,如下,

package com.example.reprator.underlinetextview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.AppCompatTextView;
import android.text.Layout;
import android.util.AttributeSet;

public class UnderlinedTextView extends AppCompatTextView {

private Rect mRect;
private Paint mPaint;
private int mColor;
private float mStrokeWidth;
private float mMarginTop;
private boolean isAllSelected;
private int lineNumber;
private int selectTextEachLine;

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

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

public UnderlinedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs, defStyleAttr);
}

private void init(Context context, AttributeSet attributeSet, int defStyle) {

    float density = context.getResources().getDisplayMetrics().density;

    TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.UnderlinedTextView, defStyle, 0);
    mColor = typedArray.getColor(R.styleable.UnderlinedTextView_underlineColor, 0xFFFF0000);
    mStrokeWidth = typedArray.getDimension(R.styleable.UnderlinedTextView_underlineWidth, density * 2);
    mMarginTop = typedArray.getDimension(R.styleable.UnderlinedTextView_underlineMarginTop, density * 2);
    isAllSelected = typedArray.getBoolean(R.styleable.UnderlinedTextView_underlineIsAll, false);
    lineNumber = typedArray.getInteger(R.styleable.UnderlinedTextView_underlineNoLine, 1);
    selectTextEachLine = typedArray.getInteger(R.styleable.UnderlinedTextView_underlineTextEachLine, 3);
    typedArray.recycle();

    mRect = new Rect();
    mPaint = new Paint();
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setColor(mColor); //line mColor
    mPaint.setStrokeWidth(mStrokeWidth);
}

public int getUnderLineColor() {
    return mColor;
}

public void setUnderLineColor(int mColor) {
    this.mColor = mColor;
    invalidate();
}

public float getUnderlineWidth() {
    return mStrokeWidth;
}

public void setUnderlineWidth(float mStrokeWidth) {
    this.mStrokeWidth = mStrokeWidth;
    invalidate();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int h = (int) (getMeasuredHeight() + mMarginTop);
    setMeasuredDimension(widthMeasureSpec, h);
}

@Override
protected void onDraw(Canvas canvas) {

    final Layout layout = getLayout();
    float x_start, x_stop;
    int firstCharInLine, lastCharInLine;

    int limit = isAllSelected ? getLineCount() : lineNumber;
    for (int i = 0; i < limit; i++) {
        int baseline = getLineBounds(i, mRect);
        firstCharInLine = layout.getLineStart(i);
        lastCharInLine = layout.getLineEnd(i);

        int textHighlight = isAllSelected ? lastCharInLine - 1 : (firstCharInLine + selectTextEachLine);
        x_start = layout.getPrimaryHorizontal(firstCharInLine);
        x_stop = layout.getPrimaryHorizontal(textHighlight);

        float y = baseline + mStrokeWidth + mMarginTop;
        canvas.drawLine(x_start, y, x_stop, y, mPaint);
    }

    super.onDraw(canvas);
}

}

和我的attars.xml如下,

 <declare-styleable name="UnderlinedTextView">
    <attr name="underlineWidth" format="dimension" />
    <attr name="underlineMarginTop" format="dimension" />
    <attr name="underlineColor" format="color" />
    <attr name="underlineText" format="string" />
    <attr name="underlineIsAll" format="boolean" />
    <attr name="underlineNoLine" format="integer" />
    <attr name="underlineTextEachLine" format="integer" />
</declare-styleable>