I need a semi circular menu for my app .
I have been using this library to achieve the same :-
https://github.com/xresco/CircularLayout
I am able to achieve something like this:-
As you can see the Library works well for circular layout , however for rectangular layouts , not so good.
The code which handles the rotation of the rectangles is as follows:-
#Override
#SuppressWarnings("deprecation")
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int childs = getChildCount();
float totalWeight = 0f;
for(int i=0; i<childs; i++) {
final View child = getChildAt(i);
LayoutParams lp = layoutParams(child);
totalWeight += lp.weight;
}
shiftAngle= mAngleRange/totalWeight;
final int width = getWidth();
final int height = getHeight();
final float minDimen = width > height ? height : width;
float radius = (minDimen )/2f;
radius=(float) (width/2)+radius_parameter;
float startAngle = mAngleOffset+270;
for(int i=0; i<childs; i++) {
final View child = getChildAt(i);
final LayoutParams lp = layoutParams(child);
final float angle = mAngleRange/totalWeight * lp.weight;
final float centerAngle = startAngle ;
final int x;
final int y;
Log.e("CenterAngle", String.valueOf(centerAngle));
if(child instanceof CircularLayoutItem)
{
CircularLayoutItem civ=(CircularLayoutItem)child;
civ.setRotationParameters((int)(centerAngle)+90);
}
if(childs > 1) {
x = (int) (radius * Math.cos(Math.toRadians(centerAngle))) + width/2+center_width_parameter;
y = (int) (radius * Math.sin(Math.toRadians(centerAngle))) + height/3+(int)radius+center_height_parameter;
} else {
x = width/2;
y = height/2;
}
final int halfChildWidth = child.getMeasuredWidth()/2;
final int halfChildHeight = child.getMeasuredHeight()/2;
final int left = lp.width != LayoutParams.FILL_PARENT ? x - halfChildWidth : 0;
final int top = lp.height != LayoutParams.FILL_PARENT ? y - halfChildHeight : 0;
final int right = lp.width != LayoutParams.FILL_PARENT ? x + halfChildWidth : width;
final int bottom = lp.height != LayoutParams.FILL_PARENT ? y + halfChildHeight : height;
Log.e("Coords", String.valueOf(left)+"/"+right+"/"+top+"/"+bottom);
child.layout(left, top, right, bottom);
startAngle += angle;
}
invalidate();
}
Is there a way so that the rectangles appear as whole and still facing to the center?
I have come here from here:-
Horizontal Curved Sliding menu
Any help is appreciated.Thank you.
Related
Description:
I have a class called Container which can hold items. In the code below I added only one item to the container. The user can move this item by dragging it and rotating it by 90 degrees by double-clicking on it.
Before double-clicking on it (before applying the rotation), it moves as expected when the user drags the item.
If the user double-clicks the item (applies 90 degrees rotation) and then tries to move it by dragging it, it unexpectedly moves so quickly out of the window and in a random direction.
Demo:
Code:
Container.java
public class Container extends ViewGroup {
public Container(Context context) {
super(context);
}
public Container(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Container(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//Layout all children used fixed position
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
for (int i = 0; i<count; i++) {
View child = getChildAt(i);
int left = child.getLeft();
int top = child.getTop();
int right = child.getRight();
int bottom = child.getBottom();
child.layout(left, top, right, bottom);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
for (int i = 0; i<count; i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, heightMeasureSpec);
}
}
}
Item.java
public class Item extends View {
// default width and height for this item
private static final int WIDTH = 200;
private static final int HEIGHT = 80;
private final Paint mPaint;
private final static int OFFSET = 1;
//Store the click position
private float mStartX = 0;
private float mStartY = 0;
//Used to detect double-click on this item
private long mStartTime = 0;
private static final int DOUBLE_TAP_THRESHOLD = 200;
public Item(Context context, int x, int y) {
super(context);
// Set the size of the item,
// No need to override onMeasure()
setLeft(x);
setTop(y);
setRight(x + WIDTH);
setBottom(y + HEIGHT);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
}
#Override
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
canvas.drawRect(OFFSET, OFFSET, width-OFFSET, height-OFFSET, mPaint);
}
// Rotate the item if the user double click on it
// And move the item if the user drag it
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
long currentTime = System.currentTimeMillis();
if(currentTime - mStartTime < DOUBLE_TAP_THRESHOLD) {
//Double click detected
// Apply rotation
setRotation(getRotation() + 90); // rotation that cause the problem
return true;
}
mStartTime = currentTime;
mStartX = event.getX();
mStartY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
// compute the new position for the item
float deltaX = event.getX() - mStartX;
float deltaY = event.getY() - mStartY;
float newX = getX() + deltaX;
float newY = getY() + deltaY;
//move the item
setX(newX);
setY(newY);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Container container = findViewById(R.id.container);
container.addView(new Item(this, 100, 200));
}
}
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.package.name.Container
android:id="#+id/container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Question: Why does the item move so quickly when rotating it? and how to fix this issue.
Your problem is different frames of reference. X and Y are relative to the view's upper left hand corner. When you rotate and move the view, you're changing the relative coordinates of the view, which is going to lead to some funnky math.
There's 2 solutions to this. The one that changes your code the least is to convert all touch coordienates to a fixed coordinate system first. For example, the parent view's coordinate system, or the screens. view.getX is relative to its parent already.
The second and probably better way to do it- don't have the individual views control that. Do it all in a touch handler of the parent. The parent knows where all its children are and is responsible for laying them out, so this not only is more aligned with how Android works, but it avoids the problem of changing coordinate systems. All you have to do to make that work is make the views ignore all touches (their default behavior) and touches on them will fall through to their parent.
Here is how I fixed this issue. You need to take into account the rotation angle by using the rotation matrix:
x' = x*cos(theta) - y*sin(theta)
y' = x*sin(theta) - y*cos(theta)
There are two ways to implement this:
By using the direct formula
double rotation = Math.toRadians(getRotation());
float newX = (float) (getX() + deltaX*Math.cos(rotation) - deltaY*Math.sin(rotation));
float newY = (float) (getY() + deltaX*Math.sin(rotation) + deltaY*Math.cos(rotation));
//move the item
setX(newX);
setY(newY);
By using the Matrix class
float[] point = new float[] {deltaX, deltaY};
mapPoint(point, getRotation());
float newX = getX() + point[0];
float newY = getY() + point[1];
//move the item
setX(newX);
setY(newY);
Here is the helper method mapPoint:
private void mapPoint(float[] point, float angle) {
Matrix matrix = new Matrix();
matrix.setRotate(angle);
matrix.mapPoints(point);
}
I am trying to make a scrollable layout, where I would have a single bigger custom view at the start and dynamic amount of smaller TextViews after it.
Like this:
|-----|---Start of devices screen
| |
| | -Custom view 1
| |
|-----|
| |---TextView & End of devices screen
|-----|
|-----|
| |
|-----|
The custom view is a view where I do some drawing in onDraw().
I have been trying to fiddle with the onMeasure() method, layout_height and layout_weight properties, but I am unable to get a satisfactory result. I always end up with a unscrollable layout or one without the custom view. Only way I have been able to get the functionality is by setting the custom view's height to some 'dp' value, but I would like it leave the same physical amount of space in the botto of the screen.
Is something like this possible with the tools Android provides, or would this need some custom view for the scrolling too? How would I go about implementing this?
Edit: To clarify, I need the first element I have in the ScrollView to initially either fill the whole visible area of the ScrollView or leave a small space under it that is constant on every device.
Use Flow Layout In place of your custom layout
find flow layout implementation link
https://docs.google.com/file/d/0B_VKZCqEnHblNDdiY2UxODgtYWNhNS00MmU4LWE4NDMtZjQ1OWI5MDMxZTVh/edit?num=50&sort=name&layout=list&pli=1#
package com.example.android.layout;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
public class FlowLayout extends ViewGroup {
private int mHorizontalSpacing;
private int mVerticalSpacing;
private Paint mPaint;
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);
try {
mHorizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 0);
mVerticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 0);
} finally {
a.recycle();
}
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(0xffff0000);
mPaint.setStrokeWidth(2.0f);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight();
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
boolean growHeight = widthMode != MeasureSpec.UNSPECIFIED;
int width = 0;
int height = getPaddingTop();
int currentWidth = getPaddingLeft();
int currentHeight = 0;
boolean breakLine = false;
boolean newLine = false;
int spacing = 0;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
spacing = mHorizontalSpacing;
if (lp.horizontalSpacing >= 0) {
spacing = lp.horizontalSpacing;
}
if (growHeight && (breakLine || currentWidth + child.getMeasuredWidth() > widthSize)) {
height += currentHeight + mVerticalSpacing;
currentHeight = 0;
width = Math.max(width, currentWidth - spacing);
currentWidth = getPaddingLeft();
newLine = true;
} else {
newLine = false;
}
lp.x = currentWidth;
lp.y = height;
currentWidth += child.getMeasuredWidth() + spacing;
currentHeight = Math.max(currentHeight, child.getMeasuredHeight());
breakLine = lp.breakLine;
}
if (!newLine) {
height += currentHeight;
width = Math.max(width, currentWidth - spacing);
}
width += getPaddingRight();
height += getPaddingBottom();
setMeasuredDimension(resolveSize(width, widthMeasureSpec),
resolveSize(height, heightMeasureSpec));
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight());
}
}
#Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
boolean more = super.drawChild(canvas, child, drawingTime);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.horizontalSpacing > 0) {
float x = child.getRight();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y - 4.0f, x, y + 4.0f, mPaint);
canvas.drawLine(x, y, x + lp.horizontalSpacing, y, mPaint);
canvas.drawLine(x + lp.horizontalSpacing, y - 4.0f, x + lp.horizontalSpacing, y + 4.0f, mPaint);
}
if (lp.breakLine) {
float x = child.getRight();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y, x, y + 6.0f, mPaint);
canvas.drawLine(x, y + 6.0f, x + 6.0f, y + 6.0f, mPaint);
}
return more;
}
#Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
#Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
#Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
#Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p.width, p.height);
}
public static class LayoutParams extends ViewGroup.LayoutParams {
int x;
int y;
public int horizontalSpacing;
public boolean breakLine;
public LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout_LayoutParams);
try {
horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_horizontalSpacing, -1);
breakLine = a.getBoolean(R.styleable.FlowLayout_LayoutParams_layout_breakLine, false);
} finally {
a.recycle();
}
}
public LayoutParams(int w, int h) {
super(w, h);
}
}
}
<resources>
<declare-styleable name="FlowLayout">
<attr name="horizontalSpacing" format="dimension" />
<attr name="verticalSpacing" format="dimension" />
</declare-styleable>
<declare-styleable name="FlowLayout_LayoutParams">
<attr name="layout_breakLine" format="boolean" />
<attr name="layout_horizontalSpacing" format="dimension" />
</declare-styleable>
</resources>
I am building an app in which i have a Arc SeekBar and i am trying to make the TextView to follow SeekBar thumb.
My Code:
seekBar = (ArcSeekBar)findViewById(R.id.seekArc);
textView = (TextView)findViewById(R.id.myText);
seekBar.setOnSeekArcChangeListener(new ArcSeekBar.OnSeekArcChangeListener() {
#Override
public void onProgressChanged(ArcSeekBar seekArc, int progress, boolean fromUser) {
int x = seekBar.getmTranslateX() - seekBar.getmThumbXPos()-100;
int y = seekBar.getmTranslateY() - seekBar.getmThumbYPos()-100;
textView.setX(x);
textView.setY(y);
textView.setText(String.valueOf(progress));
}
#Override
public void onStartTrackingTouch(ArcSeekBar seekArc) {
}
#Override
public void onStopTrackingTouch(ArcSeekBar seekArc) {
}
});
And how i meeassure the seekbar X and Y positions.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int height = getDefaultSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
final int width = getDefaultSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
final int min = Math.min(width, height);
float top = 0;
float left = 0;
int arcDiameter = 0;
mTranslateX = (int) (width * 0.5f);
mTranslateY = (int) (height * 0.5f);
arcDiameter = min - getPaddingLeft();
mArcRadius = arcDiameter / 2;
top = height / 2 - (arcDiameter / 2);
left = width / 2 - (arcDiameter / 2);
mArcRect.set(left, top, left + arcDiameter, top + arcDiameter);
int arcStart = (int) mProgressSweep + mStartAngle + mRotation + 90;
mThumbXPos = (int) (mArcRadius * Math.cos(Math.toRadians(arcStart)));
mThumbYPos = (int) (mArcRadius * Math.sin(Math.toRadians(arcStart)));
setTouchInSide(mTouchInside);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
The result is:
Any ideas? I want the text to be above the thumb always.
yout must to have central point . and the textview circle size must be bigger than other circle
What i want to do is place view along circle whose center is a parent layout.
I tried my best, I can't see anything. Below is my code.(alphabetView is just simple extends from textview. for debugging purpose i commented placing along circle,and change it to placing along simple line)
When i placed it at a constructor, i couldn't get width and height, but i could see child views. so far as i know, i can only get 0 width and height in constructor. So I moved code to onSizeChanged.
But now, after place it on onSizeChanged, i could get center of parent layout, but i can't see any child.
Am i misunderstand something? Is there any better way to achieve placing view along ring?
public class RingUIView extends RelativeLayout {
private String[] _keySet = {"A", "B", "C", "D", "E", "F", "G"};
private double UI_SIZE = 200;
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
float centerX = getX() + getWidth() / 2;
float centerY = getY() + getHeight() / 2;
Log.e("ASDF", String.format("%f, %f", centerX, centerY));
double radian = 0;
for (int i = 0; i < _keySet.length; i++) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.alphabet_view, null);
AlphabetView alphabetView = (AlphabetView) view;
alphabetView.setText(_keySet[i]);
this.addView(alphabetView);
/*float childX = (float)(centerX+UI_SIZE*Math.cos(radian) - alphabetView.getWidth());
float childY = (float)(centerY+UI_SIZE*Math.sin(radian) - alphabetView.getHeight());*/
float childX = centerX + 20 * i;
float childY = centerY + 20 * i;
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams();
params.leftMargin = (int) childX;
params.topMargin = (int) childY;
radian += Math.PI / 4;
}
}
public RingUIView(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
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