English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

تحقيق تقليل وتكبير وتحريك الصور باستخدام ImageView في Android

النص الموجز: من خلال التحكم في widget ImageView المخصص، يتم تحقيق تكبير الصور من خلال استخدام العناصر المخصصة في layout xml.

/**
* التحقق من ImageView المخصص، يمكنه تحريك وتكبير الصور عن طريق اللمس المتعدد
* 
* @author qiuwanyong
*/
public class MyImageView extends ImageView {
/**
* دالة لوضع الصورة في حالة التشغيل
*/
public static final int STATUS_INIT = 1;
/**
* دالة لتكبير الصورة
*/
public static final int STATUS_ZOOM_OUT = 2;
/**
* دالة لتقليل الصورة
*/
public static final int STATUS_ZOOM_IN = 3;
/**
* دالة لتحريك الصورة
*/
public static final int STATUS_MOVE = 4;
/**
* ماتريكس يستخدم لتغيير تحريك وتكبير الصورة
*/
private Matrix matrix = new Matrix();
/**
* 待展示的Bitmap对象
*/
private Bitmap sourceBitmap;
/**
* يُسجل حالة العمل الحالية، القيم الممكنة هي STATUS_INIT، STATUS_ZOOM_OUT، STATUS_ZOOM_IN وSTATUS_MOVE
*/
private int currentStatus;
/**
* عرض ZoomImageView
*/
private int width;
/**
* طول ZoomImageView
*/
private int height;
/**
* يُسجل مقياس الوسط عند وضع اليد على الشاشة
*/
private float centerPointX;
/**
* يُسجل مقياس الوسط عند وضع اليد على الشاشة
*/
private float centerPointY;
/**
* يُسجل عرض الصورة الحالية، وسيُغير هذا القيمة عندما يتم تقليل أو تكبير الصورة
*/
private float currentBitmapWidth;
/**
* يُسجل طول الصورة الحالية، وسيُغير هذا القيمة عندما يتم تقليل أو تكبير الصورة
*/
private float currentBitmapHeight;
/**
* يُسجل مقياس اليد في تحركها الأخير في الاتجاه الأفقي
*/
private float lastXMove = -1;
/**
* يُسجل مقياس اليد في تحركها الأخير في الاتجاه العمودي
*/
private float lastYMove = -1;
/**
* يُسجل مسافة تحرك اليد في الاتجاه الأفقي
*/
private float movedDistanceX;
/**
* يُسجل مسافة تحرك اليد في الاتجاه العمودي
*/
private float movedDistanceY;
/**
* 记录图片在矩阵上的横向偏移值
*/
private float totalTranslateX;
/**
* 记录图片在矩阵上的纵向偏移值
*/
private float totalTranslateY;
/**
* 记录图片在矩阵上的总缩放比例
*/
private float totalRatio;
/**
* 记录手指移动的距离所造成的缩放比例
*/
private float scaledRatio;
/**
* 记录图片初始化时的缩放比例
*/
private float initRatio;
/**
* 记录上次两指之间的距离
*/
private double lastFingerDis;
/**
* ZoomImageView构造函数,将当前操作状态设为STATUS_INIT。
* 
* @param context
* @param attrs
*/
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
currentStatus = STATUS_INIT;
}
/**
* 将待展示的图片设置进来。
* 
* @param bitmap
* 待展示的Bitmap对象
*/
public void setImageBitmap(Bitmap bitmap) {
sourceBitmap = bitmap;
无效();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
// 分别获取到ZoomImageView的宽度和高度
width = getWidth();
height = getHeight();
}
}
@SuppressLint("NewApi") @Override
public boolean onTouchEvent(MotionEvent event) {
if (initRatio == totalRatio) {
getParent().requestDisallowInterceptTouchEvent(false);
} else {
getParent().requestDisallowInterceptTouchEvent(true);
}
switch (event.getActionMasked()) {
case MotionEvent.ACTION_POINTER_DOWN:
إذا كان عدد أجهزة اللمس == 2) {
// يتم حساب مسافة بين الاصابع عندما يكون هناك اصابعان ممسكان الشاشة
lastFingerDis = distanceBetweenFingers(event);
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() == 1) {
// يتم التكبير فقط عند تحريك اصبع واحد على الشاشة
float xMove = event.getX();
float yMove = event.getY();
if (lastXMove == -1 && lastYMove == -1) {
lastXMove = xMove;
lastYMove = yMove;
}
currentStatus = STATUS_MOVE;
movedDistanceX = xMove - lastXMove;
movedDistanceY = yMove - lastYMove;
// يتم إجراء فحص الحدود، لا يُسمح بسحب الصورة خارج الحدود
if (totalTranslateX + movedDistanceX > 0) {
movedDistanceX = 0;
} else if (width - (totalTranslateX + movedDistanceX) > currentBitmapWidth) {
movedDistanceX = 0;
}
if (totalTranslateY + movedDistanceY > 0) {
movedDistanceY = 0;
} else if (height - (totalTranslateY + movedDistanceY) > currentBitmapHeight) {
movedDistanceY = 0;
}
// إرسال طلب إلى method onDraw() للرسم الصورة
无效();
lastXMove = xMove;
lastYMove = yMove;
} else if (event.getPointerCount() == 2) {
// هناك اصابعان ممسكان الشاشة ويتم تحريكهما، يتم التكبير
centerPointBetweenFingers(event);
نسبة_الإجمالي = بعد_الإصبع_بين_الإصابع(event);
إذا كان بعد_الإصبع > بعد_الإصبع السابق) {
الحالة الحالية = حالة الت縮소;
} else {
الحالة الحالية = حالة التكبير;
}
// فحص نسبة التكبير، يسمح بزيادة الصورة إلى أقصى 4 مرات، يمكن تصغيرها إلى نسبة الإعداد الأصلية
إذا ((الحالة الحالية == حالة الت縮소 && نسبة_الإجمالي < 4 * نسبة_الإعداد)
أو (الحالة الحالية == حالة التكبير && نسبة_الإجمالي > نسبة_الإعداد)) {
نسبة_الإجمالي = نسبة_الإجمالي * نسبة_التكبير;
إذا كان نسبة_الإجمالي > 4 * نسبة_الإعداد) {
نسبة_الإجمالي = 4 * نسبة_الإعداد;
إذا كان نسبة_الإجمالي < نسبة_الإعداد) {
}
نسبة_الإجمالي = نسبة_الإعداد;
}
// إرسال طلب إلى method onDraw() للرسم الصورة
无效();
آخر بعد_الإصبع = بعد_الإصبع;
}
}
break;
حالة MotionEvent.ACTION_POINTER_UP:
إذا كان عدد أجهزة اللمس == 2) {
// استعادة القيم المؤقتة عند مغادرة الإصبع للشاشة
آخر حركة_السحب = -1;
آخر حركة_السحب = -1;
}
break;
حالة MotionEvent.ACTION_UP:
// استعادة القيم المؤقتة عند مغادرة الإصبع للشاشة
آخر حركة_السحب = -1;
آخر حركة_السحب = -1;
break;
default:
break;
}
العودة إلى الحقيقة;
}
/**
* يقرر بناءً على قيمة currentStatus ما هي نوع العمليات الرسومية التي ستتم على الصورة.
*/
@Override
محمية void على الرسم(الرسام كائن الرسم) {
السوبر.على الرسم (الرسام);
المحول (الحالة الحالية) {
حالة الت縮소
حالة التكبير
تقريب (الرسام);
break;
حالة الحركة
move(canvas);
break;
case STATUS_INIT:
initBitmap(canvas);
default:
if (sourceBitmap != null) {
canvas.drawBitmap(sourceBitmap, matrix, null);
}
break;
}
}
/**
* معالجة تكبير الصورة.
* 
* @param canvas
*/
private void zoom(Canvas canvas) {
matrix.reset();
// يتم تكبير الصورة بناءً على نسبة التكبير الكلية
matrix.postScale(totalRatio, totalRatio);
float scaledWidth = sourceBitmap.getWidth() * totalRatio;
float scaledHeight = sourceBitmap.getHeight() * totalRatio;
float translateX = 0f;
float translateY = 0f;
// إذا كانت عرض الصورة الحالية أقل من عرض الشاشة، يتم التكبير الأفقي من خلال عرض مركز الشاشة. وإلا يتم التكبير الأفقي من خلال عرض مركز الإصبعين
if (عرضالصورةالحالية < العرض) {
translateX = (العرض - العرضالمقاس) / 2f;
} else {
translateX = مجموعtranslateX * الطولالمقاس + نقطةالوسطالأفقية
* (1 - الطولالمقاس);
// تأكد من أن الصورة ليست منحرفة خارج الشاشة بعد التكبير في الاتجاه الأفقي
if (translateX > 0) {
translateX = 0;
} else if (العرض - translateX > العرضالمقاس) {
translateX = العرض - العرضالمقاس;
}
}
// إذا كانت طول الصورة الحالية أقل من طول الشاشة، يتم التكبير العمودي من خلال纵坐标 مركز الشاشة. وإلا يتم التكبير العمودي من خلال纵坐标 مركز الإصبعين
if (طولالصورةالحالية < الارتفاع) {
translateY = (الارتفاع - الطولالمقاس) / 2f;
} else {
translateY = مجموعtranslateY * الطولالمقاس + نقطةالوسطالعمودية
* (1 - الطولالمقاس);
// تأكد من أن الصورة ليست منحرفة خارج الشاشة بعد التكبير في الاتجاه العمودي
if (translateY > 0) {
translateY = 0;
} else if (الارتفاع - translateY > الطولالمقاس) {
translateY = height - scaledHeight;
}
}
// يتم تحريك الصورة بعد التضخيم لضمان عدم تغيير موقع نقطة الوسط
matrix.postTranslate(translateX, translateY);
totalTranslateX = translateX;
totalTranslateY = translateY;
currentBitmapWidth = scaledWidth;
currentBitmapHeight = scaledHeight;
canvas.drawBitmap(sourceBitmap, matrix, null);
}
/**
* يتم معالجة تحريك الصورة
* 
* @param canvas
*/
private void move(Canvas canvas) {
matrix.reset();
// يتم حساب القيمة الإجمالية للتحريك بناءً على المسافة المتحركة للبصمة
float translateX = totalTranslateX + movedDistanceX;
float translateY = totalTranslateY + movedDistanceY;
// يتم تضخيم الصورة بناءً على نسبة التضخيم الموجودة بالفعل
matrix.postScale(totalRatio, totalRatio);
// يتم تحريك الصورة بناءً على المسافة المتحركة
matrix.postTranslate(translateX, translateY);
totalTranslateX = translateX;
totalTranslateY = translateY;
canvas.drawBitmap(sourceBitmap, matrix, null);
}
/**
* يتم إعداد الصورة، بما في ذلك وضعها في منتصف الشاشة، وإذا كانت الصورة أكبر من أبعاد الشاشة، يتم ضغطها
* 
* @param canvas
*/
private void initBitmap(Canvas canvas) {
if (sourceBitmap != null) {
matrix.reset();
int bitmapWidth = sourceBitmap.getWidth();
int bitmapHeight = sourceBitmap.getHeight();
if (bitmapWidth > width || bitmapHeight > height) {
if (bitmapWidth - width > bitmapHeight - height) {
// عندما تكون عرض الصورة أكبر من عرض الشاشة، يتم ضغط الصورة بنسبة واحدة، لكي يمكن عرضها بشكل كامل
float ratio = width / (bitmapWidth * 1.0f);
matrix.postScale(ratio, ratio);
float translateY = (height - (bitmapHeight * ratio)) / 2f;
// يتم تحريك الصورة في اتجاه الصعود لضمان عرضها في منتصف الشاشة
matrix.postTranslate(0, translateY);
totalTranslateY = translateY;
totalRatio = initRatio = ratio;
} else {
// عندما تكون عالية الصورة أكبر من عالية الشاشة، يتم ضغط الصورة بنسبة واحدة، لكي يمكن عرضها بشكل كامل
float ratio = height / (bitmapHeight * 1.0f);
matrix.postScale(ratio, ratio);
float translateX = (width - (bitmapWidth * ratio)) / 2f;
// في اتجاه المحور الأفقي يتم إجراء تحريك، لضمان عرض الصورة في وسط الشاشة
matrix.postTranslate(translateX, 0);
totalTranslateX = translateX;
totalRatio = initRatio = ratio;
}
currentBitmapWidth = bitmapWidth * initRatio;
currentBitmapHeight = bitmapHeight * initRatio;
} else {
// عندما يكون عرض وارتفاع الصورة أقل من عرض وارتفاع الشاشة، يتم عرض الصورة في وسط الشاشة مباشرة
float translateX = (width - sourceBitmap.getWidth()) / 2f;
float translateY = (height - sourceBitmap.getHeight()) / 2f;
matrix.postTranslate(translateX, translateY);
totalTranslateX = translateX;
totalTranslateY = translateY;
totalRatio = initRatio = 1f;
currentBitmapWidth = bitmapWidth;
currentBitmapHeight = bitmapHeight;
}
canvas.drawBitmap(sourceBitmap, matrix, null);
}
}
/**
* حساب المسافة بين اصابع.
* 
* @param event
* @return  بينما بين اصابع
*/
@SuppressLint("NewApi") private double distanceBetweenFingers(MotionEvent event) {
float disX = Math.abs(event.getX(0) - event.getX(1));
float disY = Math.abs(event.getY(0) - event.getY(1));
return Math.sqrt(disX * disX + disY * disY);
}
/**
* حساب إحداثيات نقطة الوسط بين أصابعين.
* 
* @param event
*/
@SuppressLint("NewApi") private void centerPointBetweenFingers(MotionEvent event) {
float xPoint0 = event.getX(0);
float yPoint0 = event.getY(0);
float xPoint1 = event.getX(1);
float yPoint1 = event.getY(1);
centerPointX = (xPoint0 + xPoint1) / 2;
centerPointY = (yPoint0 + yPoint1) / 2;
}
}

استدعاء في التركيب

ما تم ذكره أعلاه هو رمز التنفيذ الذي قدمته لكم الإدارة لتحقيق تمدد وتدحرج الصور باستخدام وحدة التحكم ImageView المعدة مسبقًا لـ Android، آمل أن يكون هذا مفيدًا لكم، إذا كان لديكم أي استفسارات، يرجى ترك تعليق، وسأقوم بالرد على رسائلكم في الوقت المناسب. شكرًا جزيلاً أيضًا للدعم الذي يقدمونه لموقع呐喊 لتعليم البرمجة!

بيان: محتوى هذا المقال تم جمعه من الإنترنت، يحق لصاحب الحقوق أن يكون له، تم جمع المحتوى من قبل مستخدمي الإنترنت بطرق متبادلة ويتم تحميله بشكل مستقل، هذا الموقع لا يملك حقوق الملكية، لم يتم تعديل المحتوى بشكل إنساني، ولا يتحمل أي مسؤولية قانونية. إذا وجدت محتوى يشتبه في انتهاك حقوق النسخ، فالرجاء إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (الرجاء استبدال # ب @ عند إرسال البريد الإلكتروني) للإبلاغ، وقدم الدليل المطلوب، إذا تم التحقق من ذلك، سيتم حذف المحتوى المزعوم فوراً.

أعجبك