Rotate imageview in android - android

I am trying to create a simple zoom in/out view.
So I extend the LinearLayout and add two ImaegView as the in and out button, this is the codes:
public class ZoomView extends LinearLayout{
private ImageView mZoomIn;
private ImageView mZoomOut;
public ZoomView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setupView();
}
private void setupView() {
mZoomIn = new ImageView(getContext());
mZoomOut = new ImageView(getContext());
mZoomIn.setBackgroundDrawable(getResources().getDrawable(R.drawable.map_zoomin_btn));
mZoomIn.setOnClickListener(this);
mZoomOut.setBackgroundDrawable(getResources().getDrawable(R.drawable.map_zoomout_btn));
mZoomOut.setOnClickListener(this);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
setOrientation(LinearLayout.HORIZONTAL);
} else {
setOrientation(LinearLayout.VERTICAL);
}
addView(mZoomIn);
addView(mZoomOut);
}
}
As the codes shown, I want to ZoomView change its orientation according to the screen.
However I just have two images:
Now this is what I get at the portrait view(this is what I want):
However this is for landscape view:
While I want this for landscape view:
Then I wonder if I can implement my requirement without new bit maps? Perhaps rotate the imageview or something else? I have tried:
mZoomIn.setRotate(-90);
or
Matrix matrix = new Matrix();
matrix.postRotate(-90);
mZoomIn.setScaleType(ImageView.ScaleType.MATRIX); //required
mZoomIn.setImageMatrix(matrix);
But this does not work. Any suggestion?

Try this:
mZoomIn's values:
Matrix matrix=new Matrix();
mZoomIn.setScaleType(ScaleType.MATRIX);
matrix.postRotate( -90f, mZoomIn.getDrawable().getBounds().width()/2,
mZoomIn.getDrawable().getBounds().height()/2);
imageView.setImageMatrix(matrix);
and same for mZoomOut:
matrix.postRotate( 90f, mZoomOut.getDrawable().getBounds().width()/2,
mZoomOut.getDrawable().getBounds().height()/2);
Dont forget to use the f in the 90f or just do a type casting
The proper implementation of matrix.postRotate is as below:
matrix.postRotate((float) angle, pivX, pivY);
hope this works out for you.

Related

How to tilt a child layout at some angle

I've tried the custom view and tilt the image to 45 degree successfully but I want to tilt the whole child layoout at some angle so that whatever I'll add in that child layout will automactically tiled .. For reference please take a look at the attached picture
even I have tried this code but it wont help
public class CustomLinear extends LinearLayout{
private Matrix mForward = new Matrix();
private Matrix mReverse = new Matrix();
private float[] mTemp = new float[2];
public CustomLinear(Context context) {
super(context);
}
public CustomLinear(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.rotate(75, getWidth() / 2, getHeight() / 2);
mForward = canvas.getMatrix();
mForward.invert(mReverse);
canvas.save();
canvas.setMatrix(mForward); // This is the matrix we need to use for
// proper positioning of touch events
super.dispatchDraw(canvas);
canvas.restore();
invalidate();
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
event.setLocation(getWidth() - event.getX(), getHeight() - event.getY());
return super.dispatchTouchEvent(event);
}
}
I thing it is possible using rotate animation. you can apply animation on the whole child layout with 0 duration in On_create.
Here is the animation code
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="-90"
android:pivotX="50%"
android:pivotY="50%"
android:duration="0"
android:fillAfter="true">
</rotate>
You can set the rotation angle as per your need.
Then use given code in your Activity's onCreate,
#Override
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.myscreen);
Animation rotate_anim = AnimationUtils.loadAnimation(this, R.anim.rotation);
LayoutAnimationController anim_controller = new LayoutAnimationController(rotate_anim, 0);
FrameLayout layout = (FrameLayout)findViewById(R.id.MyScreen_ContentLayout);
layout.setLayoutAnimation(anim_controller);
}
Make custom (tilted/rotated) xml views and call it all in the main view.
Also, take a look at the following link this may help you.
http://mindfreakconcepts.blogspot.com/2013/03/how-to-rotate-listview-items-in-android.html
I could be wrong but from my understanding you have to use animation to get the effect that you want instead of draw. There is a similar thread, here that might be worth checking out.

I need to understand why setImageMatrix does not work

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

Setting background image in a custom view

I have created a class which extends View class.
public class SplashScreen extends View
and i use it by setting contentview
View splash = new SplashScreen(this);
setContentView(splash);
I need to set background image but I can't use layout. I think I need to do canvas drawing but I don't know how to do.
protected void onDraw(Canvas canvas) {
ballBounds.set(ballX-ballRadius, ballY-ballRadius, ballX+ballRadius, ballY+ballRadius);
paint.setColor(Color.LTGRAY);
// canvas.drawImage(R.drawable.background_image); (Ps: I know there is no function such as drawImage)"
canvas.drawOval(ballBounds, paint);}
If you want to just set the background you can do
public SplashScreen(Context context, AttributeSet attrs) {
super(context, attrs);
setBackgroundResource(R.drawable.background);
}
you can add image on canvas as:
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.pic180);
Matrix matrix=new Matrix();
matrix.postScale(0.8f, 0.8f);
matrix.postRotate(45);
Bitmap dstbmp=Bitmap.createBitmap(bmp,0,0,bmp.getWidth(),
bmp.getHeight(),matrix,true);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(dstbmp, 10, 10, null);
Don't you just want to change SplachScreen type to activity? Then setContentView change to whatever your layout is and if you want that splach screen appear before your application, make it first in Manifest and in splashscreen end, destroy activity and start your application menu activity. Then you won't need View class and less work finding where is problem

Trying to add Imageview to canvas via FrameLayout.addView();

I can add this logo to the canavas if I do this:
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(200,200);
ImageView boo = new ImageView(ExampletouchActivity.this);
boo.setImageResource(R.drawable.ic_launcher);
boo.setLayoutParams(lp);
fr.addView(boo); //this works fine
But if I try to add the same logo to the canvas like this it does not show anything up:
fr.addView(new Toucher(ExampletouchActivity.this));
My Toucher class is like so...
public class Toucher extends View{
ImageView boo;
public Toucher(Context context)
{
super(context);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(200,200);
boo = new ImageView(context);
boo.setImageResource(R.drawable.ic_launcher);
boo.setLayoutParams(lp);
}
#Override
public void onDraw(Canvas c)
{
boo.draw(c);
}
I have been trying for ages and cannot work out why this imageview will not draw itself to the canvas?
Many Thanks
Layout and Canvas aren't the same thing. Layout is "draw this for me", and Canvas is "I'm drawing this". In your working example, you're taking a static image and putting it into a Layout.
When you are using the canvas, in a view things are different, so try using:
canvas.drawBitmap(bg, src, dst, paint);

Android: Rotate image in imageview by an angle

I am using the following code to rotate a image in ImageView by an angle. Is there any simpler and less complex method available.
ImageView iv = (ImageView)findViewById(imageviewid);
TextView tv = (TextView)findViewById(txtViewsid);
Matrix mat = new Matrix();
Bitmap bMap = BitmapFactory.decodeResource(getResources(),imageid);
mat.postRotate(Integer.parseInt(degree));===>angle to be rotated
Bitmap bMapRotate = Bitmap.createBitmap(bMap, 0, 0,bMap.getWidth(),bMap.getHeight(), mat, true);
iv.setImageBitmap(bMapRotate);
mImageView.setRotation(angle) with API>=11
Another simple way to rotate an ImageView:
UPDATE:
Required imports:
import android.graphics.Matrix;
import android.widget.ImageView;
Code: (Assuming imageView, angle, pivotX & pivotY are already defined)
Matrix matrix = new Matrix();
imageView.setScaleType(ImageView.ScaleType.MATRIX); //required
matrix.postRotate((float) angle, pivotX, pivotY);
imageView.setImageMatrix(matrix);
This method does not require creating a new bitmap each time.
NOTE: To rotate an ImageView on ontouch at runtime you can
set onTouchListener on ImageView & rotate it by adding last two
lines(i.e. postRotate matrix & set it on imageView) in above code
section in your touch listener ACTION_MOVE part.
If you're supporting API 11 or higher, you can just use the following XML attribute:
android:rotation="90"
It might not display correctly in Android Studio xml preview, but it works as expected.
There are two ways to do that:
1 Using Matrix to create a new bitmap:
imageView = (ImageView) findViewById(R.id.imageView);
Bitmap myImg = BitmapFactory.decodeResource(getResources(), R.drawable.image);
Matrix matrix = new Matrix();
matrix.postRotate(30);
Bitmap rotated = Bitmap.createBitmap(myImg, 0, 0, myImg.getWidth(), myImg.getHeight(),
matrix, true);
imageView.setImageBitmap(rotated);
2 use RotateAnimation on the View you want to Rotate, and make sure the Animation set to fillAfter=true, duration=0, and fromDegrees=toDgrees
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="50%"
android:pivotY="50%"
android:duration="0"
android:startOffset="0"
/>
and Inflate the Animation in code:
Animation rotation = AnimationUtils.loadAnimation(this, R.anim.rotation);
myView.startAnimation(rotation);
I know this is insanely late, but it was helpful for me so it may help others.
As of API 11, you can set the absolute rotation of an ImageView programmatically by using the imageView.setRotation(angleInDegrees); method.
By absolute, I mean you can repeatedly call this function without having to keep track of the current rotation. Meaning, if I rotate by passing 15F to the setRotation() method, and then call setRotation() again with 30F, the image's rotation with be 30 degrees, not 45 degrees.
Note: This actually works for any subclass of the View object, not just ImageView.
For Kotlin,
mImageView.rotation = 90f //angle in float
This will rotate the imageView rather than rotating the image
Also, though its a method in View class. So you can pretty much rotate any view using it.
Can also be done this way:-
imageView.animate().rotation(180).start();
got from here.
Rotate an image in android with delay:
imgSplash.animate().rotationBy(360f).setDuration(3000).setInterpolator(new LinearInterpolator()).start();
This is my implementation of RotatableImageView. Usage is very easy: just copy attrs.xml and RotatableImageView.java into your project and add RotatableImageView to your layout. Set desired rotation angle using example:angle parameter.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:example="http://schemas.android.com/apk/res/com.example"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.views.RotatableImageView
android:id="#+id/layout_example_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="#drawable/ic_layout_arrow"
example:angle="180" />
</FrameLayout>
If you have some problems with displaying image, try change code in RotatableImageView.onDraw() method or use draw() method instead.
Also, if you want to rotate an ImageView by 180 degrees vertically or horizontally, you can use scaleY or scaleX properties and set them to -1f. Here is a Kotlin example:
imageView.scaleY = -1f
imageView.scaleX = -1f
1f value is used to return an ImageView to its normal state:
imageView.scaleY = 1f
imageView.scaleX = 1f
I have a solution to this.
Actually it is a solution to a problem that arises after rotation(Rectangular image doesn't fit ImagView)
but it covers your problem too..
Although this Solution has Animation for better or for worse
int h,w;
Boolean safe=true;
Getting the parameters of imageView is not possible at initialisation of activity
To do so please refer to this solution
OR set the dimensions at onClick of a Button Like this
rotateButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(imageView.getRotation()/90%2==0){
h=imageView.getHeight();
w=imageView.getWidth();
}
.
.//Insert the code Snippet below here
}
And the code to be run when we want to rotate ImageView
if(safe)
imageView.animate().rotationBy(90).scaleX(imageView.getRotation()/90%2==0?(w*1.0f/h):1).scaleY(imageView.getRotation()/90%2==0?(w*1.0f/h):1).setDuration(2000).setInterpolator(new LinearInterpolator()).setListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
safe=false;
}
#Override
public void onAnimationEnd(Animator animation) {
safe=true;
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
}).start();
}
});
This solution is sufficient for the Problem above.Although it will shrink the imageView even if it is not necessary(when height is smaller than Width).If it bothers you,you can add another ternary operator inside scaleX/scaleY.
I think the best method :)
int angle = 0;
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
angle = angle + 90;
imageView.setRotation(angle);
}
});
You can simply use rotation atribute of ImageView
Below is the attribute from ImageView with details from Android source
<!-- rotation of the view, in degrees. -->
<attr name="rotation" format="float" />
Sadly, I don't think there is. The Matrix class is responsible for all image manipulations, whether it's rotating, shrinking/growing, skewing, etc.
http://developer.android.com/reference/android/graphics/Matrix.html
My apologies, but I can't think of an alternative. Maybe someone else might be able to, but the times I've had to manipulate an image I've used a Matrix.
Best of luck!
try this on a custom view
public class DrawView extends View {
public DrawView(Context context,AttributeSet attributeSet){
super(context, attributeSet);
}
#Override
public void onDraw(Canvas canvas) {
/*Canvas c=new Canvas(BitmapFactory.decodeResource(getResources(), R.drawable.new_minute1) );
c.rotate(45);*/
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.new_minute1), 0, 0, null);
canvas.rotate(45);
}
}
here's a nice solution for putting a rotated drawable for an imageView:
Drawable getRotateDrawable(final Bitmap b, final float angle) {
final BitmapDrawable drawable = new BitmapDrawable(getResources(), b) {
#Override
public void draw(final Canvas canvas) {
canvas.save();
canvas.rotate(angle, b.getWidth() / 2, b.getHeight() / 2);
super.draw(canvas);
canvas.restore();
}
};
return drawable;
}
usage:
Bitmap b=...
float angle=...
final Drawable rotatedDrawable = getRotateDrawable(b,angle);
root.setImageDrawable(rotatedDrawable);
another alternative:
private Drawable getRotateDrawable(final Drawable d, final float angle) {
final Drawable[] arD = { d };
return new LayerDrawable(arD) {
#Override
public void draw(final Canvas canvas) {
canvas.save();
canvas.rotate(angle, d.getBounds().width() / 2, d.getBounds().height() / 2);
super.draw(canvas);
canvas.restore();
}
};
}
also, if you wish to rotate the bitmap, but afraid of OOM, you can use an NDK solution i've made here
If you only want to rotate the view visually you can use:
iv.setRotation(float)
if u want to rotate an image by 180 degrees then put these two value in imageview tag:-
android:scaleX="-1"
android:scaleY="-1"
Explanation:- scaleX = 1 and scaleY = 1 repesent it's normal state but if we put -1 on scaleX/scaleY property then it will be rotated by 180 degrees
Another possible solution is to create your own custom Image view(say RotateableImageView extends ImageView )...and override the onDraw() to rotate either the canvas/bitmaps before redering on to the canvas.Don't forget to restore the canvas back.
But if you are going to rotate only a single instance of image view,your solution should be good enough.
without matrix and animated:
{
img_view = (ImageView) findViewById(R.id.imageView);
rotate = new RotateAnimation(0 ,300);
rotate.setDuration(500);
img_view.startAnimation(rotate);
}
just write this in your onactivityResult
Bitmap yourSelectedImage= BitmapFactory.decodeFile(filePath);
Matrix mat = new Matrix();
mat.postRotate((270)); //degree how much you rotate i rotate 270
Bitmap bMapRotate=Bitmap.createBitmap(yourSelectedImage, 0,0,yourSelectedImage.getWidth(),yourSelectedImage.getHeight(), mat, true);
image.setImageBitmap(bMapRotate);
Drawable d=new BitmapDrawable(yourSelectedImage);
image.setBackground(d);
Try this code 100% working;
On rotate button click write this code:
#Override
public void onClick(View view) {
if(bitmap==null){
Toast.makeText(getApplicationContext(), "Image photo is not yet set", Toast.LENGTH_LONG).show();
}
else {
Matrix matrix = new Matrix();
ivImageProduct.setScaleType(ImageView.ScaleType.MATRIX); //required
matrix.postRotate(90,ivImageProduct.getDrawable().getBounds().width()/2,ivImageProduct.getDrawable().getBounds().height()/2);
Bitmap bmp=Bitmap.createBitmap(bitmap, 0, 0,bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
bitmap=bmp;
ivImageProduct.setImageBitmap(bitmap);
}
}
Rather than convert image to bitmap and then rotate it try to rotate direct image view like below code.
ImageView myImageView = (ImageView)findViewById(R.id.my_imageview);
AnimationSet animSet = new AnimationSet(true);
animSet.setInterpolator(new DecelerateInterpolator());
animSet.setFillAfter(true);
animSet.setFillEnabled(true);
final RotateAnimation animRotate = new RotateAnimation(0.0f, -90.0f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
animRotate.setDuration(1500);
animRotate.setFillAfter(true);
animSet.addAnimation(animRotate);
myImageView.startAnimation(animSet);
Follow the below answer for continuous rotation of an imageview
int i=0;
If rotate button clicked
imageView.setRotation(i+90);
i=i+90;
Matrix matrix = new Matrix();
imageView.setScaleType(ImageView.ScaleType.MATRIX); //required
matrix.postRotate((float) 20, imageView.getDrawable().getBounds().width()/2, imageView.getDrawable().getBounds().height()/2);
imageView.setImageMatrix(matrix);
how to use?
public class MainActivity extends AppCompatActivity {
int view = R.layout.activity_main;
TextView textChanger;
ImageView imageView;
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(view);
textChanger = findViewById(R.id.textChanger);
imageView=findViewById(R.id.imageView);
textChanger.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
roateImage(imageView);
}
});
}
private void roateImage(ImageView imageView) {
Matrix matrix = new Matrix();
imageView.setScaleType(ImageView.ScaleType.MATRIX); //required
matrix.postRotate((float) 20, imageView.getDrawable().getBounds().width()/2, imageView.getDrawable().getBounds().height()/2);
imageView.setImageMatrix(matrix);
}
}
It is too late for the answer, someone may found this useful, I came across a situation where I need to animate the rotation og ImageView by some angle on first ClickListener event, and then on the 2nd ClickListener event, need to rotate back the image to the original angle. this is how this magic happened
fun rotateAnim(imageView: ImageView,angle : Float){
imageView.isEnabled = false
Log.i(TAG, "onCreate: ${imageView.rotation}")
val rotation = imageView.animate().rotationBy(angle)
rotation.interpolator = FastOutSlowInInterpolator()
rotation.startDelay = 200
rotation.setListener(object : Animator.AnimatorListener{
override fun onAnimationEnd(animation: Animator?) {
imageView.isEnabled = true
}
override fun onAnimationStart(animation: Animator?) {}
override fun onAnimationCancel(animation: Animator?) {}
override fun onAnimationRepeat(animation: Animator?) {}
})
rotation.start()
}
and implementation is like
holder.itemView.setOnClickListener {
val rotation = imageView.rotation
if(rotation == 180F){
rotateAnim(imageView,90F)
}else{
rotateAnim(imageView,-90F)
}
}
Using Kotlin:
imageView.rotation = degrees.toFloat()

Categories

Resources