How to cut circle from one side - android

Hi I am trying to create Circle using canvas like following image.
But now I can only able to make like following.
I don't understand how can I make this. I need to cut the circle from one side and need to fill that circle border only.
Here is my code For review.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Clear canvas
canvas.drawColor(Color.TRANSPARENT);
// Draw Ticks and colored arc
drawTicks(canvas);
}
private void drawTicks(Canvas canvas) {
float availableAngle = 160;
float majorStep = (float) (majorTickStep/ maxSpeed *availableAngle);
float majorTicksLength = 30;
RectF oval = getOval(canvas, 1);
float radius = oval.width()*0.35f;
float currentAngle = 10;
double curProgress = 0;
while (currentAngle <= 170) {
if (labelConverter != null) {
canvas.save();
canvas.rotate(180 + currentAngle, oval.centerX(), oval.centerY());
float txtX = oval.centerX() + radius + majorTicksLength/2 + 8;
float txtY = oval.centerY();
canvas.rotate(+90, txtX, txtY);
//canvas.drawText(labelConverter.getLabelFor(curProgress, maxSpeed), txtX, txtY, txtPaint);
canvas.restore();
}
currentAngle += majorStep;
curProgress += majorTickStep;
}
RectF smallOval = getOval(canvas, 0.7f);
colorLinePaint.setColor(defaultColor);
//canvas.drawArc(smallOval, 185, 170, false, colorLinePaint);
canvas.drawCircle(250, 210, 180, colorLinePaint);
for (ColoredRange range: ranges) {
colorLinePaint.setColor(range.getColor());
//canvas.drawArc(smallOval, (float) (190 + range.getBegin()/ maxSpeed *160), (float) ((range.getEnd() - range.getBegin())/ maxSpeed *160), false, colorLinePaint);
//canvas.drawArc(smallOval, (float) (190 + range.getBegin()/ maxSpeed *160), (float) ((range.getEnd() - range.getBegin())/ maxSpeed *160), false, colorLinePaint);
//canvas.drawCircle((float) (190 + range.getBegin()/ maxSpeed *160), (float) ((range.getEnd() - range.getBegin())/ maxSpeed *160), 100, colorLinePaint);
//canvas.drawCircle((float)(300 + range.getBegin()/ maxSpeed *160), (float) ((range.getEnd() - range.getBegin())/ maxSpeed *160), 180, colorLinePaint);
}
}
private RectF getOval(Canvas canvas, float factor) {
RectF oval;
final int canvasWidth = canvas.getWidth() - getPaddingLeft() - getPaddingRight();
final int canvasHeight = canvas.getHeight() - getPaddingTop() - getPaddingBottom();
if (canvasHeight*2 >= canvasWidth) {
oval = new RectF(0, 0, canvasWidth*factor, canvasWidth*factor);
} else {
oval = new RectF(0, 0, canvasHeight*2*factor, canvasHeight*2*factor);
}
oval.offset((canvasWidth-oval.width())/2 + getPaddingLeft(), (canvasHeight*2-oval.height())/2 + getPaddingTop());
return oval;
}
Really got stuck on this. Please give me any hint or reference.

i created a View for you.. it may help.. just give a try... its only a basic view...i think it will give an idea..
package abbitfoot.likhil.customeprogressbar;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ProgressBar;
public class CustomeView extends View {
Paint red=new Paint();
Paint white=new Paint();
Paint bg=new Paint();
int radiusBg=200;
public CustomeView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
private void init(){
red.setColor(Color.RED);
white.setColor(Color.WHITE);
bg.setColor(Color.rgb(0x99, 0x99, 0x99));
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.save();
canvas.drawCircle(getWidth()/2, getHeight()/2, radiusBg, bg);
Rect oval=new Rect(getWidth()/2-radiusBg+10, getHeight()/2-radiusBg+10,getWidth()/2+radiusBg-10,getHeight()/2+radiusBg-10 );
RectF rectF=new RectF(oval);
canvas.drawArc(rectF, 140,200,true, red);
canvas.drawArc(rectF, 340,60,true, white);
canvas.drawCircle(getWidth()/2, getHeight()/2, radiusBg-25, bg);
canvas.restore();
}
}
hope this will help you...and sorry this is not a rightmethod i think..

Related

Multiple rectangles not drawing on canvas

I am trying to create a family tree like structure in android. I am using canvas to draw rectangle and line for family members names and connecting line.
I am drawing rectangle and line by the following method with the help of link
DrawView.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;
public class DrawView extends View {
Paint paint = new Paint();
float mx, my, mdensity;
Paint mBGPaint, mTXTPaint,mLINEPaint,mBRDPaint;
String text;
public DrawView(Context context, float x, float y, float density, String text) {
super(context);
paint.setColor(Color.RED);
paint.setStrokeWidth(8);
paint.setStyle(Paint.Style.STROKE);
mx = x;
my = y;
mdensity = density;
this.text = text;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
init();
mLINEPaint.setStrokeWidth(8);
//draw rect border
canvas.drawRect(100, 100, 200, 200, mBRDPaint);
// //draw text
canvas.drawText(text, 150, 150, mTXTPaint);
// //draw line
float x = mx+150;
canvas.drawLine(x, 10, x, 100, mLINEPaint);
}
public void init() {
//rectangle background
mBGPaint = new Paint();
mBGPaint.setColor(Color.parseColor("#80123456"));
//your text
mTXTPaint = new Paint();
mTXTPaint.setColor(Color.parseColor("#123456"));
//your line
mLINEPaint = new Paint();
mLINEPaint.setColor(0xFFFF00FF);
//rectangle border
mBRDPaint = new Paint();
mBRDPaint.setStyle(Paint.Style.STROKE);
mBRDPaint.setStrokeWidth(10);
mBRDPaint.setColor(Color.parseColor("#80123456"));
}
}
Now I am trying to add multiple views in LinearLayout with orientation horizontal like below :
float density = getApplicationContext().getResources().getDisplayMetrics().density;
DrawView drawView;
float x = 100, y = 200;
int count1 = 1;
int id;
LinearLayout layout2 = new LinearLayout(this);
layout2.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
layout2.setOrientation(LinearLayout.HORIZONTAL);
main_layout.addView(layout2);
DrawView drawView1;
CircleView circleView;
for (Map.Entry<String, ArrayList<String>> entry : map.entrySet()) {
String key = entry.getKey();
if (count1 < 2) {
x = dirButton.getX();
y = dirButton.getY();
}
drawView1 = new DrawView(this, x, y, density, key);
drawView1.setId(butId++);
drawView1.setLayoutParams(params);
layout2.addView(drawView1);
count1++;
x = x + 100;
}
But when I do this only one view is added to the canvas and others are not visible. I have no experience in working with canvas in android , I would be glad if someone could guide me with this problem.
I tried working on your project but it is too broad to edit on the answer sheet. I must suggest to look these:
Multiple rect.
Rectangle with view
if (count1 < 2) {
x = dirButton.getX();
y = dirButton.getY();
}
from the code line above, you set condition for when the line is executed.
and use if statement.
int count1 = 1; //Count was initialized to 1
This makes the code to enter the if statement on first call
count1++;
This line increases the value of count to 2, hence the if block do not execute again...
And y value never change which leads to overlay.
May be what you missed is regular increament of y
y+=something;
Hope that helps
Please check how i have done this,
You can check from here form myapp, how it work
// How i call to draw rectangle
This is the SDV.class
public static boolean isDrawing = false;
public static float mStartX;
public static float mStartY;
public static float mx;
public static float my;
public static void Shape14(float x, float y, float radius) {
Path path = new Path();
y -= 2 * radius;
radius *= 2;
path.moveTo(x + radius, y + radius);
path.lineTo(x - radius, y + radius);
path.lineTo(x, y);
path.lineTo(x + radius, y + radius);
float div = (2 * radius) / 5;
float top = y + radius;
RectF rect1 = new RectF(x + radius / 4, y, x + radius / 1.9f, y
+ radius);
RectF rect2 = new RectF(x + div / 2, top, x + div / 2 + div, top + div
* 2);
RectF rect3 = new RectF(x - div / 2 - div, top, x - div / 2, top + div
* 2);
RectF rect4 = new RectF(x - div / 2, top, x + div / 2, top + div);
HashMap<String, Object> hm = new HashMap<String, Object>();
hm.put("type", shape14);
hm.put("paint", new Paint(DrawingView.mColorPaint));
hm.put("path", path);
hm.put("rect1", rect1);
hm.put("rect2", rect2);
hm.put("rect3", rect3);
hm.put("rect4", rect4);
al.add(hm);
Gmap.mDrawingView.invalidate();
}
Here is our view,
public class DrawingView extends View {
public static Paint mPaint;
public static int mCurrentShape;
Point p1, p2, p3, p4;
public static Paint mDotedPaint;
public static Paint mColorPaint;
GoogleMap googleMap;
SeekBar sbWidth;
public static float sx, sy;
public DrawingView(Context context, GoogleMap googleMap, SeekBar sbWidth) {
super(context);
this.googleMap = googleMap;
this.sbWidth = sbWidth;
mPaint = new Paint(Paint.DITHER_FLAG);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(SDV.colorChoosen);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(SDV.width);
mDotedPaint = new Paint(Paint.DITHER_FLAG);
mDotedPaint.setAntiAlias(true);
mDotedPaint.setDither(true);
mDotedPaint.setColor(SDV.colorChoosen);
mDotedPaint.setStyle(Paint.Style.STROKE);
mDotedPaint.setStrokeJoin(Paint.Join.ROUND);
mDotedPaint.setStrokeCap(Paint.Cap.ROUND);
mDotedPaint.setStrokeWidth(SDV.width);
mColorPaint = new Paint(Paint.DITHER_FLAG);
mColorPaint.setAntiAlias(true);
mColorPaint.setDither(true);
mColorPaint.setFilterBitmap(true);
mColorPaint.setStyle(Paint.Style.FILL);
mColorPaint.setStrokeWidth(SDV.width);
mColorPaint.setColor(SDV.colorChoosen);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
sx = super.getWidth() * 0.5f;
sy = super.getHeight() * 0.5f;
if (SDV.isDrawing) {
new OnGoingDrawings().HandleAllOnGoingDrawings(mCurrentShape,
canvas);
} else {
new ShapeDrawer().DrawEverything(canvas, googleMap, sbWidth);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
SDV.mx = event.getX();
SDV.my = event.getY();
switch (mCurrentShape) {
case SDV.shape14:
TouchEvents.Shape14(event);
break;
return true;
}
}
Here is touch listener,
public static void Shape14(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
SDV.isDrawing = true;
SDV.mStartX = SDV.mx;
SDV.mStartY = SDV.my;
Gmap.mDrawingView.invalidate();
break;
case MotionEvent.ACTION_MOVE:
Gmap.mDrawingView.invalidate();
break;
case MotionEvent.ACTION_UP:
SDV.isDrawing = false;
float x = SDV.mStartX,
y = SDV.mStartY;
float DifX = Math.abs(SDV.mx - SDV.mStartX);
float DifY = Math.abs(SDV.my - SDV.mStartY);
float radius;
if (DifY > DifX)
radius = Math.abs(SDV.my - SDV.mStartY);
else
radius = Math.abs(SDV.mx - SDV.mStartX);
SDV.Shape14(x, y, radius);
break;
}
}

how to make a growing line animation on canvas android

I am trying to make an animation of growing line it will look like that line is moving towards the end of canvas width and the start of the line will be constant only end of line should be growing
here is my code of the class which paint line on android PLZ HELP ANY HELP WOULD BE APPREICATED.
package com.example.line;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.view.View;
public class MyPlay extends View{
float startx = 30;
float starty = 60;
float endx=0;
float endy=0;
public MyPlay(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
Paint textPaint = new Paint();
textPaint.setARGB(50, 254, 10, 50);
textPaint.setColor(Color.RED);
textPaint.setTextAlign(Align.CENTER);
textPaint.setTextSize(20);
canvas.drawText("Made by Skyrush", canvas.getWidth()/2, canvas.getHeight()/2, textPaint);
Paint linePaint = new Paint();
linePaint.setColor(Color.BLACK);
linePaint.setStrokeWidth(2);
//canvas.drawLine(startx, starty, endx, endy, linePaint);
if(endx < canvas.getWidth()){
endx = startx+5;
endy = starty-5;
canvas.drawLine(startx, starty, endx, endy, linePaint);
invalidate();
}
invalidate();
}
}
In this webpage there's a way to make an animation of a line growing.
You just have to implement the following methods in a custom view:
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// starting point
x1 = 50;
y1 = 50;
// ending point
x2 = getWidth() / 2 + getWidth() / 4;
y2 = getHeight() / 2 + getHeight() / 4;
Log.d("line xy xy", x1 + " : "+y1+" : "+x2 + " : "+y2);
divideLineIntoEqualParts();
}
// dividing line into 50 equal parts
private void divideLineIntoEqualParts() {
/*
* Courtesy : www.dummies.com
* (x,y) = (x1 + k(x2 - x1),y1 + k(y2 - y1))
* */
listOfPoints.clear();
for (int k = 1; k <= 50; k++) {
listOfPoints.add(new PointF(x1 + ((k * (x2 - x1)) / 50),y1 + (k * (y2 - y1)) / 50));
}
Log.d("listOfPoints : size : ",listOfPoints.size()+"");
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(inte < listOfPoints.size()){
canvas.drawLine(listOfPoints.get(0).x, listOfPoints.get(0).y, listOfPoints.get(inte).x,listOfPoints.get(inte).y, paint);
inte++;
if(inte < listOfPoints.size()){
invalidate();
}
}

Android Hexagon ImageView

how can I achieve the hexagon imageview that is shown below.
http://imgur.com/1PEGuQu
Note that I tried the solution which is at this question:
How to give hexagon shape to ImageView
And I also tried this solution:
Masking(crop) image in frame
But I don't want to fill a color outside of the hexagon. I want it to be transparent, so the views and images behind can be seen.
By the way I tried, BitmapShader, PorterDuffXFermode etc. but cannot managed to get the result I wanted.
Thanks in advance.
I at last solved my problem. I find a very useful library that specifically does the trick I wanted. It is masking the imageview with a svg type vector image.
Library:
CustomShapeImageView
Result:
Screenshot
Edit: I also want to share the hexagonal svg with you, in case of necessity.
<svg width="205" height="237" xmlns="http://www.w3.org/2000/svg">
<title>hexagon</title>
<metadata id="metadata3064">image/svg+xml</metadata>
<g>
<title>Layer 1</title>
<polygon points="0,59.27092742919922 0,177.8127899169922 102.66026306152344,237.08370971679688 205.3205108642578,177.8127899169922 205.3205108642578,59.27092742919922 102.66026306152344,0 " id="svg_1" fill="#000000"/>
</g>
</svg>
Here is my code for this, this supports shadows to:
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class HexagonImageView extends ImageView {
private Path hexagonPath;
private Path hexagonBorderPath;
private float radius;
private Bitmap image;
private int viewWidth;
private int viewHeight;
private Paint paint;
private BitmapShader shader;
private Paint paintBorder;
private int borderWidth = 4;
public HexagonImageView(Context context) {
super(context);
setup();
}
public HexagonImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public HexagonImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setup();
}
private void setup() {
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
setBorderColor(Color.WHITE);
paintBorder.setAntiAlias(true);
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 1.0f, 1.0f, Color.BLACK);
hexagonPath = new Path();
hexagonBorderPath = new Path();
}
public void setRadius(float r) {
this.radius = r;
calculatePath();
}
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
private void calculatePath() {
float triangleHeight = (float) (Math.sqrt(3) * radius / 2);
float centerX = viewWidth/2;
float centerY = viewHeight/2;
hexagonBorderPath.moveTo(centerX, centerY + radius);
hexagonBorderPath.lineTo(centerX - triangleHeight, centerY + radius/2);
hexagonBorderPath.lineTo(centerX - triangleHeight, centerY - radius/2);
hexagonBorderPath.lineTo(centerX, centerY - radius);
hexagonBorderPath.lineTo(centerX + triangleHeight, centerY - radius/2);
hexagonBorderPath.lineTo(centerX + triangleHeight, centerY + radius/2);
hexagonBorderPath.moveTo(centerX, centerY + radius);
float radiusBorder = radius - borderWidth;
float triangleBorderHeight = (float) (Math.sqrt(3) * radiusBorder / 2);
hexagonPath.moveTo(centerX, centerY + radiusBorder);
hexagonPath.lineTo(centerX - triangleBorderHeight, centerY + radiusBorder/2);
hexagonPath.lineTo(centerX - triangleBorderHeight, centerY - radiusBorder/2);
hexagonPath.lineTo(centerX, centerY - radiusBorder);
hexagonPath.lineTo(centerX + triangleBorderHeight, centerY - radiusBorder/2);
hexagonPath.lineTo(centerX + triangleBorderHeight, centerY + radiusBorder/2);
hexagonPath.moveTo(centerX, centerY + radiusBorder);
invalidate();
}
private void loadBitmap() {
BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
if (bitmapDrawable != null)
image = bitmapDrawable.getBitmap();
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
loadBitmap();
// init shader
if (image != null) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
canvas.drawPath(hexagonBorderPath, paintBorder);
canvas.drawPath(hexagonPath, paint);
}
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec, widthMeasureSpec);
viewWidth = width - (borderWidth * 2);
viewHeight = height - (borderWidth * 2);
radius = height / 2 - borderWidth;
calculatePath();
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
}
else {
result = viewWidth;
}
return result;
}
private int measureHeight(int measureSpecHeight, int measureSpecWidth) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
}
else {
result = viewHeight;
}
return (result + 2);
}
}
I've read this and looks valid. They even have a video tutorial: http://www.41post.com/4794/programming/android-rendering-a-path-with-a-bitmap-fill on how to fill a shape with a texture

UniversalImageLoader android : Add white border around rounded image

I use UniversalImageLoader library to create a rounded imageview :
DisplayImageOptions options = new DisplayImageOptions.Builder()
.displayer(new RoundedBitmapDisplayer(2000))
.cacheOnDisc(true)
.build();
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(avatar, rounded, options);
How can i add a thin border (1dp) around the rounded imageView ?
This issue was addressed some times ago but was not implemented in the UIL so here is what you have to do change the BitmapDisplayer to CircleBitmapDisplayer like this
package com.nostra13.universalimageloader.core.display;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import com.nostra13.universalimageloader.core.assist.LoadedFrom;
import com.nostra13.universalimageloader.core.imageaware.ImageAware;
import com.nostra13.universalimageloader.core.imageaware.ImageViewAware;
public class CircleBitmapDisplayer implements BitmapDisplayer {
private float radius, centerX, centerY, borderWidth = 0;
private int borderColor = Color.BLACK;
private boolean biggestCircle = false, isCentered = true;
public CircleBitmapDisplayer() {
this.biggestCircle = true;
}
public CircleBitmapDisplayer(float centerX, float centerY) {
this();
this.centerX = centerX;
this.centerY = centerY;
this.isCentered = false;
}
public CircleBitmapDisplayer(float borderWidth, int borderColor) {
this();
this.borderWidth = borderWidth;
this.borderColor = borderColor;
}
public CircleBitmapDisplayer(float radius) {
this.radius = radius;
}
public CircleBitmapDisplayer(float radius, float borderWidth,
int borderColor) {
this(radius);
this.borderWidth = borderWidth;
this.borderColor = borderColor;
}
public CircleBitmapDisplayer(float radius, float centerX, float centerY) {
this(radius);
this.centerX = centerX;
this.centerY = centerY;
this.isCentered = false;
}
public CircleBitmapDisplayer(float radius, float centerX, float centerY,
float borderWidth, int borderColor) {
this(radius, centerX, centerY);
this.borderWidth = borderWidth;
this.borderColor = borderColor;
}
#Override
public void display(Bitmap bitmap, ImageAware imageAware,
LoadedFrom loadedFrom) {
if (!(imageAware instanceof ImageViewAware)) {
throw new IllegalArgumentException(
"ImageAware should wrap ImageView. ImageViewAware is expected.");
}
int ivWidth = imageAware.getWidth();
int ivHeight = imageAware.getHeight();
int bmWidth = bitmap.getWidth();
int bmHeight = bitmap.getHeight();
if (isCentered) {
centerX = (float) ivWidth / 2;
centerY = (float) ivHeight / 2;
}
if (biggestCircle) {
if (isCentered) {
radius = ivWidth < ivHeight ? (float) ivWidth / 2
: (float) ivHeight / 2;
} else {
radius = Math.min(centerX < ivWidth - centerX ? centerX
: ivWidth - centerX,
centerY < ivHeight - centerY ? centerX : ivHeight
- centerY);
}
}
Rect srcRect;
if (bmWidth < bmHeight) {
srcRect = new Rect(0, (bmHeight - bmWidth) / 2, bmWidth, bmWidth
+ (bmHeight - bmWidth) / 2);
} else {
srcRect = new Rect((bmWidth - bmHeight) / 2, 0, bmHeight
+ (bmWidth - bmHeight) / 2, bmHeight);
}
RectF destRectF = new RectF(0, 0, ivWidth, ivHeight);
imageAware.setImageBitmap(getCircledBitmap(bitmap, centerX, centerY,
radius, srcRect, destRectF, ivWidth, ivHeight, borderWidth,
borderColor));
}
public static Bitmap getCircledBitmap(Bitmap bitmap, float centerX,
float centerY, float radius, Rect srcRect, RectF destRectF,
int width, int height, float borderWidth, int borderColor) {
Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
paint.setAntiAlias(true);
// if 1 pixel is missing, do: radius - borderWidth + 1
canvas.drawCircle(centerX, centerY, radius - borderWidth, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, srcRect, destRectF, paint);
if (0 < borderWidth) {
paint.setXfermode(null);
paint.setStyle(Style.STROKE);
paint.setColor(borderColor);
paint.setStrokeWidth(borderWidth);
canvas.drawCircle(centerX, centerY, radius - borderWidth / 2, paint);
}
return output;
}
}
I guess such customization may not be offered by UniversalImageLoader Internally, however this work arround can fit your need:
The Imageview on which you wish to show the downloaded image, just set its background property to white color, and also set its padding attribute to 1DP. Then set its SRC property to the image you have downloaded using UniversalImageLoader.
This should do the trick!

How to give hexagon shape to ImageView

How to give hexagon shape to ImageView . Is it possible to do in same way ? If so then how. If this is not possible through this then how this could be achieved ?
<shape xmlns:android="http//schemas.android.com/apk/res/android"
android:shape="hexagon">
<solid android:color="#ffffffff" />
<size android:width="60dp"
android:height="40dp" />
</shape>
Screenshot
Here I can't do masking image because I can not detect which portion of bitmap I should crop to get hexagon shape bitmap. So I am looking for the answer to give hexagon shape to ImageView
Try this View. You might want to adjust it for your specific needs, but it draws a hexagon mask with a border on top of a view. The background resource goes below the mask.
The result:
The code:
HexagonMaskView.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Path;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.View;
public class HexagonMaskView extends View {
private Path hexagonPath;
private Path hexagonBorderPath;
private float radius;
private float width, height;
private int maskColor;
public HexagonMaskView(Context context) {
super(context);
init();
}
public HexagonMaskView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public HexagonMaskView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
hexagonPath = new Path();
hexagonBorderPath = new Path();
maskColor = 0xFF01FF77;
}
public void setRadius(float r) {
this.radius = r;
calculatePath();
}
public void setMaskColor(int color) {
this.maskColor = color;
invalidate();
}
private void calculatePath() {
float triangleHeight = (float) (Math.sqrt(3) * radius / 2);
float centerX = width/2;
float centerY = height/2;
hexagonPath.moveTo(centerX, centerY + radius);
hexagonPath.lineTo(centerX - triangleHeight, centerY + radius/2);
hexagonPath.lineTo(centerX - triangleHeight, centerY - radius/2);
hexagonPath.lineTo(centerX, centerY - radius);
hexagonPath.lineTo(centerX + triangleHeight, centerY - radius/2);
hexagonPath.lineTo(centerX + triangleHeight, centerY + radius/2);
hexagonPath.moveTo(centerX, centerY + radius);
float radiusBorder = radius - 5;
float triangleBorderHeight = (float) (Math.sqrt(3) * radiusBorder / 2);
hexagonBorderPath.moveTo(centerX, centerY + radiusBorder);
hexagonBorderPath.lineTo(centerX - triangleBorderHeight, centerY + radiusBorder/2);
hexagonBorderPath.lineTo(centerX - triangleBorderHeight, centerY - radiusBorder/2);
hexagonBorderPath.lineTo(centerX, centerY - radiusBorder);
hexagonBorderPath.lineTo(centerX + triangleBorderHeight, centerY - radiusBorder/2);
hexagonBorderPath.lineTo(centerX + triangleBorderHeight, centerY + radiusBorder/2);
hexagonBorderPath.moveTo(centerX, centerY + radiusBorder);
invalidate();
}
#Override
public void onDraw(Canvas c){
super.onDraw(c);
c.clipPath(hexagonBorderPath, Region.Op.DIFFERENCE);
c.drawColor(Color.WHITE);
c.save();
c.clipPath(hexagonPath, Region.Op.DIFFERENCE);
c.drawColor(maskColor);
c.save();
}
// getting the view size and default radius
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
radius = height / 2 - 10;
calculatePath();
}
}
Update 29.07.2016
A better way to only clip the source image without painting the whole view's background. Switched to an ImageView as a base class to benefit from the scaleType. I also did some code refactoring.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Region;
import android.util.AttributeSet;
import android.widget.ImageView;
public class HexagonMaskView extends ImageView {
private Path hexagonPath;
private Path hexagonBorderPath;
private Paint mBorderPaint;
public HexagonMaskView(Context context) {
super(context);
init();
}
public HexagonMaskView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public HexagonMaskView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
this.hexagonPath = new Path();
this.hexagonBorderPath = new Path();
this.mBorderPaint = new Paint();
this.mBorderPaint.setColor(Color.WHITE);
this.mBorderPaint.setStrokeCap(Paint.Cap.ROUND);
this.mBorderPaint.setStrokeWidth(50f);
this.mBorderPaint.setStyle(Paint.Style.STROKE);
}
public void setRadius(float radius) {
calculatePath(radius);
}
public void setBorderColor(int color) {
this.mBorderPaint.setColor(color);
invalidate();
}
private void calculatePath(float radius) {
float halfRadius = radius / 2f;
float triangleHeight = (float) (Math.sqrt(3.0) * halfRadius);
float centerX = getMeasuredWidth() / 2f;
float centerY = getMeasuredHeight() / 2f;
this.hexagonPath.reset();
this.hexagonPath.moveTo(centerX, centerY + radius);
this.hexagonPath.lineTo(centerX - triangleHeight, centerY + halfRadius);
this.hexagonPath.lineTo(centerX - triangleHeight, centerY - halfRadius);
this.hexagonPath.lineTo(centerX, centerY - radius);
this.hexagonPath.lineTo(centerX + triangleHeight, centerY - halfRadius);
this.hexagonPath.lineTo(centerX + triangleHeight, centerY + halfRadius);
this.hexagonPath.close();
float radiusBorder = radius - 5f;
float halfRadiusBorder = radiusBorder / 2f;
float triangleBorderHeight = (float) (Math.sqrt(3.0) * halfRadiusBorder);
this.hexagonBorderPath.reset();
this.hexagonBorderPath.moveTo(centerX, centerY + radiusBorder);
this.hexagonBorderPath.lineTo(centerX - triangleBorderHeight, centerY + halfRadiusBorder);
this.hexagonBorderPath.lineTo(centerX - triangleBorderHeight, centerY - halfRadiusBorder);
this.hexagonBorderPath.lineTo(centerX, centerY - radiusBorder);
this.hexagonBorderPath.lineTo(centerX + triangleBorderHeight, centerY - halfRadiusBorder);
this.hexagonBorderPath.lineTo(centerX + triangleBorderHeight, centerY + halfRadiusBorder);
this.hexagonBorderPath.close();
invalidate();
}
#Override
public void onDraw(Canvas c) {
c.drawPath(hexagonBorderPath, mBorderPaint);
c.clipPath(hexagonPath, Region.Op.INTERSECT);
c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
super.onDraw(c);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
calculatePath(Math.min(width / 2f, height / 2f) - 10f);
}
}
Example layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:background="#android:color/holo_green_dark">
<com.scelus.hexagonmaskimproved.HexagonMaskView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/bear"
android:background="#android:color/holo_green_light"/>
</RelativeLayout>
Here is my working code for this, it supports shadows to:
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class HexagonImageView extends ImageView {
private Path hexagonPath;
private Path hexagonBorderPath;
private float radius;
private Bitmap image;
private int viewWidth;
private int viewHeight;
private Paint paint;
private BitmapShader shader;
private Paint paintBorder;
private int borderWidth = 4;
public HexagonImageView(Context context) {
super(context);
setup();
}
public HexagonImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public HexagonImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setup();
}
private void setup() {
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
setBorderColor(Color.WHITE);
paintBorder.setAntiAlias(true);
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 1.0f, 1.0f, Color.BLACK);
hexagonPath = new Path();
hexagonBorderPath = new Path();
}
public void setRadius(float r) {
this.radius = r;
calculatePath();
}
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
private void calculatePath() {
float triangleHeight = (float) (Math.sqrt(3) * radius / 2);
float centerX = viewWidth/2;
float centerY = viewHeight/2;
hexagonBorderPath.moveTo(centerX, centerY + radius);
hexagonBorderPath.lineTo(centerX - triangleHeight, centerY + radius/2);
hexagonBorderPath.lineTo(centerX - triangleHeight, centerY - radius/2);
hexagonBorderPath.lineTo(centerX, centerY - radius);
hexagonBorderPath.lineTo(centerX + triangleHeight, centerY - radius/2);
hexagonBorderPath.lineTo(centerX + triangleHeight, centerY + radius/2);
hexagonBorderPath.moveTo(centerX, centerY + radius);
float radiusBorder = radius - borderWidth;
float triangleBorderHeight = (float) (Math.sqrt(3) * radiusBorder / 2);
hexagonPath.moveTo(centerX, centerY + radiusBorder);
hexagonPath.lineTo(centerX - triangleBorderHeight, centerY + radiusBorder/2);
hexagonPath.lineTo(centerX - triangleBorderHeight, centerY - radiusBorder/2);
hexagonPath.lineTo(centerX, centerY - radiusBorder);
hexagonPath.lineTo(centerX + triangleBorderHeight, centerY - radiusBorder/2);
hexagonPath.lineTo(centerX + triangleBorderHeight, centerY + radiusBorder/2);
hexagonPath.moveTo(centerX, centerY + radiusBorder);
invalidate();
}
private void loadBitmap() {
BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
if (bitmapDrawable != null)
image = bitmapDrawable.getBitmap();
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
loadBitmap();
// init shader
if (image != null) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
canvas.drawPath(hexagonBorderPath, paintBorder);
canvas.drawPath(hexagonPath, paint);
}
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec, widthMeasureSpec);
viewWidth = width - (borderWidth * 2);
viewHeight = height - (borderWidth * 2);
radius = height / 2 - borderWidth;
calculatePath();
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
}
else {
result = viewWidth;
}
return result;
}
private int measureHeight(int measureSpecHeight, int measureSpecWidth) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
}
else {
result = viewHeight;
}
return (result + 2);
}
}
There are a couple things you can try:
You might want to try drawing a 9patch in top of your image.
There's also this short tuto by Romain Guy : http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
RectF rect = new RectF(0.0f, 0.0f, width, height);
// rect contains the bounds of the shape
// radius is the radius in pixels of the rounded corners
// paint contains the shader that will texture the shape
canvas.drawRoundRect(rect, radius, radius, paint);
Instead of using drawRoundRect() method of canvas, you may try using drawPath() to get the desired shape.
Hope this puts you on the right direction.
See this example which is creating triangle so you can get logic from it :)
http://looksok.wordpress.com/2013/08/24/android-triangle-arrow-defined-as-an-xml-shape/
Another solution I found but not tested so try this also
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView) findViewById(R.id.text);
Path path = new Path();
float stdW = 100;
float stdH = 100;
float w3 = stdW / 3;
float h2 = stdH / 2;
path.moveTo(0, h2);
h2 -= 6 / 2;
path.rLineTo(w3, -h2); path.rLineTo(w3, 0); path.rLineTo(w3, h2);
path.rLineTo(-w3, h2); path.rLineTo(-w3, 0); path.rLineTo(-w3, -h2);
Shape s = new PathShape(path, stdW, stdH);
ShapeDrawable d = new ShapeDrawable(s);
Paint p = d.getPaint();
p.setColor(0xffeeeeee);
p.setStyle(Style.STROKE);
p.setStrokeWidth(6);
tv.setBackgroundDrawable(d);
}
Source: Google group
Third solution - This might be useful library
PathDrawable is a Drawable that draws simple shapes using Path object.
Its Late to relpy.. But Hope it will help someone...
public Bitmap getHexagonShape(Bitmap scaleBitmapImage) {
// TODO Auto-generated method stub
int targetWidth = 200;
int targetHeight =200;
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth,
targetHeight,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
Path path = new Path();
float stdW = 200;
float stdH = 200;
float w3 =stdW / 2;
float h2 = stdH / 2;
float radius=stdH/2-10;
float triangleHeight = (float) (Math.sqrt(3) * radius / 2);
float centerX = stdW/2;
float centerY = stdH/2;
path.moveTo(centerX, centerY + radius);
path.lineTo(centerX - triangleHeight, centerY + radius/2);
path.lineTo(centerX - triangleHeight, centerY - radius/2);
path.lineTo(centerX, centerY - radius);
path.lineTo(centerX + triangleHeight, centerY - radius/2);
path.lineTo(centerX + triangleHeight, centerY + radius/2);
path.moveTo(centerX, centerY + radius);
canvas.clipPath(path);
Bitmap sourceBitmap = scaleBitmapImage;
canvas.drawBitmap(sourceBitmap,
new Rect(0, 0, sourceBitmap.getWidth(),
sourceBitmap.getHeight()),
new Rect(0, 0, targetWidth,
targetHeight), null);
return targetBitmap;
}
public static Bitmap drawableToBitmap (Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable)drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
Call this where you want to use
Drawable drawable = getResources().getDrawable( R.drawable.placeholder );
Bitmap b=getHexagonShape(drawableToBitmap(drawable));
img=(ImageView)findViewById(R.id.imageView);
img.setImageBitmap(b);
The function below reads your image as input bitmap and returns a bitmap which is hexagon in shape
public Bitmap getHexagonShape(Bitmap scaleBitmapImage) {
// TODO Auto-generated method stub
int targetWidth = 600;
int targetHeight = 600;
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth,
targetHeight,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
Path path = new Path();
float stdW = 300;
float stdH = 300;
float w3 =stdW / 2;
float h2 = stdH / 2;
path.moveTo(0, (float) (h2*Math.sqrt(3)/2));
path.rLineTo(w3/2, -(float) (h2*Math.sqrt(3)/2)); path.rLineTo(w3, 0); path.rLineTo(w3/2, (float) (h2*Math.sqrt(3)/2));
path.rLineTo(-w3/2, (float) (h2*Math.sqrt(3)/2)); path.rLineTo(-w3, 0); path.rLineTo(-w3/2, -(float) (h2*Math.sqrt(3)/2));
canvas.clipPath(path);
Bitmap sourceBitmap = scaleBitmapImage;
canvas.drawBitmap(sourceBitmap,
new Rect(0, 0, sourceBitmap.getWidth(),
sourceBitmap.getHeight()),
new Rect(0, 0, targetWidth,
targetHeight), null);
return targetBitmap;
}
I don't know if the OP got the answer he was looking for, but here goes.
I've create a custom view, that extends ImageView, that will do the job for you a bit better.
The answer here just creates a maks inside the ImageView and forces you to set the picture as the background
My view lets you set the image like a standard bitmap, it handles CenterCrop and scaling of the image.
It actually sets the mask outside instead, and with the same border plus drop shadow.
And if that not enough, you can easily create custom shapes to render, just be extending the RenderShape-class. (4 shapes are included in the library: Circle, Triangle, Hexagon and Octagon)
Have a look at my github
Cheers
I've solved it using this code:
private Bitmap getHexagoneCroppedBitmap(Bitmap bitmap, int radius) {
Bitmap finalBitmap;
if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
false);
else
finalBitmap = bitmap;
Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
finalBitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
Paint paint = new Paint();
final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
finalBitmap.getHeight());
Point point1_draw = new Point(75, 0);
Point point2_draw = new Point(0, 50);
Point point3_draw = new Point(0, 100);
Point point4_draw = new Point(75, 150);
Point point5_draw = new Point(150, 100);
Point point6_draw = new Point(150, 50);
Path path = new Path();
path.moveTo(point1_draw.x, point1_draw.y);
path.lineTo(point2_draw.x, point2_draw.y);
path.lineTo(point3_draw.x, point3_draw.y);
path.lineTo(point4_draw.x, point4_draw.y);
path.lineTo(point5_draw.x, point5_draw.y);
path.lineTo(point6_draw.x, point6_draw.y);
path.close();
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(finalBitmap, rect, rect, paint);
return output;
}
You can use the Android Shape ImageView by siamed.
https://github.com/siyamed/android-shape-imageview
<com.github.siyamed.shapeimageview.HexagonImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:src="#drawable/neo"
app:siBorderWidth="8dp"
app:siBorderColor="#color/darkgray"/>
Please read the documentation on github, lots of options are available.

Categories

Resources