Creating right arrow inside circle - android

I would like to draw an image as below using android drawable something as below:
I could do the arrow but when I add circle, the image gets distorted.
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape>
<solid android:color="#android:color/transparent"/>
<size android:width="2dp" android:height="50dp"/>
</shape>
</item>
<item android:bottom="20dp">
<rotate
android:fromDegrees="45"
android:toDegrees="45">
<shape android:shape="rectangle">
<solid android:color="#F0AD4E"/>
<corners
android:radius="0dp"
android:bottomRightRadius="0dp"
android:bottomLeftRadius="0dp"/>
</shape>
</rotate>
</item>
<item android:top="20dp">
<rotate
android:fromDegrees="-45"
android:toDegrees="45">
<shape android:shape="rectangle">
<solid android:color="#F0AD4E"/>
<corners
android:radius="0dp"
android:topRightRadius="0dp"
android:topLeftRadius="0dp"/>
</shape>
</rotate>
</item>
Can anyone help me to complete the picture.
Thanks.

Don't use drawables for this, use a custom view and canvas.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by Bojan on 17.5.2015.
*/
public class CircleRightArrow extends View {
private int circleColor = 0xFF505070;
private int arrowColor = 0xFF505070;
private int measuredSize;
private int strokeWidth;
private Paint mCirclePiant, mArrowPaint;
public CircleRightArrow(Context context) {
super(context);
init(context, null, 0);
}
public CircleRightArrow(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public CircleRightArrow(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attributeSet, int defStyle) {
mCirclePiant = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePiant.setColor(circleColor);
mCirclePiant.setStyle(Paint.Style.STROKE);
mArrowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mArrowPaint.setColor(arrowColor);
mArrowPaint.setStyle(Paint.Style.STROKE);
mArrowPaint.setStrokeCap(Paint.Cap.ROUND);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
measuredSize = Math.min(measuredHeight, measuredWidth);
strokeWidth = Math.round(measuredSize * 0.05f);
mCirclePiant.setStrokeWidth(strokeWidth);
mArrowPaint.setStrokeWidth(strokeWidth);
// Make a square
setMeasuredDimension(measuredSize + strokeWidth, measuredSize + strokeWidth);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (measuredSize <= 0) {
// Not much we can draw, can we
return;
}
float center = (measuredSize + strokeWidth) * 0.5f;
canvas.drawCircle(center, center, measuredSize * 0.5f, mCirclePiant);
canvas.drawLine(center + 0.2f * measuredSize, center, center - 0.1f * measuredSize, center + 0.2f * measuredSize, mArrowPaint);
canvas.drawLine(center + 0.2f * measuredSize, center, center - 0.1f * measuredSize, center - 0.2f * measuredSize, mArrowPaint);
}
}
Result of 50x50dp at 1920x1080p

Following Bojan's answer, I edited the view to redraw based on the touch events and added the OnClickListener part. Feel free to suggest any improvements.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by noorul.ahmed on 5/18/2015.
*/
public class CircleRightArrow extends View {
private int viewColor;
private int backgroundColor;
private int normalColor = 0xFFF0AD4E;
private int normalBackground = 0xFFFFFFFF;
private int touchBackground = 0xFFEC971F;
private int touchColor = 0xFFFFFFFF;
private int disabledBackground = 0xFFFFFFFF;
private int disabledColor = 0xFFCECECE;
private int measuredSize;
private int strokeWidth;
private boolean touched = false;
private float startX, startY, endX, endY;
private OnClickListener listener;
private Paint mCirclePiant, mArrowPaint;
public CircleRightArrow(Context context) {
super(context);
init(context, null, 0);
setInitialColor();
}
public CircleRightArrow(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
setInitialColor();
}
public CircleRightArrow(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
setInitialColor();
}
private void init(Context context, AttributeSet attributeSet, int defStyle) {
mCirclePiant = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePiant.setColor(viewColor);
mCirclePiant.setStyle(Paint.Style.STROKE);
mArrowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mArrowPaint.setColor(viewColor);
mArrowPaint.setStyle(Paint.Style.STROKE);
mArrowPaint.setStrokeCap(Paint.Cap.ROUND);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
measuredSize = Math.min(measuredHeight, measuredWidth);
strokeWidth = Math.round(measuredSize * 0.025f);
mCirclePiant.setStrokeWidth(strokeWidth);
mArrowPaint.setStrokeWidth(strokeWidth);
// Make a square
setMeasuredDimension(measuredSize + strokeWidth, measuredSize + strokeWidth);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (measuredSize <= 0) {
// Not much we can draw, can we
return;
}
float center = (measuredSize + strokeWidth) * 0.5f;
canvas.drawCircle(center, center, measuredSize * 0.5f, mCirclePiant);
canvas.drawLine(center + 0.2f * measuredSize, center, center - 0.1f * measuredSize, center + 0.2f * measuredSize, mArrowPaint);
canvas.drawLine(center + 0.2f * measuredSize, center, center - 0.1f * measuredSize, center - 0.2f * measuredSize, mArrowPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = super.onTouchEvent(event);
switch (event.getAction()){
case MotionEvent.ACTION_DOWN :
touched = true;
startX = event.getX();
startY = event.getY();
togglePaintColor(event);
postInvalidate();
return true;
case MotionEvent.ACTION_UP :
endX = event.getX();
endY = event.getY();
togglePaintColor(event);
postInvalidate();
float diffX = Math.abs(startX - endX);
float diffY = Math.abs(startY - endY);
if (diffX <= 5 && diffY <= 5 && touched ) {
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,1));
}
return true;
default:
return false;
}
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getAction() == KeyEvent.ACTION_UP) {
touched = false;
if(listener != null) listener.onClick(this);
}
return super.dispatchKeyEvent(event);
}
public void setListener(OnClickListener listener) {
this.listener = listener;
}
public void setInitialColor(){
if (isClickable()){
viewColor = normalColor;
backgroundColor = normalBackground;
}
else {
viewColor = disabledColor;
backgroundColor = disabledBackground;
this.listener = null;
}
mCirclePiant.setColor(viewColor);
mCirclePiant.setStyle(Paint.Style.STROKE);
mArrowPaint.setColor(viewColor);
}
#Override
public void setClickable(boolean isClickable){
super.setClickable(isClickable);
if (isClickable){
viewColor = normalColor;
backgroundColor = normalBackground;
}
else {
viewColor = disabledColor;
backgroundColor = disabledBackground;
this.listener = null;
}
mCirclePiant.setColor(viewColor);
mCirclePiant.setStyle(Paint.Style.STROKE);
mArrowPaint.setColor(viewColor);
postInvalidate();
}
private void togglePaintColor(MotionEvent event) {
if (isClickable()) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
viewColor = touchColor;
backgroundColor = touchBackground;
mCirclePiant.setColor(backgroundColor);
mCirclePiant.setStyle(Paint.Style.FILL);
mArrowPaint.setColor(viewColor);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
viewColor = normalColor;
backgroundColor = normalBackground;
mCirclePiant.setColor(viewColor);
mCirclePiant.setStyle(Paint.Style.STROKE);
mArrowPaint.setColor(viewColor);
}
}
}
}
The three button states are:
Normal State
Pressed State
Disabled state

Related

Removing the Background border from a ProgressBar

I am trying to achieve Pie Progress without border
without center circle and it's progress .. So I tried multiple ways to achieve it in ProgressBar
Both my approach shows a border around the PIE
I simply want to remove the border Or I want the below circle to be of exact size.
1st Approach
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#color/grey_lightest"/>
</shape>
</item>
<item>
<shape
android:innerRadiusRatio="100"
android:shape="ring"
android:thicknessRatio="2.5"
android:useLevel="true">
<gradient
android:centerColor="#color/orange_above_avg"
android:endColor="#color/orange_above_avg"
android:startColor="#color/orange_above_avg"
android:type="sweep"
android:useLevel="false" />
</shape>
</item>
</layer-list>
2nd Approach
I created seperate background and progressDrawable but still same result..
It's not exact solution to your problem but you can use customview to achieve it .
Here is a reference which I picked from some project (so an't give proper credit)
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import in.eightfolds.soundvision.R;
public class CustomProgress extends View {
private static final String TAG = "CustomProgress";
private float maxWidth, maxHight;
private PointF centerPoint;
private float radius;
float progressSize = 0f;
private Path path;
private RectF oval;
private Paint mcirclePaint;
private Paint mTextPaint;
private int progress = 0;
private Paint mBackCirclePaint;
private int paintStrokeWidth=40;
public CustomProgress(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CustomProgress(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomProgress(Context context) {
super(context);
init();
}
private void init() {
centerPoint = new PointF();
path = new Path();
mcirclePaint = new Paint();
mcirclePaint.setColor(Color.RED);
mcirclePaint.setStrokeWidth(paintStrokeWidth);
// paint.setDither(true);
mcirclePaint.setAntiAlias(true);
mcirclePaint.setStyle(Paint.Style.STROKE);
mBackCirclePaint = new Paint();
mBackCirclePaint.setColor(Color.DKGRAY);
mBackCirclePaint.setStrokeWidth(paintStrokeWidth);
// paint.setDither(true);
mBackCirclePaint.setAntiAlias(true);
mBackCirclePaint.setStyle(Paint.Style.STROKE);
oval = new RectF();
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.SUBPIXEL_TEXT_FLAG);
// mTextPaint.setColor(getResources().getColor(
// android.R.color.holo_blue_dark));
mTextPaint.setColor(Color.RED);
mTextPaint.setStrokeWidth(1);
mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextSize(60);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(centerPoint.x, centerPoint.y, radius,
mBackCirclePaint);
// mcirclePaint.setColor(Color.RED);
canvas.drawArc(oval, -90, progressSize, false, mcirclePaint);
// paint.setTextSize(20);
// canvas.drawCircle(centerPoint.x, centerPoint.y, 2, mcirclePaint);
if (progress > 0) {
canvas.drawText(progress + "%", centerPoint.x, centerPoint.y
+ mTextPaint.descent(), mTextPaint);
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
Log.v(TAG, "" + changed);
if (getMeasuredWidth() < getMeasuredHeight()) {
maxWidth = getMeasuredWidth();
maxHight = getMeasuredHeight();
centerPoint.x = maxWidth / 2;
centerPoint.y = maxHight / 2;
} else {
maxWidth = getMeasuredHeight();
maxHight = getMeasuredWidth();
centerPoint.x = maxHight / 2;
centerPoint.y = maxWidth / 2;
}
setUp();
}
private void setUp() {
if (maxWidth > maxHight) {
radius = maxHight / 4;
} else {
radius = maxWidth / 4;
}
path.addCircle(maxWidth / 2,
maxHight / 2, radius,
Path.Direction.CW);
oval.set(centerPoint.x - radius,
centerPoint.y - radius,
centerPoint.x + radius,
centerPoint.y + radius);
}
public void upDateProgress(int progress) {
mcirclePaint.setColor(getResources().getColor(R.color.themeColor));
mTextPaint.setColor(getResources().getColor(R.color.themeColor));
this.progress = progress;
float i = 360f / 100f;
progressSize = (float) (i * progress);
Log.d(TAG, progress + "<----progress---->" + progressSize);
invalidate();
}
public int getProgress() {
return progress;
}
}
Use this in layout file and use upDateProgress to change progress .
Change widths and colors to your own . If you want text, then place a textview in center to this customview

give space between text and underline with customview android

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>

Draw arc like progressbar with touch options for Android

i have got some problem with my own progressbar.
When i click on dot they catch me.
I try do it something like that:
here is code:
package test.pionas.myapplication;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class PioArcCircle extends View {
private static final String TAG = PioArc.class.getSimpleName();
private static int INVALID_PROGRESS_VALUE = -1;
private float mThickness = 50f; // thickness of line
private int mRotate = 0; // rotate circle in degrees
private Paint mCircleBgPaint;
private int mCircleEndAngle = 270; // end arc
private int mCircleStartAngle = 0; // start arc
private int mCircleSweepAngle = 0; // actualy arc
private RectF mCircleOuterBounds;
private int mCircleBgColor = Color.RED; // color of circle
private Paint mCirclePaint; // progressbar
private int mCircleColor = Color.BLUE; // color of progressbar
private Paint mEraserPaint;
private RectF mCircleInnerBounds;
private int mEraserColor = Color.YELLOW; // background color of circle
private boolean mEraserInnerBackground = false; // eraser background inner circle
private Bitmap mBitmap;
private Canvas mCanvas;
private float mMinValue = 0; // min progressbar value
private float mMaxValue = 100; // max progressbar value
private float mProgressSweep = 0; // start progressbar value
private boolean mEnabled; // draw dot
private float mDotSize; // dot size
private Paint mCircleThumbPaint;
private float mTranslateX; // center circle (axis X)
private float mTranslateY; // center circle (axis Y)
private boolean mTouchInside; // touch inside circle can change position on progress
private float mTouchIgnoreRadius;
private int mArcRadius;
private int mThumbXPos;
private int mThumbYPos;
private OnPioArcCircleChangeListener mOnPioArcCircleChangeListener;
public PioArcCircle(Context context) {
super(context);
initDefaultValue(context, 0, null);
}
public PioArcCircle(Context context, AttributeSet attrs) {
super(context, attrs);
initDefaultValue(context, 0, attrs);
}
public PioArcCircle(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initDefaultValue(context, defStyleAttr, attrs);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PioArcCircle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initDefaultValue(context, defStyleAttr, attrs);
}
private void initDefaultValue(Context context, int defStyleAttr, AttributeSet attrs) {
if (attrs != null) {
TypedArray typedArray = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PioArcCircle,
defStyleAttr, 0);
this.mThickness = typedArray.getFloat(R.styleable.PioArcCircle_thickness1, this.mThickness);
this.mRotate = typedArray.getInt(R.styleable.PioArcCircle_rotate, this.mRotate);
this.mCircleSweepAngle = typedArray.getInt(R.styleable.PioArcCircle_circleSweepAngle, this.mCircleSweepAngle);
this.mCircleEndAngle = typedArray.getInt(R.styleable.PioArcCircle_circleEndAngle, this.mCircleEndAngle);
this.mCircleStartAngle = typedArray.getInt(R.styleable.PioArcCircle_circleStartAngle, this.mCircleStartAngle);
this.mCircleBgColor = typedArray.getInt(R.styleable.PioArcCircle_circleBgColor, this.mCircleBgColor);
this.mEraserColor = typedArray.getInt(R.styleable.PioArcCircle_eraserColor, this.mEraserColor);
this.mEraserInnerBackground = typedArray.getBoolean(R.styleable.PioArcCircle_eraserInnerBackground, this.mEraserInnerBackground);
this.mMinValue = typedArray.getFloat(R.styleable.PioArcCircle_minValue, this.mMinValue);
this.mMaxValue = typedArray.getFloat(R.styleable.PioArcCircle_maxValue, this.mMaxValue);
this.mEnabled = typedArray.getBoolean(R.styleable.PioArcCircle_enable, this.mEnabled);
this.mDotSize = typedArray.getFloat(R.styleable.PioArcCircle_dotSize, this.mDotSize);
this.mTouchInside = typedArray.getBoolean(R.styleable.PioArcCircle_touchInside, this.mTouchInside);
this.mCircleColor = typedArray.getInt(R.styleable.PioArcCircle_circleBgColor, this.mCircleColor);
}
mCircleBgPaint = new Paint();
mCircleBgPaint.setAntiAlias(true);
mCircleBgPaint.setColor(mCircleBgColor);
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(mCircleColor);
mEraserPaint = new Paint();
mEraserPaint.setAntiAlias(true);
mEraserPaint.setColor(mEraserColor);
if (mEraserInnerBackground) {
mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
mCircleThumbPaint = new Paint();
mCircleThumbPaint.setAntiAlias(true);
mCircleThumbPaint.setColor(Color.CYAN);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBitmap.eraseColor(Color.TRANSPARENT);
mCanvas = new Canvas(mBitmap);
}
super.onSizeChanged(w, h, oldw, oldh);
updateBounds();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int min = Math.min(widthMeasureSpec, heightMeasureSpec);
this.setMeasuredDimension(parentWidth, parentHeight);
this.setTouchInSide(this.mTouchInside);
super.onMeasure(min, min);
}
#Override
protected void onDraw(Canvas canvas) {
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
mCanvas.drawArc(mCircleOuterBounds, (mCircleStartAngle + mRotate), (mCircleEndAngle - mCircleStartAngle), true, mCircleBgPaint);
if (mCircleSweepAngle - mRotate > 0f) {
mCanvas.drawArc(mCircleOuterBounds, (mCircleStartAngle + mRotate), (mCircleSweepAngle - mRotate), true, mCirclePaint);
}
mCanvas.drawOval(mCircleInnerBounds, mEraserPaint);
if (mEnabled) {
mThumbXPos = (int) (mTranslateX + (mArcRadius * Math.cos(Math.toRadians((double) this.mCircleSweepAngle))));
mThumbYPos = (int) (mTranslateY + (mArcRadius * Math.sin(Math.toRadians((double) this.mCircleSweepAngle))));
mCanvas.drawCircle(mThumbXPos, mThumbYPos, mThickness, mCircleThumbPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, null);
}
private void updateBounds() {
if (this.getPaddingLeft() < (mThickness / 2)) {
this.setPadding((int) (mThickness / 2), this.getPaddingTop(), this.getPaddingRight(), this.getPaddingBottom());
}
mCircleOuterBounds = new RectF(0 + this.getPaddingLeft(), 0 + this.getPaddingLeft(), getWidth() - this.getPaddingLeft(), getHeight() - this.getPaddingLeft());
mCircleInnerBounds = new RectF(
mCircleOuterBounds.left + mThickness,
mCircleOuterBounds.top + mThickness,
mCircleOuterBounds.right - mThickness,
mCircleOuterBounds.bottom - mThickness);
this.mTranslateX = mCircleOuterBounds.centerX();
this.mTranslateY = mCircleOuterBounds.centerY();
this.mArcRadius = (int) (mTranslateX - this.getPaddingLeft() - (mThickness / 2));
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.mEnabled) {
this.getParent().requestDisallowInterceptTouchEvent(true);
switch (event.getAction()) {
case 0:
this.onStartTrackingTouch();
this.updateOnTouch(event);
break;
case 1:
this.onStopTrackingTouch();
this.setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
case 2:
this.updateOnTouch(event);
break;
case 3:
this.onStopTrackingTouch();
this.setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
}
return true;
} else {
return false;
}
}
public void setTouchInSide(boolean isEnabled) {
int thumbHalfheight = (int) (mThickness / 2);
int thumbHalfWidth = (int) (mThickness / 2);
this.mTouchInside = isEnabled;
if (this.mTouchInside) {
this.mTouchIgnoreRadius = (float) this.mArcRadius / 4.0F;
} else {
this.mTouchIgnoreRadius = (float) (this.mArcRadius - Math.min(thumbHalfWidth, thumbHalfheight));
}
}
private void updateOnTouch(MotionEvent event) {
boolean ignoreTouch = this.ignoreTouch(event.getX(), event.getY());
if (!ignoreTouch) {
this.setPressed(true);
this.mProgressSweep = (float) this.getTouchDegrees(event.getX(), event.getY());
this.updateProgress((int) this.mProgressSweep);
}
}
private double getTouchDegrees(float xPos, float yPos) {
double angle = (int) (Math.atan2(yPos - mTranslateY, xPos - mTranslateX) * 180 / Math.PI);
if (angle < 0) {
angle += 360;
}
float x = xPos - this.mTranslateX;
float y = yPos - this.mTranslateY;
angle = Math.toDegrees(Math.atan2((double) y, (double) x) + 1.5707963267948966D - Math.toRadians((double) this.mRotate));
if (angle < 0.0D) {
angle += 360.0D;
}
angle -= (double) this.mCircleStartAngle;
return angle;
}
private boolean ignoreTouch(float xPos, float yPos) {
boolean ignore = false;
double touchRadius = Math.sqrt(Math.pow(xPos - this.mTranslateX, 2) + Math.pow(yPos - this.mTranslateY, 2));
if (this.mTouchInside && touchRadius > this.mArcRadius) {
ignore = true;
} else {
if ((touchRadius > (this.mArcRadius + (this.mThickness / 2))) ||
(touchRadius < (this.mArcRadius - (this.mThickness / 2)))) {
ignore = true;
}
}
return ignore;
}
private void onStartTrackingTouch() {
if (this.mOnPioArcCircleChangeListener != null) {
this.mOnPioArcCircleChangeListener.onStartTrackingTouch(this);
}
}
private void onStopTrackingTouch() {
if (this.mOnPioArcCircleChangeListener != null) {
this.mOnPioArcCircleChangeListener.onStopTrackingTouch(this);
}
}
private void updateProgress(int progress) {
if (progress != INVALID_PROGRESS_VALUE) {
if (this.mOnPioArcCircleChangeListener != null) {
this.mOnPioArcCircleChangeListener.onProgressChanged(this);
}
mCircleSweepAngle = progress;
this.invalidate();
}
}
public OnPioArcCircleChangeListener getmOnPioArcCircleChangeListener() {
return mOnPioArcCircleChangeListener;
}
public void setmOnPioArcCircleChangeListener(OnPioArcCircleChangeListener mOnPioArcCircleChangeListener) {
this.mOnPioArcCircleChangeListener = mOnPioArcCircleChangeListener;
}
public interface OnPioArcCircleChangeListener {
void onProgressChanged(PioArcCircle var1);
void onStartTrackingTouch(PioArcCircle var1);
void onStopTrackingTouch(PioArcCircle var1);
}
}
activity_main.xml:
<com.test.myapplication.PioArcCircle
android:layout_width="200dp"
android:layout_height="200dp"
android:padding="#dimen/activity_vertical_margin"
android:progressDrawable="#drawable/circular_progress_bar"
pioarccircle:circleColor="#color/colorAccent"
pioarccircle:enable="true"
pioarccircle:minValue="50.0"
pioarccircle:rotate="135"
pioarccircle:thickness1="100" />
First problem:
How i can create a few colors of progress?
Thanks for help.

Prevent ImageView redraw state after hide keyboard

First, I have a view like this:
When user press some text in edittext, I try to draw some rectangles in ImageView with specific coordinates. The problem is when the soft keyboard is hidden, all draw state of Imageview display wrong coordinates, look like it invalidated the imageview. I wonder is there any way to stop this.
Here is my Custom Drawable Imageview:
public class DrawableImageView extends ImageView {
private Paint ptBlur;
private List<Rect> rects;
private int originWidth;
private int originHeight;
public DrawableImageView(Context context) {
super(context);
initPaint();
}
public DrawableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public DrawableImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initPaint();
}
public void setRects(List<Rect> rects, int originWidth, int originHeight) {
this.originHeight = originHeight;
this.originWidth = originWidth;
this.rects = rects;
invalidate();
}
private void initPaint() {
ptBlur = new Paint();
ptBlur.setColor(Color.YELLOW);
ptBlur.setStyle(Paint.Style.STROKE);
ptBlur.setStrokeWidth(5);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (rects != null) {
int width = getWidth();
int height = getHeight();
for (Rect rect : rects) {
rect.bottom = Math.round(height * rect.bottom / originHeight);
rect.left = Math.round(width * rect.left / originWidth);
rect.right = Math.round(width * rect.right / originWidth);
rect.top = Math.round(height * rect.top / originHeight);
canvas.drawRect(rect, ptBlur);
}
}
}
}
The OnEditorActionListener for EditText:
// get the rectangles and draw
List<Rect> rects = DataUtil.getHighlightRectList(searchText);
drawableImageView.setRects(rects, pageWidth, pageHeight);

Android drawing an animated line

I'm currently working with graphics and paths, and I can successufully display whatever I want.
But instead of drawing a line directly on my SurfaceView, I'd like to draw it progressively in an animation.
What I've done so far is to create a Path and then to use PathMeasure to retrieve the coordinates progressively along the path. Here is basically what I've done so far
PathMeasure pm = new PathMeasure(myPath, false);
float position = 0;
float end = pm.getLength();
float[] coord = {0,0,0,0,0,0,0,0,0};
while (position < end){
Matrix m = new Matrix();
// put the current path position coordinates into the matrix
pm.getMatrix(position, m, PathMeasure.POSITION_MATRIX_FLAG | PathMeasure.TANGENT_MATRIX_FLAG);
// put the matrix data into the coord array (coord[2] = x and coord[5] = y)
m.getValues(coord);
????
position += 1;
}
The question marks is where I'm stuck. I want to draw the path progressively and see it animated on the screen. I couldn't find much info about it on the internet, so any clue would be much appreciated if you have already come across the same situation. The final effect I want to create is like a pencil drawing progressively a text automatically.
Instead of creating a for loop, you can use the ObjectAnimator class to callback to one of your class's methods every time you'd like to draw a bit more of the path.
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.View;
import android.util.Log;
public class PathView extends View
{
Path path;
Paint paint;
float length;
public PathView(Context context)
{
super(context);
}
public PathView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public PathView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
public void init()
{
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
path = new Path();
path.moveTo(50, 50);
path.lineTo(50, 500);
path.lineTo(200, 500);
path.lineTo(200, 300);
path.lineTo(350, 300);
// Measure the path
PathMeasure measure = new PathMeasure(path, false);
length = measure.getLength();
float[] intervals = new float[]{length, length};
ObjectAnimator animator = ObjectAnimator.ofFloat(PathView.this, "phase", 1.0f, 0.0f);
animator.setDuration(3000);
animator.start();
}
//is called by animtor object
public void setPhase(float phase)
{
Log.d("pathview","setPhase called with:" + String.valueOf(phase));
paint.setPathEffect(createPathEffect(length, phase, 0.0f));
invalidate();//will calll onDraw
}
private static PathEffect createPathEffect(float pathLength, float phase, float offset)
{
return new DashPathEffect(new float[] { pathLength, pathLength },
Math.max(phase * pathLength, offset));
}
#Override
public void onDraw(Canvas c)
{
super.onDraw(c);
c.drawPath(path, paint);
}
}
Then, just call init() to begin the animation, like this (or if you'd like it to start as soon as the view is inflated, put the init() call inside the constructors):
PathView path_view = (PathView) root_view.findViewById(R.id.path);
path_view.init();
Also see this question here, and this example, which I've based my code on.
I just have resolve this problem, here what I do:
private float[] mIntervals = { 0f, 0f };
private float drawSpeed = 2f;
private int currentPath = -1;
private PathMeasure mPathMeasure = new PathMeasure();
private ArrayList<Path> mListPath = new ArrayList<Path>(this.pathCount);
#Override
protected void onDraw(Canvas canvas) {
if (mIntervals[1] <= 0f && currentPath < (pathCount - 1)) {
// Set the current path to draw
// getPath(int num) a function to return a path.
Path newPath = this.getPath(mListPath.size());
this.mListPath.add(newPath);
this.mPathMeasure.setPath(newPath, false);
mIntervals[0] = 0;
mIntervals[1] = this.mPathMeasure.getLength();
}
if (mIntervals[1] > 0) {
// draw the previous path
int last = this.mListPath.size();
for (int i = 0; i < last; i++) {
canvas.drawPath(this.mListPath.get(i), mPaint);
}
// partially draw the last path
this.mPaint.setPathEffect(new DashPathEffect(mIntervals, 0f));
canvas.drawPath(this.mListPath.get(last), mPaint);
// Update the path effects values, to draw a little more
// on the path.
mIntervals[0] += drawSpeed;
mIntervals[1] -= drawSpeed;
super.invalidate();
} else {
// The drawing have been done, draw it entirely
for (int i = 0; i < this.mListPath.size(); i++) {
canvas.drawPath(this.mListPath.get(i), mPaint);
}
}
}
This example, is an adaptation of what I've done (to simplify the example). Hope you will understand it. Since I've just made this function working, It lacks of optimizations and things like that.
Hope it will help ;-)
here is an alternative solution that worked for me
package com.sample;
/**
* Created by Sumit
*/
public class PathView extends View {
Paint mPaint;
Path mPath;
int mStrokeColor;
float mStrokeWidth;
float mProgress = 0.0f;
float mLength = 0f;
float mTotal;
public PathView(Context context) {
this(context, null);
init();
}
public PathView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
init();
}
public PathView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mStrokeColor = Color.RED;
mStrokeWidth = 8.0f;
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(mStrokeColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
setPath(new Path());
// setPath2(new Path());
}
public void setPath(Path p) {
mPath = p;
PathMeasure measure = new PathMeasure(mPath, false);
mPathLength = measure.getLength();
}
public void setPath(List<float[][]> list) {
Log.d("Path", "size " + list.size());
Path p = new Path();
p.moveTo(list.get(0)[0][0], list.get(1)[0][1]);
for (int i = 1; i < list.size(); i++) {
p.lineTo(list.get(i)[0][0], list.get(i)[0][1]);
//if (i > 100)
//p.moveTo(list.get(i)[0][0], list.get(i)[0][1]);
}
//p.setFillType(FillType.WINDING);
setPath(p);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mTotal = (mLength - mLength * mProgress);
PathEffect pathEffect = new DashPathEffect(new float[] { mLength, mLength }, mTotal);
Log.d("Path Tag", "length =" + mLength + ", totla=" + mTotal);
mPaint.setPathEffect(pathEffect);
canvas.save();
// canvas.translate(getPaddingLeft(), getPaddingTop());
canvas.drawPath(mPath, mPaint);
canvas.restore();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(widthMeasureSpec);
int measuredWidth, measuredHeight;
if (widthMode == MeasureSpec.AT_MOST)
throw new IllegalStateException("Use MATCH_PARENT");
else
measuredWidth = widthSize;
if (heightMode == MeasureSpec.AT_MOST)
throw new IllegalStateException("Use MATCH_PARENT");
else
measuredHeight = heightSize;
setMeasuredDimension(measuredWidth, measuredHeight);
setPath();
}
void setPath() {
int cX = getWidth() / 2;
int cY = getHeight() / 2;
cY += 50;
cX -= 50;
List<float[][]> list = new ArrayList<float[][]>();
for (int i = 0; i < 50; i++) {
list.add(new float[][] { { cX--, cY++ } });
}
for (int i = 0; i < 100; i++) {
list.add(new float[][] { { cX--, cY-- } });
}
for (int i = 0; i < 100; i++) {
list.add(new float[][] { { cX++, cY-- } });
}
for (int i = 0; i < 200; i++) {
list.add(new float[][] { { cX++, cY++ } });
}
for (int i = 0; i < 100; i++) {
list.add(new float[][] { { cX++, cY-- } });
}
for (int i = 0; i < 100; i++) {
list.add(new float[][] { { cX--, cY-- } });
}
for (int i = 0; i < 100; i++) {
list.add(new float[][] { { cX--, cY++ } });
}
setPath(list);
}
}
and use
final PathView pathView = (PathView) findViewById(R.id.path_view);
pathView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "percentage", 0.0f, 1.0f);
anim.setDuration(2000);
anim.setInterpolator(new LinearInterpolator());
anim.setRepeatCount(Animation.INFINITE);
anim.start();
}
});
You will have to add this view to the layout, setting height to 1 and width to match parent. The line will be animated from left to right. The later line will be placed over the first one.
public class AnimatorLineView extends RelativeLayout {
private View animatorLineView;
private View simpleLineView;
View animatorLine;
private int colorBeforeAnimation;
private int colorAfterAnimation;
private int colorForErrorLine;
public AnimatorLineView(Context context) {
super(context);
init();
startAnimation();
}
public AnimatorLineView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
initAttributes(context, attrs);
setColors();
startAnimation();
}
public AnimatorLineView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
initAttributes(context, attrs);
setColors();
startAnimation();
}
private void setColors() {
simpleLineView.setBackgroundColor(colorBeforeAnimation);
animatorLine.setBackgroundColor(colorAfterAnimation);
}
public void init() {
animatorLineView = inflate(getContext(), R.layout.ainimator_line_view, this);
animatorLine = findViewById(R.id.simple_line);
simpleLineView = findViewById(R.id.animator_line);
}
public void setColor(int color) {
animatorLine.setBackgroundColor(color);
}
public void startAnimation() {
animatorLine.setVisibility(View.VISIBLE);
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.enter_animation_underline);
animatorLine.startAnimation(animation);
}
public void showErrorLine(){
animatorLine.setBackgroundColor(colorForErrorLine);
animatorLine.setVisibility(View.VISIBLE);
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.enter_animation_underline);
animatorLine.startAnimation(animation);
}
public void hideErrorLine(){
animatorLine.setBackgroundColor(colorAfterAnimation);
animatorLine.setVisibility(View.VISIBLE);
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.enter_animation_underline);
animatorLine.startAnimation(animation);
}
private void initAttributes(Context context, AttributeSet attributeSet) {
TypedArray attr = getTypedArray(context, attributeSet, R.styleable.ProgressButton);
if (attr == null) {
return;
}
try {
colorBeforeAnimation = attr.getColor(R.styleable.AnimatorLineView_al_color_after_animation,ContextCompat.getColor(getContext(), R.color.animation_line_text_color));
colorAfterAnimation = attr.getColor(R.styleable.ProgressButton_pb_text_color, ContextCompat.getColor(getContext(), R.color.black_color));
colorForErrorLine = attr.getColor(R.styleable.ProgressButton_pb_text_color, ContextCompat.getColor(getContext(), R.color.error_msgs_text_color));
} finally {
attr.recycle();
}
}
protected TypedArray getTypedArray(Context context, AttributeSet attributeSet, int[] attr) {
return context.obtainStyledAttributes(attributeSet, attr, 0, 0);
}
public void resetColor(){
animatorLine.setBackgroundColor(colorAfterAnimation);
animatorLine.setVisibility(View.GONE);
}
}
<animator_line_view>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<View
android:id="#+id/simple_line"
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:background="#E0E0E0" />
<View
android:id="#+id/animator_line"
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:background="#000000"
android:visibility="gone" />
</FrameLayout>
<enter_animation_underline>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:fromXDelta="-100%" android:toXDelta="0%"
android:fromYDelta="0%" android:toYDelta="0%"
android:duration="#integer/animator_line_duration" />
</set>
---- styles------
<style name="animator_line">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="al_color_before_animation">#E0E0E0</item>
<item name="al_color_after_animation">#0000000</item>
<item name="al_error_line_color">#FF3352</item>
</style>
<declare-styleable name="AnimatorLineView">
<attr name="al_color_before_animation" format="color" />
<attr name="al_color_after_animation" format="color" />
<attr name="al_error_line_color" format="color" />
</declare-styleable>
-------- to be include in the xml
<com.careem.acma.widget.AnimatorLineView
android:id="#+id/animator_line"
style="#style/animator_line" />

Categories

Resources