i am trying to draw a circle which fills the entire changed view (for any device).
Circle will fill as much screen space as possible (without deforming its circular shape).
Rotating the screen orientation will adjust the clock view.
lass Circles extends View
{
private int x = 0;
private int y = 0;
private final int rsec=240;
private final int rmin=200;
private final int rhrs=150;
private Date date;
int viewWidth = 0;
int viewHeight = 0;
int Radius = 0;
public Circles(Context context)
{
super(context);
}
public void onDraw(final Canvas canvas)
{
super.onDraw(canvas);
String msg = "width: " + viewWidth + "height: " + viewHeight;
System.out.println(msg);
x = viewWidth / 2 ;
y = viewHeight / 2 ;
//2 Circels
Paint p1 = new Paint();
p1.setColor(Color.BLUE);
p1.setStyle(Style.STROKE);
Paint p2 = new Paint();
p2.setColor(Color.RED);
p2.setStyle(Style.FILL);
canvas.drawCircle(x, y , Radius, p1);
canvas.drawCircle(x , y , 20, p2);
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
viewWidth = xNew;
viewHeight = yNew;
/*
these viewWidth and viewHeight variables
are the global int variables
that were declared above
*/
this.setMeasuredDimension( viewWidth, viewHeight);
Radius=Math.min(viewWidth, viewHeight);
}
the 1st circle , is not display at all when the phone is vertical , but when rotate him horizontal , the edges of the circke can be seen .
is nayone can tell me whats wrong with the onSizeChanged i used. ?
move this line
this.setMeasuredDimension( viewWidth, viewHeight);
after this line
Radius=Math.min(viewWidth, viewHeight);
and see if this works.
Related
I'm trying to figure out how to fill an View clockwise.
I figured out how to rotate an image but not sure how to rotate and fill.
Used this class to create a circle:
public class Circle extends View {
private static final int START_ANGLE_POINT = 270;
private final Paint paint;
private RectF rect;
private float angle;
public Circle(Context context, AttributeSet attrs) {
super(context, attrs);
final int strokeWidth = 60;
Point[] points = new Point[3];
points[0] = new Point(7, 13);
points[1] = new Point(13, 19);
points[2] = new Point(21, 9);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
//Circle color
paint.setColor(Theme.darkRedColour());
//Initial Angle (optional, it can be zero)
angle = 0;
}
#Override
protected void onDraw(Canvas canvas) {
if (rect == null) {
DisplayMetrics metrics = App.getAppContext().getResources().getDisplayMetrics();
int densityDpi = (int)metrics.density;
densityDpi = 3;
int canvasW = getWidth();
int canvasH = getHeight();
Point centerOfCanvas = new Point(canvasW / 2, canvasH / 2);
int rectW = 100; // * (densityDpi - 1);
int rectH = 100; // * (densityDpi - 1);
int left = centerOfCanvas.x - (rectW / 2);
int top = centerOfCanvas.y - (rectH / 2);
int right = centerOfCanvas.x + (rectW / 2);
int bottom = centerOfCanvas.y + (rectH / 2);
rect = new RectF(left, top, right, bottom);
}
super.onDraw(canvas);
canvas.drawArc(rect, START_ANGLE_POINT, angle, true, paint);
}
public float getAngle() {
return angle;
}
public void setAngle(float angle) {
this.angle = angle;
}
}
Then used an AnimiationListener and updated the angle.
I am trying to get the center coordinates of my custom view (a circle) so that I can draw a line from the those points. The custom view is inside a TableLayout which is itself inside a FrameLayout. However, I am having trouble - this code doesn't get it right. Any advice please?
The values given by this method are wrong on all devices. If I change the layout padding/margins etc. then the dots obviously move, but the point given by this method does not change.
public float[] getDotCenterLocationOnScreen() {
int[] location = new int[2];
getLocationOnScreen(location);
int xLoc = location[0];
int yLoc = location[1];
float xCenter = xLoc + (getWidth()/2);
float yCenter = yLoc - (getWidth()/2);
float[] dotCenterLocation = { xCenter, yCenter };
return dotCenterLocation;
}
Here is most of the code from my view class:
// Radius of Dot
int RADIUS;
private static final int START_RADIUS = 30;
// Value of which the Radius is multiplied by to get full width & height of
// the DotView
int sizeMultiplier = 4;
// Define other Objects
private Paint paint = new Paint();
float mTranslateX;
float mTranslateY;
public DotView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setColor(Color.BLACK);
RADIUS = START_RADIUS;
}
public void setRadius(int radius) {
RADIUS = radius;
invalidate();
}
public int getRadius() {
return RADIUS;
}
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.translate(mTranslateX, mTranslateY);
canvas.drawCircle(0, 0, RADIUS, paint);
canvas.restore();
}
public float[] getDotCenterLocationOnScreen() {
int[] location = new int[2];
getLocationOnScreen(location);
int xLoc = location[0];
int yLoc = location[1];
float xCenter = xLoc + (getWidth()/2);
float yCenter = yLoc - (getWidth()/2);
float[] dotCenterLocation = { xCenter, yCenter };
return dotCenterLocation;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int dia = START_RADIUS * sizeMultiplier; // Multiplying by 2 makes
// boundaries exactly the same size a dot.
int w = resolveSize(dia, widthMeasureSpec);
int h = resolveSize(dia, heightMeasureSpec);
setMeasuredDimension(w, h);
float radius = Math.min(w, h) / 2F;
mTranslateX = radius;
mTranslateY = radius;
}
}
I have a gallery of images with different sizes. Each image is displayed inside an ImageView sequentially (through OnTouchListener). I need to know the position of the frame of the picture I'm showing relatives to the ImageView but with the testing I've done I've only gotten the coordinates of ImageView. Any idea?
I need the values of (x1, y1) and (x2, y2).
Thanks in advance.
This is my class:
public class PuzzleView extends ImageView {
protected Paint currentPaint;
protected boolean drawRect = false;
protected float left;
protected float top;
protected float right;
protected float bottom;
protected float pixelX;
protected float pixelY;
protected int nChunksX = 5;
protected int nChunksY = 5;
protected int currentWidth = 0;
protected int currentHeight = 0;
public PuzzleView(Context context, AttributeSet attrs) {
super(context, attrs);
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFF00CC00);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(2);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float chunkWidth = currentWidth / nChunksX;
float chunkHeight = currentHeight / nChunksY;
float posX = ((int)(pixelX / chunkWidth)) * chunkWidth;
float posY = ((int)(pixelY / chunkHeight)) * chunkHeight;
canvas.drawRect(posX, posY, posX + chunkWidth, posY + chunkHeight, currentPaint);
Rect rect = this.getDrawable().getBounds();
canvas.drawRect(rect, currentPaint);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Get image matrix values and place them in an array
float[] f = new float[9];
getImageMatrix().getValues(f);
// Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
final float scaleX = f[Matrix.MSCALE_X];
final float scaleY = f[Matrix.MSCALE_Y];
// Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
final Drawable d = getDrawable();
final int origW = d.getIntrinsicWidth();
final int origH = d.getIntrinsicHeight();
// Calculate the actual dimensions
final int actW = Math.round(origW * scaleX);
final int actH = Math.round(origH * scaleY);
currentWidth = actW;
currentHeight = actH;
}
public boolean isDrawRect() {
return drawRect;
}
public void setDrawRect(boolean drawRect) {
this.drawRect = drawRect;
}
public float getLeftRect() {
return left;
}
public void setLeftRect(float left) {
this.left = left;
}
public float getTopRect() {
return top;
}
public void setTopRect(float top) {
this.top = top;
}
public float getRightRect() {
return right;
}
public void setRightRect(float right) {
this.right = right;
}
public float getBottomRect() {
return bottom;
}
public void setBottomRect(float bottom) {
this.bottom = bottom;
}
public float getPixelX() {
return pixelX;
}
public void setPixelX(float pixelX) {
this.pixelX = pixelX;
}
public float getPixelY() {
return pixelY;
}
public void setPixelY(float pixelY) {
this.pixelY = pixelY;
}
public int getChunksX() {
return nChunksX;
}
public void setChunksX(int nChunksX) {
this.nChunksX = nChunksX;
}
public int getChunksY() {
return nChunksY;
}
public void setChunksY(int nChunksY) {
this.nChunksY = nChunksY;
}
}
For now, the source image is defined in XML file:
<com.jocajica.shakepic.PuzzleView
android:id="#+id/imageViewSelected"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:contentDescription="#string/image_selected"
android:src="#android:drawable/progress_indeterminate_horizontal" />
I need to draw a grid over the image.
According to Jacob Nordfalk's link, I was able to produce a static method allowing you to get the image position and dimensions from an ImageView.
/**
* Returns the bitmap position inside an imageView.
* #param imageView source ImageView
* #return 0: left, 1: top, 2: width, 3: height
*/
public static int[] getBitmapPositionInsideImageView(ImageView imageView) {
int[] ret = new int[4];
if (imageView == null || imageView.getDrawable() == null)
return ret;
// Get image dimensions
// Get image matrix values and place them in an array
float[] f = new float[9];
imageView.getImageMatrix().getValues(f);
// Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
final float scaleX = f[Matrix.MSCALE_X];
final float scaleY = f[Matrix.MSCALE_Y];
// Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
final Drawable d = imageView.getDrawable();
final int origW = d.getIntrinsicWidth();
final int origH = d.getIntrinsicHeight();
// Calculate the actual dimensions
final int actW = Math.round(origW * scaleX);
final int actH = Math.round(origH * scaleY);
ret[2] = actW;
ret[3] = actH;
// Get image position
// We assume that the image is centered into ImageView
int imgViewW = imageView.getWidth();
int imgViewH = imageView.getHeight();
int top = (int) (imgViewH - actH)/2;
int left = (int) (imgViewW - actW)/2;
ret[0] = left;
ret[1] = top;
return ret;
}
You should use getImageMatrix():
float[] imageMatrix = new float[9];
getImageMatrix().getValues(imageMatrix);
scale = imageMatrix[Matrix.MSCALE_X];
transX = imageMatrix[Matrix.MTRANS_X];
See also
Trying to get the display size of an image in an ImageView
Thank you Quentis S. and Jacob Nordfalk for the very usefull routine.
I took the liberty of changing the return value from an array to a Rect object.
/**
* Returns the bitmap position inside an imageView.
*
* #param imageView source ImageView
* #return Rect position of the bitmap in the ImageView
*/
public static final Rect getBitmapPositionInsideImageView(ImageView imageView)
{
Rect rect = new Rect();
if (imageView == null || imageView.getDrawable() == null)
{
return rect;
}
// Get image dimensions
// Get image matrix values and place them in an array
float[] f = new float[9];
imageView.getImageMatrix().getValues(f);
// Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
final float scaleX = f[Matrix.MSCALE_X];
final float scaleY = f[Matrix.MSCALE_Y];
// Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
final Drawable d = imageView.getDrawable();
final int origW = d.getIntrinsicWidth();
final int origH = d.getIntrinsicHeight();
// Calculate the actual dimensions
final int actW = Math.round(origW * scaleX);
final int actH = Math.round(origH * scaleY);
// Get image position
// We assume that the image is centered into ImageView
int imgViewW = imageView.getWidth();
int imgViewH = imageView.getHeight();
rect.top = (int) (imgViewH - actH) / 2;
rect.left = (int) (imgViewW - actW) / 2;
rect.bottom = rect.top + actH;
rect.right = rect.left + actW;
return rect;
}
Override the onLayout method
//inside puzzleView
float[] matrix = new float[9];
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
matrix = getMatrix();
}
public void getMatrix(){
return matrix;
}
private float[] getMatrix() {
final float[] matrix = new float[9];
getImageMatrix().getValues(matrix);
return matrix;
}
and use this to get values
// Extract the scale and translation values from the matrix.
float scaleX = matrix[Matrix.MSCALE_X];
float scaleY = matrix[Matrix.MSCALE_Y];
float transX = matrix[Matrix.MTRANS_X];
float transY = matrix[Matrix.MTRANS_Y];
I hope that this help u
Each time I create a new rectangle with this code it does not work, I can only draw to a specified position, if I use a variable to change position on execution it does not draw anything.
Inside a Asynctask method:
rect = new desenho(main.this, x, y);
Which calls this:
public class desenho extends View{
int x, y;
Paint mPaint = new Paint();
public desenho(Context context, int x, int y) {
super(context);
this.x = x;
this.y = y;
mPaint.setStrokeWidth(3);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(width, y);
}
#Override
protected void onDraw(Canvas c) {
// TODO Auto-generated method stub
super.onDraw(c);
c.drawRect(5, y, width-5, y+x, mPaint);
}
}
It seems to me that you want the size to be independent of position. For that, these requirements must be met in your Canvas.drawRect(left, top, right, bottom, paint):
left - right = a
top - bottom = b
where a, b are constant. Example:
c.drawRect(xPos, yPos, xPos + width - 1, yPos + height - 1, mPaint);
You see in this example that
left - right = xPos - (xPos + width - 1) = 1 - width
top - bottom = yPos - (yPos + height - 1) = 1 - height
Both are constant → size is constant.
I'm trying to make a color picker that allows the users to pick color by simply having a touch input. My hueShade gives the hue to the color circle, while the saturationShade gives
me the whiting out of the center. The SweepGradient does not need a radius, but the Radial Gradient does require it. However, I am calling this at the time of the creation when it can't get the actual values of the width and height. Instead it picks up the values stated. Is there an intermediate step where the radius can be set when that information is available? Or should I try a different approach?
private Paint mPaint;
private int[] mColors;
private int viewWidth = 120;
private int viewHeight = 120;
private int centerX = 60;
private int centerY = 60;
private int padding = 10;
public ColorWheelView(Context context) {
super(context);
onInitialize();
// TODO Auto-generated constructor stub
}
private void onInitialize()
{
mColors = new int[] {
0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF, 0xFF00FF00,
0xFFFFFF00, 0xFFFF0000
};
Shader totalShade = new SweepGradient(0, 0, mColors, null);
Shader hueShade = new SweepGradient(0, 0, mColors, null);
Shader saturationShade = new RadialGradient(0, 0, (float)viewWidth-padding, 0xFFFFFFFF, 0x00FFFFFF, Shader.TileMode.CLAMP);
//Shader valueShade;
totalShade = new ComposeShader(hueShade, saturationShade, PorterDuff.Mode.SCREEN);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setShader(totalShade);
mPaint.setStyle(Paint.Style.FILL);
}
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld)
{
super.onSizeChanged(xNew, yNew, xOld, yOld);
viewWidth = xNew;
viewHeight = yNew;
centerX = viewWidth / 2;
centerY = viewHeight / 2;
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
super.onLayout(changed, left, top, right, bottom);
viewWidth = right - left;
viewHeight = bottom - top;
centerX = viewWidth / 2;
centerY = viewHeight / 2;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredWidth, measuredHeight);
}
If it helps to figure out what I am achieving, I'm trying to make this view available to use for different size screens. That's why I need the information from the device.
It is best to call this in onLayout since it's typically guaranteed when any change in size or orientation is performed. I wasn't getting desired values previously, but that was because I inherited from a base class other than the Android.view.View class.