I want an underline below OPTING like below, but when i create this will the help of customview, underline appears just below opting but i want some space between text and line like image
I had created a Custom view, in which a word will searched in a string if that is found, then that corresponding text will be underlined but the only thing i want is to give some space between underline and text,
My class is as follows,
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 is as follows,
<declare-styleable name="UnderLine" >
<attr name="underlineWidthh" format="dimension" />
<attr name="underlineColorr" format="color" />
<attr name="underlineTextt" format="string" />
</declare-styleable>
Sample layout as follows,
<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"/>
I am a beginner with customview, and i had created this with the help of some answers on stackoverflow. Please don't suggest any other way to do this.
Anyhelp will be greatly appreciated.
I had developed my own view, as follows,
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);
}
}
and my attars.xml are as follows,
<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>