I am creating a circle with custom view or canvas. The circle gets created with border as well but the problem is that the right and bottom part of circle gets truncated. I get the following output with below mentioned code,
My custom view class for creating the above mentioned class is as follows,
package cl.tk.ui.iBAPView;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import cl.tkp.R;
public class RoundedView extends View {
private Paint paint,mPaintBorder;
private int color;
float borderWidth;
private String text = null;
private boolean checked = false;
private Drawable drawable;
public RoundedView(Context context) {
super(context);
bootstrap(context, null,0,0);
}
public RoundedView(Context context, AttributeSet attrs) {
super(context, attrs);
bootstrap(context, attrs, 0,0);
}
public RoundedView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
bootstrap(context, attrs, defStyleAttr, 0);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RoundedView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
bootstrap(context, attrs, defStyleAttr, defStyleRes);
}
private void bootstrap(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundedView, defStyleAttr, defStyleRes);
text = a.getString(R.styleable.RoundedView_android_text);
color = a.getColor(R.styleable.RoundedView_bgColor, Color.GRAY);
drawable=a.getDrawable(R.styleable.RoundedView_drawableCenter);
checked=a.getBoolean(R.styleable.RoundedView_checked,false);
borderWidth= a.getDimension(R.styleable.RoundedView_rborderWidth,context.getResources().getDimension(R.dimen._minus2sdp));
paint = new Paint(Paint.DITHER_FLAG);
mPaintBorder = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintBorder.setColor(a.getColor(R.styleable.RoundedView_borderColor,ContextCompat.getColor(context,android.R.color.transparent)));
a.recycle();
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
protected void onDraw(Canvas canvas) {
//if (getBackgroundColor(this) != 0) color = getBackgroundColor(this);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
if(borderWidth>0)
{
float radius=(getWidth()-borderWidth-2)/2;
canvas.drawCircle(radius + borderWidth,radius + borderWidth,radius + borderWidth, mPaintBorder);
canvas.drawCircle(radius + borderWidth,radius + borderWidth,radius ,paint);
}else {
float radius=getWidth()/2;
canvas.drawCircle(radius, radius, radius, paint);
}
}
}
This is how i call it in my xml,
<cl.tk.ui.iBAPView.RoundedView
android:id="#+id/signup_user_rv1"
android:layout_marginRight="#dimen/_3sdp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_width="#dimen/_18sdp"
android:layout_height="#dimen/_18sdp"
app:rborderWidth="#dimen/_2sdp"
app:borderColor="#color/colorBlue"/>
Related
I figured out that the width of the RectF is 0.0 so thats why it is always false. So can I set the width of the RectF width the StrokeWidth?
I have a path. And I want to handle clicks on it.
So I found out I can check that with an onTouchEvent.
So in the OnDraw() Method I draw a path and add the bounds to a rectF where I can get the left, right, top, bottom in the onTouchEvent correctly I guess.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class PathTest extends View {
Paint paint;
Path path;
RectF rectF = new RectF();
public PathTest(Context context) {
super(context);
init();
}
public PathTest(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PathTest(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path.moveTo((float)getWidth()/2,getHeight()-20);
path.lineTo((float)getWidth()/2,20);
path.close();
path.computeBounds(rectF,true);
canvas.drawPath(path,paint);
}
private void init(){
paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(100);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
path = new Path();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width,height/2);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
if(rectF.contains(event.getX(),event.getY())){
Log.d("HALLO","HI");
}else{
Log.d("HALLO","left"+rectF.left+" top"+rectF.top+" right"+rectF.right+" bottom"+rectF.bottom + " x->"+event.getX()+" y->"+event.getY());
}
}
return super.onTouchEvent(event);
}
}
It is always the else. I don't know why.
So I log the rectF Coordinates and the MotionEvent.ACTION_DOWN event.
D/HALLO: left540.0 top20.0 right540.0 bottom2240.0 x->528.0 y->490.0
D/HALLO: left540.0 top20.0 right540.0 bottom2240.0 x->1047.0 y->1021.0
D/HALLO: left540.0 top20.0 right540.0 bottom2240.0 x->1016.0 y->961.0
D/HALLO: left540.0 top20.0 right540.0 bottom2240.0 x->1059.0 y->1062.0```
I am trying to make a game where a user gains experience points and his level increases as shown in the image below.
I was thinking of achieving this with the use of progress bar,but I am not able to make a progress bar with the shape of a Hexagon.
The yellow line should increase as the users points increase.
Can anyone give me ideas on how I can achieve this??(I tried Custom ProgressBar,but it did not work.)
Thanks.
I managed to change the code that Nilesh mentioned and made a progressbar which did not have any curves.
This works fine for me.
Now I just have to figure out how to insert the image inside the progressbar. :p
package com.example.benedict.progress;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
public class V extends View implements View.OnClickListener {
Path segment = new Path();
Paint paint = new Paint();
PathMeasure pm;
String TAG = "View";
Path path;
public V(Context context) {
super(context);
init();
}
public V(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public V(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public V(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
void init() {
setOnClickListener(this);
paint.setColor(0xaa00ff00);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
paint.setStrokeCap(Paint.Cap.ROUND);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Path src = new Path();
src.moveTo(8.80000f, 0.630000f);//0
src.lineTo(26.030001f, 0.630000f);//1
src.lineTo(32.109999f, 14.030000f);//2
src.lineTo(26.030001f, 28.440001f);//3
src.lineTo(7.800000f, 28.440001f);//4
src.lineTo(2.200000f, 14.030000f);//5
src.lineTo(8.80000f, 0.630000f);//6
Matrix m = new Matrix();
RectF srcRect = new RectF(0, 0, 32, 40);
RectF dstRect = new RectF(0, 0, w, h);
dstRect.inset(paint.getStrokeWidth() / 2, paint.getStrokeWidth() / 2);
m.setRectToRect(srcRect, dstRect, Matrix.ScaleToFit.CENTER);
Path dst = new Path();
src.transform(m, dst);
pm = new PathMeasure(dst, true);
pm.getSegment(0, pm.getLength() / 2, segment, true);
// segment.rLineTo(0, 0);
setProgress(pm.getLength());
}
void setProgress(float progress) {
segment.reset();
float start = 0;
float end = (progress);
if (start < end) {
pm.getSegment(start, end, segment, true);
} /*else {
pm.getSegment(start, length, segment, true);
// pm.getSegment(0, end, segment, true);
}*/
segment.rLineTo(0, 0);
invalidate();
}
#Override
public void onClick(View v) {
ObjectAnimator.ofFloat(this, "progress", 0,
pm.getLength()).setDuration(5 * 2500).start();
Log.d(TAG, pm.getLength() + "");
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(segment, paint);
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/loading_status"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center_horizontal"
android:orientation="vertical"
android:background="#000"
android:visibility="visible" >
<com.example.benedict.progress.V
android:id="#+id/progress"
android:src="#drawable/poster1"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
</LinearLayout>
My application draws a circle when the screen is pressed. I'm trying to put text on the circles according to how many there are the screen. So if your first tap will give you a circle with the text C0, the second will give you a circle for C1, etc.
Currently my code looks like
lPaint = new Paint();
lPaint.setColor(Color.WHITE);
lPaint.setTextAlign(Paint.Align.CENTER);
lPaint.setTextSize(40);
nCanvas.drawCircle(v.x, v.y, 55, cPaint);
nCanvas.drawText("C"+i, v.x, v.y, lPaint);
Where v.x and v.y are the coordinators where you've touched the screen, and i is the circle counter. This code starts off just fine, but after the first circle draw, it changes ALL the text for ALL the circles to the new i value. How do I get around this?
Thanks
Just create a new variable i, inside custom view. Then increment variable i inside on click and in onDraw method just draw circle, or whatever you want.For example:
package yourpackage.
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
/**
* Color view used for picking color for drawing
*/
public class ColorView extends View {
private Paint drawPaint;
private int color = ContextCompat.getColor(getContext(), android.R.color.black);
private int i;
public ColorView(Context context) {
this(context, null);
}
public ColorView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ColorView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
drawPaint = new Paint();
drawPaint.setAntiAlias(true);
drawPaint.setColor(color);
drawPaint.setStyle(Paint.Style.FILL);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, 100, 200, drawPaint);
}
public void setColor(int color) {
drawPaint.setColor(color);
this.color = color;
}
public void onClick() {
i++;
}
public int getColor() {
return color;
}
}
I had successfully created an answer of my This question(left drawable alignment with text in andorid)
but the problem is that the canvas.drawText x co-ordinate is not working properly as the x co-ordinate is not affecting the position of text.
Here is the result with overlapped text on drawable,
I just wanted to remove the overlap and give the distance between the drawable and text on canvas.
Here is my code as follows,
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
android.widget.TextView;
import cl.tt.R;
public class CenterDrawableButton extends TextView{
private Drawable mDrawableCenter;
public CenterDrawableButton(Context context) {
super(context);
init(context, null);
}
public CenterDrawableButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs){
if(attrs!=null){
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CenterDrawableButton, 0, 0);
try {
setCenterDrawable(a.getDrawable(R.styleable.CenterDrawableButton_drawableCenter));
} finally {
a.recycle();
}
}
}
public void setCenterDrawable(#Nullable Drawable center) {
int[] state;
state = getDrawableState();
if (center != null) {
center.setState(state);
center.setBounds(0, 0, center.getIntrinsicWidth(), center.getIntrinsicHeight());
center.setCallback(this);
}
mDrawableCenter = center;
invalidate();
requestLayout();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mDrawableCenter != null) {
setMeasuredDimension(Math.max(getMeasuredWidth(), mDrawableCenter.getIntrinsicWidth()),
Math.max(getMeasuredHeight(), mDrawableCenter.getIntrinsicHeight()));
}
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (mDrawableCenter != null) {
int[] state = getDrawableState();
mDrawableCenter.setState(state);
mDrawableCenter.setBounds(0, 0, mDrawableCenter.getIntrinsicWidth(),
mDrawableCenter.getIntrinsicHeight());
}
invalidate();
}
#Override
protected void onDraw(#NonNull Canvas canvas) {
super.onDraw(canvas);
if (mDrawableCenter != null) {
float textWidth = getPaint().measureText((String)getText());
int newPosition=getWidth()-((int)textWidth+getPaddingLeft() + getPaddingRight()+mDrawableCenter.getIntrinsicWidth()+ (int)getResources().getDimension(R.dimen._5sdp));
if(newPosition>0) {
canvas.translate(newPosition, (getHeight() - mDrawableCenter.getIntrinsicHeight()) / 2);
mDrawableCenter.draw(canvas);
canvas.save();
Paint textPaint = new Paint();
int yPos = (int) ((getHeight() - ((textPaint.descent() + textPaint.ascent())) / 2));
canvas.drawText(getText().toString(), newPosition, yPos, textPaint);
canvas.restore();
}else
{
int gnewPosition=getPaddingLeft() + getPaddingRight()+(int)getResources().getDimension(R.dimen._5sdp);
canvas.translate(gnewPosition, (getHeight() - mDrawableCenter.getIntrinsicHeight()) / 2);
mDrawableCenter.draw(canvas);
canvas.save();
int nggewPosition=getPaddingLeft() + getPaddingRight()+mDrawableCenter.getIntrinsicWidth()+ (int)getResources().getDimension(R.dimen._5sdp);
Paint textPaint = new Paint();
int yPos = (int) (getHeight() - ((textPaint.descent() + textPaint.ascent())) / 2);
canvas.translate(nggewPosition, yPos);
canvas.drawText(getText().toString(), nggewPosition, yPos, textPaint);
canvas.restore();
}
}
}
}
here is the attr,
<attr name="drawableCenter" format="reference"/>
<declare-styleable name="CenterDrawableButton">
<attr name="drawableCenter"/>
</declare-styleable>
I want to mirror the app an use a customized relativeLayout class for the root view.
It works fine, but I habe one problem. If I refresh something in one element, that is mirrored not on the physical Location, it won't be updated. So I have to correct the coordinate, which should be updated, but I don't know how.
package de.etestdriver.everclock.gui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
public class HUDRelativeLayout extends RelativeLayout{
public HUDRelativeLayout(Context context) {
super(context);
this.setWillNotDraw(false);
}
public HUDRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.setWillNotDraw(false);
}
public HUDRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setWillNotDraw(false);
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.scale(-1,1, getWidth()/2, getHeight()/2);
super.dispatchDraw(canvas);
canvas.restore();
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
event.setLocation( getWidth()-event.getX(), event.getY());
return super.dispatchTouchEvent(event);
}
}