I am trying to create an android application (min SDK 14, target SDK 18) that works with images (move, scale, rotate).
I have done the move part.
But I can't make scale and rotate to work using Matrix.
According to what I have read, here is the code I am using for constructing an image view and do scale and rotate with Matrix.
public MyImage(Context context) {
super(context);
init();
}
public MyImage(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyImage(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setScaleType(ScaleType.MATRIX);
}
public void rotate(float angle) {
Matrix m = new Matrix();
m.postRotate(angle);
setImageMatrix(m);
invalidate();
}
public void scale(float scaleFactor) {
Matrix m = new Matrix();
m.postScale(scaleFactor, scaleFactor);
setImageMatrix(m);
invalidate();
}
I have tried to use the set* functions of Matrix but that didn't work.
I have tried to set the scale type every time in rotate and scale functions instead of in init, but that didn't work.
I have tried to getImageMatrix instead of creating a new Matrix every time (i.e. creating an identity Matrix), but that didn't work.
I know that rotate and scale functions are getting called through debugger.
Obviously I am missing something.
I'm trying to understand what I am missing.
Should the above code work?
Have I misunderstood how Matrix works?
see my anseer for that question How to maintain multi layers of ImageViews and keep their aspect ratio based on the largest one?, that code uses layers that can ne transformed by any Matrix you want
Related
I'm trying to create a custom LinearLayout that can rotate all children in the layout by a set angle. That is, I want to rotate the entire canvas and the children, not the children individually.
I need to support API Level 10, so android:rotate which was introduced in API Level 11 will not help me here.
I've been looking around and think I need to do something along the lines of this code below, but with this code nothing gets rotated.
Any ideas on what I'm missing here?
public class RotationLayout extends LinearLayout {
public RotationLayout(Context context) {
super(context);
init();
}
public RotationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RotationLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setWillNotDraw(false);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.rotate(350,0,0);
super.onDraw(canvas);
canvas.restore();
}
}`
I tried your code with a few changes.
In the onCreate(Bundle) of an activity class, I initialized the RotationLayout:
RotationLayout rl = new RotationLayout(this);
ImageView iv = new ImageView(this);
iv.setImageDrawable(getResources().getDrawable(R.drawable.some_drawable));
rl.addView(iv);
setContentView(rl);
And the view was indeed rotated 350 degrees(or 10 degrees counter-clockwise) around (0,0). This was what I changed:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.rotate(350,0,0);
}
From notes on Canvas.save() (Link):
Saves the current matrix and clip onto a private stack. Subsequent
calls to translate,scale,rotate,skew,concat or clipRect,clipPath will
all operate as usual, but when the balancing call to restore() is
made, those calls will be forgotten, and the settings that existed
before the save() will be reinstated.
I want to draw over the specific Line, Rectangle or Bitmap using Canvas. If i draw over the Bitmap, it will take the square shape empty background also.
So i want to draw over that particular Bitmap area only.
create a bitmap with "bmp1" name from your desire image
create a custom view
create a class and extend View like this
class MyCustomView extends View{
private Rect m_ImageRect;
private Rect m_TextRect ;
//you need these constructor
//you can init paint object or anything on them
public MyCustomView (Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
m_Context = context;
}
public MyCustomView (Context context, AttributeSet attrs)
{
super(context, attrs);
m_Context = context;
}
public MyCustomView (Context context)
{
super(context);
m_Context = context;
}
//then override on draw method
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
//here frist create two rectangle
//one for your image and two for text you want draw on it
m_ImageRect = canvas.getClipBounds();
m_TextRect = canvas.getClipBounds();
//it gives you an area that can draw on it,
//the width and height of your rect depend on your screen size device
canvas.drawBitmap(your bitmap(bmp1), null, m_ImageRect , paint);
canvas.save();
canvas.clipRect(m_TextRect);
canvas.drawText("your text", the x position you want to start draw,
the y position you want to start draw, m_paintText);
canvas.restore();
}
}
at the end put the custom view on your layout,and set field on it to send value to view for draw every thing you want
i hope it's help you,if this is not what you want!
post your code so maybe i can help you more
Seems like you need clipping. See exampls: http://www.example8.com/category/view/id/15543 , Understanding Android Canvas Clipping , http://jtomlinson.blogspot.com/2008/10/clipping.html
With clipping you can specify, which regions should be 'editable'.
I'm rotating an ImageView with postRotate(float degrees, float px, float py), setting px and py to a few differnt values including (0,0) and (imgView.getHeight(),imgView.getWidth()) but it refuses to rotate around any other point than the center. I'm wondering whether it's got anything to do with the fact that my gravity is center in the LinearLayout?
My layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<ImageView
android:id="#+id/imageTraj"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:src="#drawable/impactangle" />
How I'm rotating the image:
matrix.postRotate(degrees,imageView.getHeight(),imageView.getWidth());
imageView.setImageBitmap(Bitmap.createBitmap(imageScaled, 0, 0,
imageScaled.getWidth(), imageScaled.getHeight(), matrix, true));
PS I've noticed there are a few similar questions, but none of them have suitable answers.
I am using a custom ImageView where I set the angle rotation.
public class CompassImage extends ImageView {
private float angleRotation;
public CompassImage(Context context) {
super(context);
}
public CompassImage(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CompassImage(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setAngleRotation(float angleRotation) {
this.angleRotation = angleRotation;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Rect clipBounds = canvas.getClipBounds();
canvas.save();
canvas.rotate(angleRotation, clipBounds.exactCenterX(), clipBounds.exactCenterY());
super.onDraw(canvas);
canvas.restore();
}
}
If you play around with clipBounds you may find that helpful.
A slight "hack", you could probably adjust the image size using something like Paint.net or Gimp, depending on your OS. That would make the image appear to spin on another point. This solution would be pointless if you are planning on using a lot of images though. This is a spinning cube tutorial using opengl.
I want to be able to mirror my app so it can be viewed in the windshield of a vehicle.
My XML has several nested LinearLayouts, TextViews and ImageViews. Currently I'm transforming each one and although it is mirrored, the structure of the elements is not (what was at the top is now at the bottom).
I've been looking for days and so far have tried a couple of approaches that have failed.
An animation that uses a matrix to flip on the X axis kind of works, except that it either reverts back or it stays and doesn't update, which is no good for interacting with the app.
I just tried to create a custom LinearLayout extending the parent one, hoping that I could apply a Matrix in its onDraw() method but that gives me a blank screen (I had to set setWillNotDraw(false); to hit the onDraw()).
Well eventually I found a solution that works well for me (so far it's caused no issues for users).
My solution was to override dispatchDraw to scale the canvas in my custom LinearLayout. Then I just needed to flip the touch events by overriding dispatchTouchEvent:
public class CustomContainer extends LinearLayout {
public CustomContainer(Context context) {
super(context);
this.setWillNotDraw(false);
}
public CustomContainer(Context context, AttributeSet attrs) {
super(context, attrs);
this.setWillNotDraw(false);
}
public CustomContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setWillNotDraw(false);
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
// Flip the view canvas
if (MyHUDActivity.mHUDMode) canvas.scale(1,-1, getWidth(), getHeight()/2f);
super.dispatchDraw(canvas);
canvas.restore();
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
// If in HUD mode then flip the touch zones
if (MyHUDActivity.mHUDMode) event.setLocation(event.getX(), getHeight()-event.getY());
return super.dispatchTouchEvent(event);
}
}
You can use the new Animation api to deal with reverting back after the horizontal flip.
I am new to android. Now I generated two ImageView in my Android XML file. I want to use canvas to draw two circles in each view. But the problem is, how can I deal with the coordinates? How can I know the coordinates? And how can I center them? Thanks!
ImageViews are for displaying image files, normally. If you want to draw your view yourself, you create your own View and override the onDraw method. Here is a class that draws a big red circle inside itself:
public class CircleView extends View {
public CircleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
Paint red = new Paint();
red.setColor(0xffff0000);
int height = getHeight();
int width = getWidth();
int radius = width < height ? width/2 : height/2;
canvas.drawCircle(width/2, height/2, radius, red);
}
}
You cannnot draw cirlces in an ImageView. You can only draw a circle in a bitmap and apply that bitmap to an ImageView.
Or you can create custom views and draw directly on their canvas.
In both cases you need to find the size of these views after they are created. Then you will know the coordinates as the 0,0 starts in the top left corner.