-
-
Save karanatwal/78085a546a309209a40892a595b4a476 to your computer and use it in GitHub Desktop.
import android.content.Context; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.Paint; | |
import android.graphics.Path; | |
import android.text.Layout; | |
import android.util.AttributeSet; | |
import android.view.KeyEvent; | |
/** | |
* Created by Karandeep Atwal on 04/01/18. | |
+919646874950 | |
Chandigarh, India | |
karanatwal00@gmail.com | |
*/ | |
public class InstaEditext extends android.support.v7.widget.AppCompatEditText { | |
Paint paint ; | |
Path path = new Path(); | |
int CORNER = 36; | |
int OFFSET = CORNER/2; | |
int SIDE_OFFSET = 15; | |
private onKeyBoardDown onKeyBoardDown; | |
private int bgColor = Color.parseColor("#FC812B"); | |
private float textSize = 60f; | |
public InstaEditext(Context context) { | |
this(context,null); | |
} | |
public InstaEditext(Context context, AttributeSet attrs) { | |
this(context, attrs,0); | |
} | |
public InstaEditext(Context context, AttributeSet attrs, int defStyleAttr) { | |
super(context, attrs, defStyleAttr); | |
paint = getPaint(); | |
} | |
@Override | |
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { | |
super.onTextChanged(text, start, lengthBefore, lengthAfter); | |
if (path!=null)path.reset(); | |
} | |
@Override | |
public boolean onKeyPreIme(int keyCode, KeyEvent event) { | |
if (keyCode == KeyEvent.KEYCODE_BACK) { | |
if (onKeyBoardDown!=null){ | |
onKeyBoardDown.onBackPress(); | |
} | |
} | |
return false; | |
} | |
public void setOnKeyboardDownListener(onKeyBoardDown onKeyboardDown){ | |
this.onKeyBoardDown=onKeyboardDown; | |
} | |
public void setSideOffset(boolean sideOffsetNeeded) { | |
if (sideOffsetNeeded){ | |
SIDE_OFFSET=15; | |
}else { | |
SIDE_OFFSET=0; | |
} | |
} | |
public interface onKeyBoardDown{ | |
void onBackPress(); | |
} | |
public void changeBgColor(int color){ | |
bgColor = color; | |
if (paint!=null)paint.setColor(color); | |
invalidate(); | |
} | |
public void setTextSize(float textSize){ | |
this.textSize = textSize; | |
} | |
public float getTextSize(){ | |
return textSize; | |
} | |
@Override | |
protected void onDraw(Canvas canvas) { | |
Layout layout = getLayout(); | |
paint.setTextSize(textSize); | |
paint.setColor(bgColor); | |
paint.setStyle(Paint.Style.FILL); | |
for (int i = 0; i < layout.getLineCount() ; i++) { | |
drawPath(i,canvas,layout); | |
} | |
super.onDraw(canvas); | |
} | |
public void updateTextIn(int dur){ | |
new android.os.Handler().postDelayed(new Runnable() { | |
@Override | |
public void run() { | |
setText(getText().toString()); | |
setSelection(getText().toString().length()); | |
} | |
},dur); | |
} | |
public void updateTextImmediate(){ | |
setText(getText().toString()); | |
setSelection(getText().toString().length()); | |
} | |
public void drawPath(int current, Canvas canvas, Layout layout) { | |
int left = (int) layout.getLineLeft(current) -SIDE_OFFSET; | |
int top = layout.getLineTop(current) ; | |
int right = (int) layout.getLineRight(current) +SIDE_OFFSET; | |
int bottom = layout.getLineBottom(current); | |
if (right-left<=1+(SIDE_OFFSET*2))return; | |
/* | |
//only one line | |
if (current == 3 && layout.getLineCount() == 1) { | |
canvas.drawRoundRect(rectF, 18, 18, paint); | |
} | |
//more than one line | |
else | |
*/ | |
if (current >= 0) { | |
//start top left | |
path.moveTo(left+ OFFSET , top); | |
//top right - offset | |
path.lineTo(right - OFFSET, top); | |
//top right curve to bottom | |
path.arcTo(right - CORNER, top, right, top + CORNER, -90, 90, false); | |
//top right to bottom after curve | |
path.lineTo(right, bottom - OFFSET); | |
//last rect | |
if (current+1 == layout.getLineCount()) { | |
// bottom right curve inner | |
path.arcTo(right - CORNER, bottom - CORNER, right, bottom, 0, 90, false); | |
//bottom base line | |
path.lineTo(left + OFFSET, bottom); | |
//bottom left arc going toward top left | |
path.arcTo(left, bottom - CORNER, left+CORNER, bottom, 90, 90, false); | |
//bottom left to top left after arc | |
path.lineTo(left , top + OFFSET); | |
//last arc to complete | |
path.arcTo(left, top, left+CORNER, top+CORNER, 180, 90, false); | |
// path.close(); | |
} | |
//check next rects are bigger ,shorter or same | |
else { | |
if (nextRectIsBig(layout,current)){ | |
drawNextBigRect(layout,current); | |
} | |
else if (nextRectIsSmall(layout,current)){ | |
drawNextSmallRect(layout,current); | |
} | |
//both rect are same | |
else{ | |
drawNextSameRect(layout,current); | |
} | |
} | |
canvas.drawPath(path, paint); | |
} | |
} | |
private void drawNextSmallRect(Layout layout, int current) { | |
int next = current+1; | |
int left = (int) layout.getLineLeft(current)-SIDE_OFFSET ; | |
int top = layout.getLineTop(current) ; | |
int right = (int) layout.getLineRight(current)+SIDE_OFFSET ; | |
int bottom = layout.getLineBottom(current); | |
int next_left = (int) layout.getLineLeft(next) -SIDE_OFFSET ; | |
int next_top = layout.getLineTop(next) ; | |
int next_right = (int) layout.getLineRight(next)+SIDE_OFFSET ; | |
int next_bottom = layout.getLineBottom(next); | |
// here is arc from big rect to small rect going down to left | |
if (right-next_right<CORNER/2){ | |
path.arcTo(right - (CORNER/2f), next_top - (CORNER/2f), right, next_top, 0, 90, false); | |
}else { | |
path.arcTo(right - CORNER, next_top - CORNER, right, next_top, 0, 90, false); | |
} | |
// now going towards right end of next rect | |
path.lineTo(next_right+ OFFSET, next_top); | |
if (next_right-next_left>1+(SIDE_OFFSET*2)){ | |
//inner right curve second rect to bottom | |
if (right-next_right<CORNER/2){ | |
path.arcTo(next_right , next_top, next_right+ (CORNER/2), next_top + (CORNER/2), 270, -90, false); | |
}else { | |
path.arcTo(next_right , next_top, next_right+CORNER, next_top + CORNER, 270, -90, false); | |
} | |
//top right to bottom after curve | |
path.lineTo(next_right, next_bottom - OFFSET); | |
//bottom right curve inner | |
path.arcTo(next_right - CORNER, next_bottom - CORNER, next_right, next_bottom, 0, 90, false); | |
//bottom base line | |
path.lineTo(next_left + OFFSET, next_bottom); | |
//bottom left arc going toward top left | |
path.arcTo(next_left, next_bottom - CORNER, next_left+CORNER, next_bottom, 90, 90, false); | |
//bottom left to top left after arc | |
path.lineTo(next_left , next_top - OFFSET); | |
}else { | |
//bottom left arc going toward top left | |
path.arcTo(left, bottom - CORNER, left+CORNER, bottom, 90, 90, false); | |
//bottom left to top left after arc | |
// path.lineTo(left , top + OFFSET); | |
//last arc to complete | |
// path.arcTo(left, top, left+CORNER, top+CORNER, 180, 90, false); | |
} | |
//now check if previous was smaller or same | |
//here we will pass param 'next' index and check it with prev('current') | |
// if (prevRectIsBig(layout,next)){ | |
// drawPrevBigRect(layout,next); | |
// } | |
// else | |
if (prevRectIsBig(layout,next)){ | |
drawPrevBigRect(layout,next); | |
} | |
//both rect are same | |
else{ | |
drawPrevSameRect(layout,next); | |
} | |
//now it reached to (left,top) of next rect | |
// path.arcTo(next_left, next_top, next_left+CORNER, next_top+CORNER, 180, 90, false); | |
} | |
private void drawNextSameRect(Layout layout, int current) { | |
int next = current+1; | |
int left = (int) layout.getLineLeft(current)-SIDE_OFFSET ; | |
int top = layout.getLineTop(current) ; | |
int right = (int) layout.getLineRight(current) +SIDE_OFFSET; | |
int bottom = layout.getLineBottom(current); | |
int next_left = (int) layout.getLineLeft(next) -SIDE_OFFSET; | |
int next_top = layout.getLineTop(next) ; | |
int next_right = (int) layout.getLineRight(next) +SIDE_OFFSET; | |
int next_bottom = layout.getLineBottom(next); | |
// here is arc from small rect to big rect going down to right | |
// path.arcTo(right , next_top - CORNER, right+CORNER, next_top, 180, -90, false); | |
// now going towards right end of next rect | |
// path.lineTo(next_right- CORNER, next_top); | |
//top right curve to bottom | |
// path.arcTo(next_right - CORNER, next_top, next_right, next_bottom + CORNER, -90, 90, false); | |
//top right to bottom after curve | |
// path.lineTo(next_right, bottom - OFFSET); | |
if (next_right-next_left>1+(SIDE_OFFSET*2)){ | |
//bottom right curve inner | |
path.arcTo(next_right - CORNER, next_bottom - CORNER, next_right, next_bottom, 0, 90, false); | |
//bottom base line | |
path.lineTo(next_left + OFFSET, next_bottom); | |
//bottom left arc going toward top left | |
path.arcTo(next_left, next_bottom - CORNER, next_left+CORNER, next_bottom, 90, 90, false); | |
//bottom left to top left after arc | |
path.lineTo(next_left , next_top - OFFSET); | |
}else { | |
// bottom right curve inner | |
path.arcTo(right - CORNER, bottom - CORNER, right, bottom, 0, 90, false); | |
//bottom base line | |
path.lineTo(left + OFFSET, bottom); | |
//bottom left arc going toward top left | |
path.arcTo(left, bottom - CORNER, left+CORNER, bottom, 90, 90, false); | |
//bottom left to top left after arc | |
path.lineTo(left , top + OFFSET); | |
} | |
//now check if previous was smaller or same | |
//here we will pass param 'next' index and check it with prev('current') | |
if (prevRectIsBig(layout,next)){ | |
drawPrevBigRect(layout,next); | |
} | |
else if (prevRectIsSmall(layout,next)){ | |
drawPrevSmallRect(layout,next); | |
} | |
//both rect are same | |
else{ | |
drawPrevSameRect(layout,next); | |
} | |
//now it reached to (left,top) of next rect | |
// path.arcTo(next_left, next_top, next_left+CORNER, next_top+CORNER, 180, 90, false); | |
} | |
/* | |
this is for below case | |
| | |
| | |
|=____ | |
*/ | |
private void drawNextBigRect(Layout layout, int current) { | |
int next = current+1; | |
int left = (int) layout.getLineLeft(current) -SIDE_OFFSET; | |
int top = layout.getLineTop(current) ; | |
int right = (int) layout.getLineRight(current)+SIDE_OFFSET ; | |
int bottom = layout.getLineBottom(current); | |
int next_left = (int) layout.getLineLeft(next)-SIDE_OFFSET ; | |
int next_top = layout.getLineTop(next) ; | |
int next_right = (int) layout.getLineRight(next) +SIDE_OFFSET; | |
int next_bottom = layout.getLineBottom(next); | |
// here is arc from small rect to big rect going down to right | |
if (next_right-right<CORNER/2){ | |
path.arcTo(right , next_top - (CORNER/2f), right+(CORNER/2f), next_top, 180, -90, false); | |
}else { | |
path.arcTo(right , next_top - CORNER, right+CORNER, next_top, 180, -90, false); | |
} | |
// now going towards right end of next rect | |
path.lineTo(next_right- OFFSET, next_top); | |
//top right curve to bottom | |
if (next_right-right<CORNER/2){ | |
path.arcTo(next_right - (CORNER/2f), next_top, next_right, next_bottom + (CORNER/2f), -90, 90, false); | |
}else { | |
path.arcTo(next_right - CORNER, next_top, next_right, next_bottom + CORNER, -90, 90, false); | |
} | |
//top right to bottom after curve | |
path.lineTo(next_right, next_bottom - OFFSET); | |
//bottom right curve inner | |
path.arcTo(next_right - CORNER, next_bottom - CORNER, next_right, next_bottom, 0, 90, false); | |
//bottom base line | |
path.lineTo(next_left + OFFSET, next_bottom); | |
//bottom left arc going toward top left | |
path.arcTo(next_left, next_bottom - CORNER, next_left+CORNER, next_bottom, 90, 90, false); | |
//bottom left to top left after arc | |
path.lineTo(next_left , next_top - OFFSET); | |
//now check if previous was smaller or same | |
//here we will pass param 'next' index and check it with prev('current') | |
// if (prevRectIsBig(layout,next)){ | |
// drawPrevBigRect(layout,next); | |
// } | |
// else | |
if (prevRectIsSmall(layout,next)){ | |
drawPrevSmallRect(layout,next); | |
} | |
//both rect are same | |
else{ | |
drawPrevSameRect(layout,next); | |
} | |
//now it reached to (left,top) of next rect | |
// path.arcTo(next_left, next_top, next_left+CORNER, next_top+CORNER, 180, 90, false); | |
} | |
private void drawPrevSameRect(Layout layout, int current) { | |
int prev = current-1; | |
int left = (int) layout.getLineLeft(current)-SIDE_OFFSET ; | |
int top = layout.getLineTop(current) ; | |
int right = (int) layout.getLineRight(current)+SIDE_OFFSET ; | |
int bottom = layout.getLineBottom(current); | |
int prev_left = (int) layout.getLineLeft(prev)-SIDE_OFFSET ; | |
int prev_top = layout.getLineTop(prev) ; | |
int prev_right = (int) layout.getLineRight(prev)+SIDE_OFFSET ; | |
int prev_bottom = layout.getLineBottom(prev); | |
//below rect (left,top) curve | |
// path.arcTo(left, top, left+CORNER, top+CORNER, 180, 90, false); | |
//bottom rect (left,top) to upper rect (left,bottom) | |
// path.lineTo(prev_left - OFFSET , prev_bottom ); | |
//bottom left inner arc of upper(prev) rect going toward (left,top) | |
//path.arcTo(prev_left - CORNER, prev_bottom - CORNER, prev_left, prev_bottom, 90, -90, false); | |
//(left,bottom) to (left,top) after arc of prev rect | |
// path.lineTo(prev_left , prev_top + OFFSET); | |
//last arc to complete | |
path.arcTo(prev_left, prev_top, prev_left+CORNER, prev_top+CORNER, 180, 90, false); | |
} | |
private void drawPrevSmallRect(Layout layout, int current) { | |
int prev = current-1; | |
int left = (int) layout.getLineLeft(current) -SIDE_OFFSET; | |
int top = layout.getLineTop(current) ; | |
int right = (int) layout.getLineRight(current)+SIDE_OFFSET ; | |
int bottom = layout.getLineBottom(current); | |
int prev_left = (int) layout.getLineLeft(prev) -SIDE_OFFSET; | |
int prev_top = layout.getLineTop(prev) ; | |
int prev_right = (int) layout.getLineRight(prev)+SIDE_OFFSET ; | |
int prev_bottom = layout.getLineBottom(prev); | |
//below rect (left,top) curve | |
if (prev_left-left<CORNER/2){ | |
path.arcTo(left, top, left+(CORNER/2f), top+(CORNER/2f), 180, 90, false); | |
}else { | |
path.arcTo(left, top, left+CORNER, top+CORNER, 180, 90, false); | |
} | |
//bottom rect (left,top) to upper rect (left,bottom) | |
path.lineTo(prev_left - OFFSET , prev_bottom ); | |
//bottom left inner arc of upper(prev) rect going toward (left,top) | |
if (prev_left-left<CORNER/2){ | |
path.arcTo(prev_left - (CORNER/2f), prev_bottom - (CORNER/2f), prev_left, prev_bottom, 90, -90, false); | |
}else { | |
path.arcTo(prev_left - CORNER, prev_bottom - CORNER, prev_left, prev_bottom, 90, -90, false); | |
} | |
//(left,bottom) to (left,top) after arc of prev rect | |
path.lineTo(prev_left , prev_top + OFFSET); | |
//last arc to complete | |
path.arcTo(prev_left, prev_top, prev_left+CORNER, prev_top+CORNER, 180, 90, false); | |
} | |
private void drawPrevBigRect(Layout layout, int current) { | |
int prev = current-1; | |
int left = (int) layout.getLineLeft(current) -SIDE_OFFSET; | |
int top = layout.getLineTop(current) ; | |
int right = (int) layout.getLineRight(current)+SIDE_OFFSET ; | |
int bottom = layout.getLineBottom(current); | |
int prev_left = (int) layout.getLineLeft(prev) -SIDE_OFFSET; | |
int prev_top = layout.getLineTop(prev) ; | |
int prev_right = (int) layout.getLineRight(prev)+SIDE_OFFSET ; | |
int prev_bottom = layout.getLineBottom(prev); | |
if (right-left>1+(SIDE_OFFSET*2)){ | |
// here is arc from small rect to big rect going top to left | |
if (left-prev_left<CORNER/2){ | |
path.arcTo(left-(CORNER/2) , top, left, top+(CORNER/2), 0, -90, false); | |
}else { | |
path.arcTo(left-CORNER , top, left, top+CORNER, 0, -90, false); | |
} | |
//bottom rect (left,top) to upper rect (left,bottom) | |
path.lineTo(prev_left+ OFFSET , prev_bottom ); | |
//bottom left arc of upper(prev) rect ngoing toward (left,top) | |
if (left-prev_left<CORNER/2){ | |
path.arcTo(prev_left, prev_bottom - (CORNER/2), prev_left+(CORNER/2), prev_bottom, 90, 90, false); | |
}else { | |
path.arcTo(prev_left, prev_bottom - CORNER, prev_left+CORNER, prev_bottom, 90, 90, false); | |
} | |
//bottom left to top left after arc | |
path.lineTo(prev_left , prev_bottom - OFFSET); | |
} | |
//last arc to complete | |
path.arcTo(prev_left, prev_top, prev_left+CORNER, prev_top+CORNER, 180, 90, false); | |
} | |
private boolean prevRectIsSmall(Layout layout, int current) { | |
int prev = current-1; | |
int left = (int) layout.getLineLeft(current) ; | |
int prev_left = (int) layout.getLineLeft(prev) ; | |
return (prev_left -left>= (CORNER/4f)); | |
} | |
private boolean prevRectIsBig(Layout layout, int current) { | |
int prev = current-1; | |
int left = (int) layout.getLineLeft(current) ; | |
int prev_left = (int) layout.getLineLeft(prev) ; | |
return (left - prev_left >= (CORNER/4f)); | |
} | |
private boolean nextRectIsSmall(Layout layout, int current) { | |
int next = current+1; | |
int right = (int) layout.getLineRight(current) ; | |
int next_right = (int) layout.getLineRight(next) ; | |
return (right - next_right >= (CORNER/4f)); | |
} | |
private boolean nextRectIsBig(Layout layout,int current) { | |
int next = current+1; | |
int right = (int) layout.getLineRight(current) ; | |
int next_right = (int) layout.getLineRight(next) ; | |
return (next_right - right >=(CORNER/4f)); | |
} | |
} | |
/* | |
@Override | |
protected void onDraw(Canvas canvas) { | |
Layout layout = getLayout(); | |
paint.setTextSize(100f); | |
paint.setColor(Color.RED); | |
for (int i = 0; i < layout.getLineCount() ; i++) { | |
int left = (int)layout.getLineLeft(i) - PADDING; | |
int top= layout.getLineTop(i) - PADDING; | |
int right = (int)layout.getLineRight(i) + PADDING; | |
int bottom = layout.getLineBottom(i) + PADDING; | |
rect.set(left,top,right,bottom); | |
rectF.set(rect); | |
canvas.drawRoundRect(rectF,18,18,paint); | |
} | |
super.onDraw(canvas); | |
}*/ |
I have checked on Android 9, working flawlessly. Can you elaborate more what is happening and phone model ?
@karanatwal :
Device: Nokia 3 Plus
OS: 9
Step 1: Add InstaEditext
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".features.stickers.TextEditorDialogFragment">
<com.my.InstaEditext
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:minHeight="30dp"
android:textColor="@color/white"
android:hint="@string/input_your_text"
android:gravity="center"
android:textSize="28sp"
app:layout_constraintBottom_toTopOf="@id/footer"
android:background="@android:color/transparent"
/>
....
</androidx.constraintlayout.widget.ConstraintLayout>
Step 2: Run
Step 3: Tap on InstaEditext and the keyboard doesn't show up
One more question: is it work after changing the gravity of EditText?
Thanks
I have Nokia 6.1 Plus OS 9 and it's working fine. I will check later today in sample app. For now you can also try this https://stackoverflow.com/a/49288455/5996106.
I will let you know if got time. For Gravity question I am not sure, I will have to check.
I really love to hear your reply
1.Video: https://drive.google.com/file/d/14qgJzpiN8HcAKAqFfZc62G7HgMNTHz7-/view?usp=sharing
2.Source code demo: https://drive.google.com/file/d/12VDTOm0qCh84Cb3TtSyOjIOTrd-i9k5_/view?usp=sharing
- The BackgroundColorSpan in StackOverflow work well only in gravity = Center.
But When I change the Gravity from Center to Start/End, its really wrong drawing background.
https://gist.github.com/rahul01/8f44d730b6a5a10cc9deecfe95228352
@chihung93 support for alignment
How to add padding on all sides in background?
Well Done @karandeep
Can not show keyboard :((( on Android 9