Android: Xoay hình ảnh trong chế độ xem hình ảnh theo một góc


154

Tôi đang sử dụng đoạn mã sau để xoay hình ảnh trong ImageView theo một góc. Có bất kỳ phương pháp đơn giản và ít phức tạp hơn có sẵn.

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);

6
PS cho năm 2014, có vẻ như bạn có thể chỉ cần đặt "xoay" trong XML trong Android Studio. (Bạn thậm chí có thể chỉ cần nhấp vào nút "thuộc tính chuyên gia" ở bên phải, nếu bạn không thể bị làm phiền khi sử dụng bố cục 'Văn bản'!)
Fattie

tìm câu trả lời ngay tại đây stackoverflow.com/a/52983423/5872337
Geet Thakur

Câu trả lời:


194

Một cách đơn giản khác để xoay vòng ImageView:
CẬP NHẬT:
Nhập khẩu bắt buộc:

import android.graphics.Matrix;
import android.widget.ImageView;

Mã số: (Giả sử imageView, angle, pivotX& pivotYđược đã được xác định)

Matrix matrix = new Matrix();
imageView.setScaleType(ImageView.ScaleType.MATRIX);   //required
matrix.postRotate((float) angle, pivotX, pivotY);
imageView.setImageMatrix(matrix);

Phương pháp này không yêu cầu tạo một bitmap mới mỗi lần.

LƯU Ý: Để xoay một ImageViewtrên ontouch khi chạy bạn có thể đặt onTouchListener trên ImageView& xoay nó bằng cách thêm hai dòng cuối cùng (tức là postRotate ma trận & cài đặt nó trên IMAGExem ) trong phần mã trên liên lạc của bạn nghe ACTION_MOVE phần.


109
Để hoàn thiện ở đây là dòng dựa trên các ImageViewgiá trị của:matrix.postRotate( 180f, imageView.getDrawable().getBounds().width()/2, imageView.getDrawable().getBounds().height()/2);
Stefan Hoth

2
Làm thế nào để xoay hình ảnh trên mỗi sự kiện cảm ứng?
Saurabh

14
đối với tôi, nếu được xoay trong một phần tương đốiLoutout imageView sẽ phát triển theo kích thước của hình ảnh được chứa, không phù hợp với bố cục nữa. Có ai có kinh nghiệm làm thế nào để giải quyết điều này?
Makibo

7
Lưu ý: cho điều này để làm việc, bạn phải thiết lập của bạn ImageView's srcthuộc tính. getDrawable()đã trở về null cho tôi cho đến khi tôi nhận ra rằng tôi đã thiết lập các ImageView's backgroundthuộc tính thay vì src. facepalm
Gary S.

1
Nó chỉ xoay hình ảnh trong hình ảnh xem. Tôi nên làm gì để xoay hình ảnh quá?
Ege

177

mImageView.setRotation(angle) với API> = 11


3
nó cũng sẽ thay đổi chiều rộng và chiều cao của khung nhìn thành kích thước chính xác chứ? hoặc nó chỉ thay đổi như thế nào?
nhà phát triển Android

5
Có cách nào để có một "hoạt hình xoay" trong khi xoay không?
Ivan Morgillo

13
@IvanMorgillo Bạn có thể xem ViewPropertyAnimator, được sử dụng nhưaView.animate().rotation(20).start()
Jokester 10/07/2015

5
@IvanMorgillo: Sử dụng rotationBy(). Ví dụ , view.animate().rotationBy(180f).start(). Nhưng nó trở nên có vấn đề nếu chế độ xem được nhấp liên tiếp.
Mangesh

Tôi đang sử dụng mã này trong một nút. Lần nhấp đầu tiên là ok, nhưng lần nhấp tiếp theo không xoay nữa. Tôi có nên đặt một số dòng khác để khắc phục điều này?
Eggakin Baconwalker

73

Nếu bạn đang hỗ trợ API 11 trở lên, bạn chỉ có thể sử dụng thuộc tính XML sau:

android:rotation="90"

Nó có thể không hiển thị chính xác trong bản xem trước xml của Android Studio, nhưng nó hoạt động như mong đợi.


3
Gợi ý về bản xem trước xml đã giúp tôi rất nhiều
ngu

Bản xem trước XML hiển thị đúng cho tôi sau khi xoay được áp dụng.
Dick Lucas

Điều này sẽ xoay chế độ xem nhưng không phải hình ảnh! Điều này sẽ thêm các khu vực trống bên cạnh hình ảnh. Chỉ cần thêm một backgroundđể thấy hiệu quả.
YBrush

43

Có hai cách để làm điều đó:

1 Sử dụng Matrixđể tạo một bitmap mới:

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 sử dụng RotateAnimationtrên Viewbạn muốn Xoay, và chắc chắn rằng các thiết lập Animation để fillAfter=true, duration=0fromDegrees=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"
/>

và thổi phồng hình ảnh động trong mã:

Animation rotation = AnimationUtils.loadAnimation(this, R.anim.rotation);
myView.startAnimation(rotation);

danx .. Nhưng đây không phải là cách để thực hiện RotateAnimation trên Chế độ xem một cách linh hoạt..tôi có nghĩa là thiết lập góc d một cách linh hoạt ..
rijinrv

điều này hoạt động tốt hơn câu trả lời được chấp nhận nếu hình ảnh bạn cần xoay nằm trong ListView
Daren

9

Tôi biết điều này là cực kỳ muộn, nhưng nó rất hữu ích cho tôi vì vậy nó có thể giúp đỡ người khác.

Kể từ API 11, bạn có thể đặt chế độ xoay tuyệt đối của ImageView theo chương trình bằng cách sử dụng imageView.setRotation(angleInDegrees);phương thức.

Nói một cách tuyệt đối, ý tôi là bạn có thể liên tục gọi chức năng này mà không cần phải theo dõi vòng quay hiện tại. Có nghĩa là, nếu tôi xoay bằng cách chuyển 15Fđến setRotation()phương thức, sau đó gọi setRotation()lại bằng 30F, xoay hình ảnh với 30 độ chứ không phải 45 độ.

Lưu ý: Điều này thực sự hoạt động cho bất kỳ lớp con nào của đối tượng View , không chỉ ImageView.


Hình ảnh của tôi khi xoay tự nhiên cao hơn một chút trên trang. Làm thế nào tôi có thể đặt nó xuống?
Tôi muốn biết

Là hình ảnh của bạn tập trung đúng? Nếu bạn có độ trong suốt không đồng đều trong hình ảnh của mình, xoay có thể khiến nó xuất hiện thay đổi vị trí khi xoay
thomaspsk

Không có người đàn ông, khi hình ảnh xoay nó sử dụng trục. Hãy tưởng tượng điện thoại của bạn ở vị trí thẳng đứng trên tay, bây giờ xoay nó sang ngang. Nó không chạm vào tay bạn nữa. Vì vậy, có một khoảng trống ... Nhưng tôi đã giải quyết nó bằng cách sử dụng setPOLLX ()
Tôi muốn biết

5

Đây là triển khai của tôi về RotitableImageView . Cách sử dụng rất đơn giản: chỉ cần sao chép attrs.xmlRotatableImageView.java vào dự án của bạn và thêm RotatableImageView để bố trí của bạn. Đặt góc xoay mong muốn bằng ví dụ: tham số góc .

<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>

Nếu bạn gặp một số vấn đề với việc hiển thị hình ảnh, hãy thử thay đổi mã trong phương thức RotitableImageView.onDraw () hoặc sử dụng phương thức draw () để thay thế.


1
Rất hữu ích. Cám ơn vì đã chia sẻ!
Stefan Hoth

Tôi đã nhận được một NullPulumException trong khi sử dụng RotitableImageView. được bảo vệ void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {int w = getDrawable (). getIntrinsicWidth (); ...} BTW, tôi đã sử dụng nó trong mã (và có một hình ảnh mặc định nhất định), không phải trong xml.
RRTW

imageView này có vấn đề kỳ lạ khi được sử dụng trong GridView. nó tiếp tục vô hình cho đến khi bạn cuộn.
nhà phát triển Android


3

Ngoài ra, nếu bạn muốn xoay ImageView 180 độ theo chiều dọc hoặc chiều ngang, bạn có thể sử dụng scaleYhoặc scaleXthuộc tính và đặt chúng thành -1f. Dưới đây là một ví dụ về Kotlin:

imageView.scaleY = -1f
imageView.scaleX = -1f

1f giá trị được sử dụng để trả lại ImageView về trạng thái bình thường:

imageView.scaleY = 1f
imageView.scaleX = 1f

2

Tôi có một giải pháp cho việc này. Trên thực tế, đây là một giải pháp cho một vấn đề phát sinh sau khi xoay (Hình chữ nhật không phù hợp với ImagView) nhưng nó cũng giải quyết vấn đề của bạn .. Mặc dù Giải pháp này có Hoạt hình tốt hơn hoặc xấu hơn

    int h,w;
    Boolean safe=true;

Không thể có được các tham số của imageView khi khởi tạo hoạt động Để làm như vậy, vui lòng tham khảo giải pháp này HOẶC đặt kích thước tại onClick của một nút như thế này

    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 
       }

Và mã sẽ được chạy khi chúng ta muốn xoay 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();
        }
    });

Giải pháp này là đủ cho Vấn đề ở trên. Mặc dù nó sẽ thu nhỏ imageView ngay cả khi không cần thiết (khi chiều cao nhỏ hơn Chiều rộng). Nếu nó làm phiền bạn, bạn có thể thêm một toán tử ternary khác trong scaleX / scaleY.


2

Tôi nghĩ rằng phương pháp tốt nhất :)

int angle = 0;
imageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            angle = angle + 90;
            imageView.setRotation(angle);
        }
    });

2

Xoay một hình ảnh trong Android với độ trễ:

imgSplash.animate().rotationBy(360f).setDuration(3000).setInterpolator(new LinearInterpolator()).start();

1

thử cái này trên một cái nhìn tùy chỉnh

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);
    }
}


1

Đây là một giải pháp tuyệt vời để đặt một drawable có thể xoay cho một 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;
}

sử dụng:

Bitmap b=...
float angle=...
final Drawable rotatedDrawable = getRotateDrawable(b,angle);
root.setImageDrawable(rotatedDrawable);

một cách khác:

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();
        }
    };
}

Ngoài ra, nếu bạn muốn xoay bitmap, nhưng sợ OOM, bạn có thể sử dụng giải pháp NDK tôi đã thực hiện ở đây


1

Nếu bạn chỉ muốn xoay chế độ xem trực quan, bạn có thể sử dụng:

iv.setRotation(float)

1

Đối với Kotlin,

mImageView.rotation = 90f //angle in float

Điều này sẽ xoay imageView chứ không phải xoay hình ảnh

Ngoài ra, mặc dù đó là một phương pháp trong Viewlớp. Vì vậy, bạn có thể xoay khá nhiều góc nhìn bằng cách sử dụng nó.


0

Đáng buồn thay, tôi không nghĩ là có. Các Matrixlớp chịu trách nhiệm cho tất cả các thao tác hình ảnh, cho dù đó là xoay, thu hẹp / phát triển, làm lệch vv

http://developer.android.com/reference/android/graphics/Matrix.html

Tôi xin lỗi, nhưng tôi không thể nghĩ ra một giải pháp thay thế. Có thể người khác có thể làm được, nhưng những lần tôi phải điều khiển một hình ảnh tôi đã sử dụng Ma trận.

May mắn nhất!


0

Một giải pháp khả thi khác là tạo chế độ xem Hình ảnh tùy chỉnh của riêng bạn (giả sử RotateableImageView extends ImageView) ... và ghi đè onDraw () để xoay canvas / bitmap trước khi chuyển sang canvas. Đừng quên khôi phục lại canvas.

Nhưng nếu bạn chỉ xoay một trường hợp duy nhất của chế độ xem hình ảnh, giải pháp của bạn sẽ đủ tốt.


0

không có ma trận và hoạt hình:

{
    img_view = (ImageView) findViewById(R.id.imageView);
    rotate = new RotateAnimation(0 ,300);
    rotate.setDuration(500);
    img_view.startAnimation(rotate);
}

0

chỉ cần viết điều này trong hoạt động của bạnResult

            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); 

0

Hãy thử mã này làm việc 100%;

Trên nút xoay bấm viết mã này:

        @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);
            }
        }

0

Thay vì chuyển đổi hình ảnh thành bitmap và sau đó xoay nó cố gắng xoay chế độ xem hình ảnh trực tiếp như mã bên dưới.

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);

0

Thực hiện theo câu trả lời dưới đây để xoay vòng liên tục của một hình ảnh

int i=0;

Nếu nhấp vào nút xoay

imageView.setRotation(i+90);
i=i+90;

0

nếu bạn muốn xoay một hình ảnh 180 độ thì hãy đặt hai giá trị này vào thẻ hình ảnh: -

android:scaleX="-1"
android:scaleY="-1"

Giải thích: - scaleX = 1 và scaleY = 1 lặp lại trạng thái bình thường nhưng nếu chúng ta đặt -1 trên thuộc tính scaleX / scaleY thì nó sẽ bị xoay 180 độ


0
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);

sử dụng như thế nào?

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);
   }
}

0

Bạn chỉ có thể sử dụng thuộc tính xoay vòng của ImageView

Dưới đây là thuộc tính từ ImageView với các chi tiết từ nguồn Android

<!-- rotation of the view, in degrees. -->
<attr name="rotation" format="float" />
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.