Hexagon shaped ProgressBar - android

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>

Related

onTouchEvent on Path

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```

Android Draw Circle with Different Text

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;
}
}

Slanting custom imageview

I'm trying to make a custom imageview which cuts the image like below.
I checked many solutions but the nearest answer I saw is this link. But its slanting to opposite side and that too from corner. How can I cut the image with other side slanting and starting a little below.
// Custom View
public class SlantView extends View {
private Context mContext;
Paint paint ;
Path path;
public SlantView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
mContext = ctx;
setWillNotDraw(false);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
#Override
protected void onDraw(Canvas canvas) {
int w = getWidth(), h = getHeight();
paint.setStrokeWidth(2);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);
path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(0,0);
path.lineTo(0,h);
path.lineTo(w,h);
path.close();
canvas.drawPath(path, paint);
}
}
Here i extended the RelativeLayout. (create a java file named cutLayout)
package com.blin.sharedelementtransition;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
/**
* Created by wituser on 12/12/16.
*/
public class cutLayout extends RelativeLayout {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Xfermode pdMode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
private Path path = new Path();
public cutLayout(Context context) {
super(context);
}
public cutLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public cutLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public cutLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void dispatchDraw(Canvas canvas) {
int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
super.dispatchDraw(canvas);
paint.setXfermode(pdMode);
path.reset();
// path.moveTo(0, getHeight() - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()));
path.moveTo(0, getHeight());
path.lineTo(getWidth(), getHeight());
path.lineTo(getWidth(), getHeight() - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()));
// change value (50) to change the the slope.50 means 50dp.
// path.lineTo(getWidth()/2, getHeight());
// path.moveTo(0,0); // (0,0)
// path.lineTo(getPx(50),0); // (50,0)
// path.lineTo(0,getPx(50)); // (0,50)
//
// path.lineTo(0,getHeight()-getPx(50)); // (0,H-50)
// path.lineTo(getPx(50),getHeight()); // (50,H)
// path.lineTo(0,getHeight()); // (0,H)
//
// path.lineTo(0,0); // (0,0)
// path.lineTo(getWidth()-getPx(50),0); // (W-50,0)
// path.lineTo(getWidth(),getPx(50)); // (W,50)
// path.lineTo(getWidth(),0); // (W,0)
//
// path.lineTo(getWidth(),getHeight()-getPx(50)); // (W,H-50)
// path.lineTo(getWidth()-getPx(50),getHeight()); // (W-50,H)
// path.lineTo(getWidth(),getHeight()); // (W,H)
// path.lineTo(getWidth(),0); // (W,0)
path.close();
canvas.drawPath(path, paint);
canvas.restoreToCount(saveCount);
paint.setXfermode(null);
}
private float getPx(int i) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, i, getResources().getDisplayMetrics());
}
}
and in xml, <your.package.name.cutLayout . cutLayout is the name of the javafile.
<com.blin.sharedelementtransition.cutLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_margin="8dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg2"
android:layout_marginBottom="0.5dp"/>
</com.blin.sharedelementtransition.cutLayout>

How to scale custom image views in android?

In my face detector project, I'm using a custom ImageView (MyView) to detect faces and draw rectangles on the detected faces. For this I have set fixed dimensions for my customview (MyView) and trying to scale the bitmap to fit the customview. But somehow I'm not able to achieve this.
I have gone throught all similar questions on SO. Please help.
activity_main.xml
<RelativeLayout
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"
tools:context=".MainActivity">
<com.sample.facedetector.MyView
android:layout_width="300dp"
android:layout_height="300dp"
android:id="#+id/MyViewId"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="28dp"
android:scaleType="centerCrop"/>
MainActivity
package com.sample.facedetector;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyView faceDetectorView = (MyView) findViewById(R.id.MyViewId);
Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.face_detector).copy(Bitmap.Config.RGB_565,true);
faceDetectorView.setImage(bmp);
faceDetectorView.setScaleType(ImageView.ScaleType.CENTER_CROP);
faceDetectorView.detectFaces();
}
MyView
package com.sample.facedetector;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.media.FaceDetector;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.widget.ImageView;
public class MyView extends ImageView {
private Bitmap mFaceBitmap;
private int count = 0;
private FaceDetector.Face[] faces;
private Bitmap image;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void detectFaces(){
FaceDetector myFaceDetector = null;
mFaceBitmap = image.copy(Bitmap.Config.RGB_565, true);
int targetWidth = mFaceBitmap.getWidth();
int targetHeight = mFaceBitmap.getHeight();
faces= new FaceDetector.Face[5];
int[] fpx =null;
int[] fpy = null;
myFaceDetector = new FaceDetector(targetWidth,targetHeight,5);
count = myFaceDetector.findFaces(mFaceBitmap, faces);
setWillNotCacheDrawing(true);
requestLayout();
this.invalidate();
}
/*#Override
public void setScaleType(ScaleType scaleType) {
super.setScaleType(ScaleType.CENTER);
invalidate();
}*/
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mFaceBitmap,0,0,null);
Paint myPaint = new Paint();
myPaint.setColor(Color.GREEN);
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(3);
if (count > 0) {
for (int i = 0; i < count; i++) {
FaceDetector.Face face = faces[i];
PointF midPoint = new PointF();
face.getMidPoint(midPoint);
float eyeDistance = face.eyesDistance();
canvas.drawRect(midPoint.x-eyeDistance, midPoint.y-eyeDistance, midPoint.x+eyeDistance, midPoint.y+eyeDistance, myPaint);
}
}
}
#Override
public void setImageResource(#DrawableRes int resId) {
super.setImageResource(resId);
invalidate();
}
public void setImage(Bitmap image) {
this.image = image;
}
}

Clip Image View using xfer

I'm trying to cut an Image view, for now I've created a custom component.
This is the code:
package it.patrick91.eventually;
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.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
public class CutImageView extends ImageView {
private Path clipPath;
private int type = 0;
public int getType() {
return type;
}
public void setType(int type) {
Log.d("cut", new Integer(type).toString());
this.type = type;
}
public CutImageView(Context context) {
super(context);
}
public CutImageView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = getContext().obtainStyledAttributes(attrs,
R.styleable.CutImageView);
setType(a.getInt(R.styleable.CutImageView_type, 0));
}
public CutImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = getContext().obtainStyledAttributes(attrs,
R.styleable.CutImageView);
setType(a.getInt(R.styleable.CutImageView_type, 0));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Log.d("cut", "size changed " + w + " " + h);
clipPath = new Path();
if (type == 0) {
clipPath.moveTo(0, 0);
clipPath.lineTo(0, h);
clipPath.lineTo(w, 0);
clipPath.lineTo(0, 0);
} else {
clipPath.moveTo(w, 0);
clipPath.lineTo(w, h);
clipPath.lineTo(0, h);
}
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
//canvas.clipPath(clipPath);
super.onDraw(canvas);
Bitmap rounder = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(rounder);
Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xferPaint.setColor(Color.BLACK);
c.drawPath(clipPath, xferPaint);
xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(rounder, 0, 0, xferPaint);
}
}
So I'm basically using the xfer method as shown in this answer.
The problem is that the erased part is black. As I can read from the comments of that answer I have to ensure that I'm in an ARGB drawing context, but I'm not sure if I can do it within a subclass of ImageView. Can you help me?
This is what I get:

Categories

Resources