سؤال

علي الرسم البياني يتم رسمها داخل UIScrollView.انها واحدة كبيرة UIView باستخدام مخصص فرعية من CATiledLayer كما طبقته.

عندما التكبير والتصغير من UIScrollView, أريد الرسم البياني إلى تغيير حيوي كما يفعل عندما يعود من الرسم البياني viewForZoomingInScrollView.ومع ذلك ، فإن الرسم البياني يعيد رسم نفسه في مستوى التكبير و أريد إعادة تحويل جدول إلى 1x1 بحيث المرة القادمة المستخدم بتكبير ، تحويل يبدأ من طريقة العرض الحالية.إذا كنت إعادة تحويل الهوية في scrollViewDidEndZooming, يعمل في جهاز محاكاة ، ولكن يلقي EXC_BAD_ACCSES على الجهاز.

هذا لا يحل المشكلة كليا على محاكاة إما لأن المرة التالية التي يقوم المستخدم بتكبير ، تحويل يعيد نفسه إلى أي مستوى التكبير كان في ، بحيث يبدو كما لو كنت أسرع إلى 2x ، على سبيل المثال ، فجأة في 4x.عندما أنتهي من التكبير ، فإنه ينتهي في نطاق الصحيح ، ولكن العمل الفعلي التكبير تبدو سيئة.

لذلك الأولى:كيف تسمح الرسم البياني لإعادة رسم نفسه في معيار حجم 1x1 بعد التكبير ، كيف يكون التكبير على نحو سلس في جميع أنحاء?

تحرير: النتائج الجديدة الخطأ يبدو أن "[CALayer retainCount]: message sent to deallocated instance"

أنا لم deallocating أي طبقات نفسي.من قبل لم أكن حتى حذف أي آراء أو أي شيء.هذا كان الخطأ التي القيت على التكبير أيضا على تدوير.إذا قمت بحذف الكائن قبل دوران وإعادة إضافته بعد ذلك, فإنه لا رمي استثناء.هذا ليس خيارا بالنسبة التكبير.

هل كانت مفيدة؟

المحلول

وأنا لا يمكن أن تساعدك مع تحطمها، بخلاف اقول لكم لفحص وتأكد من انك لا غير قصد autoreleasing طريقة عرض أو طبقة في مكان ما ضمن التعليمات البرمجية. رأيت محاكاة التعامل مع توقيت autoreleases مختلفة من الجهاز (في معظم الأحيان عندما يتعلق الأمر موضوع).

ووالتحجيم الرأي مشكلة مع UIScrollView لقد واجهت، على الرغم من. خلال الحدث التكبير قرصة، سوف UIScrollView تأخذ رأي الذي حددته في طريقة مندوب viewForZoomingInScrollView: وتطبيق تحويل إلى ذلك. هذا التحويل يوفر التحجيم السلس للعرض دون الحاجة إلى إعادة رسم عليه كل إطار. في نهاية عملية التكبير، وسوف يطلق بك مندوب طريقة scrollViewDidEndZooming:withView:atScale: وتعطيك فرصة للقيام المزيد من تقديم عالية الجودة من وجهة نظركم في عامل المقياس الجديد. عموما، انه اقترح أن تقوم بإعادة تعيين التحويل على وجهة نظركم الى أن CGAffineTransformIdentity ومن ثم يكون وجهة نظركم رسم نفسها يدويا في نطاق وحجم جديد.

ولكن، وهذا يسبب مشكلة لأن UIScrollView لا يظهر لمراقبة عرض المحتويات تحويل، لذلك على عملية التكبير القادمة يقوم بتعيين تحويل من عرض المحتويات إلى أي عامل الحجم الكلي. منذ كنت إعادة رسم وجهة نظرك يدويا في عامل مقياس الماضي، فإنه يضاعف التوسع، وهو ما ترونه.

وكحل مؤقت، وأنا استخدم فئة فرعية UIView لمشاهدة المحتوى الخاص بي مع الطرق التالية تعريف:

- (void)setTransformWithoutScaling:(CGAffineTransform)newTransform;
{
    [super setTransform:newTransform];
}

- (void)setTransform:(CGAffineTransform)newValue;
{
    [super setTransform:CGAffineTransformScale(newValue, 1.0f / previousScale, 1.0f / previousScale)];
}

وحيث previousScale هو تعويم المثال متغير من وجهة النظر. وبعد ذلك تنفيذ أسلوب مندوب التكبير كما يلي:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
{
    [contentView setTransformWithoutScaling:CGAffineTransformIdentity];
// Code to manually redraw view at new scale here
    contentView.previousScale = scale;
    scrollView.contentSize = contentView.frame.size;
}

وعند القيام بذلك، يتم ضبط التحويلات المرسلة إلى عرض المحتويات على أساس المقياس الذي كان الرأي إعادة رسم الماضي. عندما يتم التكبير، قرصة، أن يتم إعادة تعيين إلى مقياس من 1.0 تحويل من خلال تجاوز التعديل في طريقة setTransform: العادي. ويبدو أن هذا السلوك توفير التحجيم الصحيح في حين يتيح لك رسم وجهة نظر واضحة عند الانتهاء من التكبير.

وUPDATE (2010/07/23): اي فون OS 3.2 وما فوق وتغيير السلوك وجهات النظر التمرير في ما يخص التكبير. الآن، وUIScrollView واحترام الهوية تحويل تطبيق لعرض محتوى وتوفر سوى عامل مقياس نسبي في -scrollViewDidEndZooming:withView:atScale:. ولذلك، فإن رمز أعلاه لفئة فرعية UIView ضروري فقط للأجهزة التي تعمل بنظام التشغيل اي فون الإصدارات القديمة من 3.2.

نصائح أخرى

شكرا إلى جميع الإجابات السابقة و هنا الحل.
تنفيذ UIScrollViewDelegate الأساليب:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return tmv;
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
    CGPoint contentOffset = [tmvScrollView contentOffset];   
    CGSize  contentSize   = [tmvScrollView contentSize];
     CGSize  containerSize = [tmv frame].size;

    tmvScrollView.maximumZoomScale = tmvScrollView.maximumZoomScale / scale;
    tmvScrollView.minimumZoomScale = tmvScrollView.minimumZoomScale / scale;

    previousScale *= scale;

    [tmvScrollView setZoomScale:1.0f];

    [tmvScrollView setContentOffset:contentOffset];
    [tmvScrollView setContentSize:contentSize];
    [tmv setFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];  

    [tmv reloadData];
}
  • tmv هو فئة فرعية من UIView
  • tmvScrollView — منفذ UIScrollView
  • مجموعة maximumZoomScale و minimumZoomScale قبل
  • إنشاء previousScale سبيل المثال متغير وتعيين قيمته إلى 1.0 f

يعمل بالنسبة لي تماما.

BR يوجين.

وكنت أبحث فقط لإعادة تحميل على التقصير مقياس الزوم، لأنه عندما كنت تكبير عليه، scrollview هو وجود مقياس الزوم نفسه للمرة القادمة حتى يحصل يتم deallocated ذلك.

-(void) viewWillAppear:(BOOL)animated {
      [self.scrollView setZoomScale:1.0f];
}

وتغيير اللعبة.

ولدي مناقشة تفصيلية لكيفية (ولماذا) UIScrollView التكبير يعمل على github.com/andreyvit/ScrollingMadness/ .

(وصلة يتضمن أيضا وصفا لكيفية تكبير UIScrollView برمجيا، وكيفية محاكاة صور على غرار مكتبة الترحيل + التكبير + التمرير، وهو مشروع سبيل المثال والطبقة ZoomScrollView التي بتغليف بعض من سحر التكبير).

اقتباس:

وUIScrollView لم يكن لديك فكرة وجود "مستوى التكبير الحالي"، لأن كل subview أنه يحتوي قد يكون بها مستوى التكبير الحالي. لاحظ أنه ليس هناك مجال في UIScrollView للحفاظ على مستوى التكبير الحالي. ومع ذلك نحن نعرف أن شخصا ما يخزن هذا المستوى التكبير، لأنه إذا كنت قرصة التكبير وsubview، ثم إعادة تعيين في تحويل لCGAffineTransformIdentity، ثم قرصة مرة أخرى، ستلاحظ أن تمت استعادة مستوى التكبير السابق للsubview.

في الواقع، إذا نظرتم الى التفكيك، بل هو UIView الذي يخزن مستوى التكبير الخاص به (وأشار داخل الكائن UIGestureInfo من قبل الحقل _gestureInfo). كما أن لديها مجموعة من الأساليب غير الموثقة لطيفة مثل zoomScale وsetZoomScale:animated:. (العقل لكم، كما أن لديها مجموعة من الأساليب المتعلقة التناوب، وربما نحن نحصل على دوران فتة دعم في يوم من الأيام في وقت قريب.)

ولكن، إذا كان لنا أن إنشاء UIView جديد لمجرد التكبير وإضافة وجهة نظرنا زوومابلي الحقيقي كما الطفل، فإننا سوف تبدأ دائما مع مستوى التكبير 1.0. ويستند بلدي تنفيذ التكبير البرامجي في هذه الخدعة.

وهو موثوق بها إلى حد ما النهج المناسب دائرة الرقابة الداخلية 3.2 و 4.0 وما بعدها, هي على النحو التالي.يجب أن تكون مستعدة لتزويد قابلة عرض (رئيس subview من عرض التمرير) في أي طلب نطاق واسع.ثم في scrollViewDidEndZooming: سوف إزالة عدم وضوح نطاق تحويل نسخة من هذا الرأي واستبدالها عرض جديدة الانتباه إلى الجدول الجديد.

سوف تحتاج إلى:

  • وهو ايفار من أجل الحفاظ على الجدول السابق;دعنا نسميها oldScale

  • طريقة تحديد قابلة عرض لكل viewForZoomingInScrollView: و scrollViewDidEndZooming:;هنا سوف اضع علامة (999)

  • الأسلوب الذي يخلق قابلة عرض العلامات ، و إدراج ذلك في التمرير عرض (هنا سأتصل addNewScalableViewAtScale:).تذكر, يجب أن تفعل كل شيء وفقا المقياس أحجام الرأي و subviews أو الرسم ، والأحجام التمرير المنظر contentSize للمباراة.

  • الثوابت من أجل minimumZoomScale و maximumZoomScale.هذه هي بحاجة لأن عندما نستبدل تحجيم الرأي مفصلة أكبر النسخة, النظام هو الذهاب إلى الاعتقاد بأن الجدول الحالي هو 1 ، لذلك يجب علينا أن تخدع إلى السماح للمستخدم نطاق عرض أسفل الظهر.

حسنا جدا.عند إنشاء عرض التمرير يمكنك إدراج متدرجة في الحجم 1.0.قد يكون هذا في viewDidLoad, على سبيل المثال (sv هو عرض التمرير):

[self addNewScalableViewAtScale: 1.0];
sv.minimumZoomScale = MIN;
sv.maximumZoomScale = MAX;
self->oldScale = 1.0;
sv.delegate = self;

ثم في scrollViewDidEndZooming: كنت تفعل الشيء نفسه, ولكن التعويض عن تغيير في الجدول:

UIView* v = [sv viewWithTag:999];
[v removeFromSuperview];
CGFloat newscale = scale * self->oldScale;
self->oldScale = newscale;
[self addNewScalableViewAtScale:newscale];
sv.minimumZoomScale = MIN / newscale;
sv.maximumZoomScale = MAX / newscale;

لاحظ أن حل المقدمة من براد لديه مشكلة واحدة على الرغم من: اذا واصلتم التكبير في برمجيا (دعنا نقول على الحدث الصنبور مزدوج) والسماح المستخدم يدويا (قرصة المغادرة) التصغير، بعد مرور بعض الوقت الفرق بين الحجم الحقيقي وUIScrollView المقياس سوف تتبع نمو كبير جدا، وبالتالي فإن previousScale في بعض سقوط نقطة من الدقة تعويم والتي ستؤدي في نهاية المطاف في سلوك غير متوقع

سويفت 4.* و كسكودي 9.3

إعداد scrollView تكبير الحجم إلى 0 سيتم إعادة تعيين الخاص بك scrollView إلى الحالة الأولية.

self.scrollView.setZoomScale(0.0, animated: true)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top