iOS 8 UITableView فاصل إدنى 0 لا يعمل




objective-c swift (20)

سويفت 2.0 تمديد

أردت فقط مشاركة ملحق قمت بإجرائه لإزالة الهوامش من فواصل خلية tableview.

extension UITableViewCell {
    func removeMargins() {

        if self.respondsToSelector("setSeparatorInset:") {
            self.separatorInset = UIEdgeInsetsZero
        }

        if self.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
            self.preservesSuperviewLayoutMargins = false
        }

        if self.respondsToSelector("setLayoutMargins:") {
            self.layoutMargins = UIEdgeInsetsZero
        }
    }
}

تستخدم في السياق:

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell

    cell.removeMargins()
    return cell

لدي تطبيق حيث تم تعيين UITableView في قائمة القيم المخصصة - Right 0 ، Left 0 . هذا يعمل بشكل جيد في iOS 7.x ، ولكن في iOS 8.0 أرى أنه يتم تعيين الأقواس الفاصلة على القيمة الافتراضية 15 على اليمين. على الرغم من أنه تم تعيينه على 0 في ملفات xib ، فإنه لا يزال يظهر بشكل غير صحيح.

كيف يمكنني إزالة هوامش فاصل UITableViewCell ؟


بعد الكثير من التحقيق ...

إليك الطريقة الوحيدة للتحكم الكامل في هذه الأشياء (التي يمكنني العثور عليها)

للتحكم بشكل كامل في كل من إدخالات الفواصل وحواف التخطيط على كل خلية. افعل ذلك في طريقة willDisplayCell على UITableviewDelegate الخاص بك.

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.layoutMargins = UIEdgeInsetsZero
    cell.contentView.layoutMargins = UIEdgeInsetsMake(0, 10, 0, 10)
    cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
}

يتحكم كائن الخلية في الفاصل ، contentView كل شيء آخر. إذا كانت مسافات المسافات الفاصلة تظهر بلون غير متوقع ، فيجب أن تحلها:

cell.backgroundColor = cell.contentView.backgroundColor

أعتقد أن هذا هو نفس السؤال الذي طرحته هنا: إزالة فاصل البيانات على iOS 8 UITableView لجهاز XCode 6 iPhone Simulator

في نظام التشغيل iOS 8 ، هناك خاصية جديدة واحدة لجميع الكائنات التي ترث من UIView . لذا ، لن يتمكن حل تعيين " SeparatorInset في iOS 7.x من إزالة المساحة البيضاء التي تشاهدها على UITableView في iOS 8.

الخاصية الجديدة تسمى " layoutMargins ".

@property(nonatomic) UIEdgeInsets layoutMargins
Description   The default spacing to use when laying out content in the view.
Availability  iOS (8.0 and later)
Declared In   UIView.h
Reference UIView Class Reference

الحل:-

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

    if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [tableView setLayoutMargins:UIEdgeInsetsZero];
    }

   if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
   }
}

إذا قمت بتعيين cell.layoutMargins = UIEdgeInsetsZero; دون التحقق مما إذا كان layoutMargins ، فإن التطبيق سوف يتلف على iOS 7.x. لذا ، فإن أفضل طريقة هي التحقق من وجود setLayoutMargins:UIEdgeInsetsZero أولاً قبل setLayoutMargins:UIEdgeInsetsZero .


إليك طريقة سهلة لإزالة الشكل الداخلي على مستوى العالم.

في UITableViewCell+Extensions.swift :

import UIKit

extension UITableViewCell {

  override public var layoutMargins: UIEdgeInsets {
    get { return UIEdgeInsetsZero }
    set { }
  }

}

في application:didFinishLaunchingWithOptions: ::

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

قد تفكر في أ) أيضًا تجاوز separatorInset في الامتداد فقط ، أو ب) تعيين المظهر layoutMargins ، بدلاً من ذلك. لن يعمل. على الرغم من أن تشير separatorInset إلى خاصية ، محاولة تجاوز فإنه خاصية (أو أسلوب) بإنشاء أخطاء برنامج التحويل البرمجي. وتعيين بروكسي المظهر UITableViewCell layoutMargins (أو ، لهذه المسألة ، أيضا تحديد بروكسيات المظهر UITableView layoutMargins و separatorInset ) ليس له أي تأثير.


استخدام التعليمات البرمجية أدناه snippet تجنب مشكلة الحشو غير المرغوب فيها لـ UITableView في IOS 8 & 7.

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

    if ([tableView respondsToSelector:@selector(setSeparatorInset:)])
    {
        [tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([tableView respondsToSelector:@selector(setLayoutMargins:)])
    {
        [tableView setLayoutMargins:UIEdgeInsetsZero];
    }

    if ([cell respondsToSelector:@selector(setLayoutMargins:)])
    {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

الارجنتين !!! بعد اللعب حول هذا إما في هذا النوع من Cell في Cell :

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

أو تعيين cell.layoutMargins = UIEdgeInsetsZero; أصلحها لي.


بالنسبة إلى نظام التشغيل iOS 9 ، يتعين عليك إضافة:

if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
    myTableView.cellLayoutMarginsFollowReadableWidth = NO;
} 

لمزيد من التفاصيل يرجى الرجوع إلى question .


بالنسبة لي فإن الخط البسيط قام بهذه المهمة

cell.layoutMargins = UIEdgeInsetsZero

بطريقة أكثر تعقيدًا من الإجابة الأكثر تصويتًا ...

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

    if ([cell respondsToSelector:@selector(setSeparatorInset:)] && [cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)] && [cell respondsToSelector:@selector(setLayoutMargins:)]) {
         [cell setSeparatorInset:UIEdgeInsetsZero];
         [cell setPreservesSuperviewLayoutMargins:NO];
         [cell setLayoutMargins:UIEdgeInsetsZero];
    }

}


بعد الاطلاع على الإجابات في الطابق 3 ، حاولت معرفة علاقة إعداد الفاصل بين TableView و TableViewCell وأجرت بعض الاختبار. وهنا استنتاجاتي:

  1. يمكننا اعتبار أن تعيين فاصل الخلية إلى الصفر يجب أن يحرك الفاصل في خطوتين: الخطوة الأولى هي تعيين فاصلة الخلية إلى صفر. الخطوة الثانية هي تعيين marginlayout الخلية إلى الصفر.

  2. تعيين separatorinset TableView و marginlayout يمكن أن يؤثر على separatorinset الخلية. ومع ذلك ، من الاختبار ، أجد أن separatorinset TableView تبدو غير مجدية ، يمكن أن يؤثر marginlayout TableView في الواقع في marginlayout الخلية.

  3. تعيين الخلية PreservesSuperviewLayoutMargins = false ، يمكن أن يقطع تأثير marginlayout TableView على الخلايا.

  4. واحد من الحلول:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = UITableViewCell()
    
        cell.preservesSuperviewLayoutMargins = false
        cell.separatorInset = UIEdgeInsetsZero
        cell.layoutMargins = UIEdgeInsetsZero
    
        return cell
    }
    

سويفت:

override func viewDidLoad() {
    super.viewDidLoad()

    if self.tableView.respondsToSelector("setSeparatorInset:") {
        self.tableView.separatorInset = UIEdgeInsetsZero
    }
    if self.tableView.respondsToSelector("setLayoutMargins:") {
        self.tableView.layoutMargins = UIEdgeInsetsZero
    }

    self.tableView.layoutIfNeeded()            // <--- this do the magic
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
     ...

    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }

    return cell
}

في Swift ، إنه أمر مزعج أكثر بعض الشيء لأن layoutMargins هي خاصية ، لذا عليك تجاوز الـ getter and setter.

override var layoutMargins: UIEdgeInsets {
  get { return UIEdgeInsetsZero }
  set(newVal) {}
}

هذا سيجعل layoutMargins فعليًا layoutMargins ، وهو في حالتي جيدًا.


لقد نجحت في القيام بذلك:

tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;

لنأخذ لحظة لفهم المشكلة قبل أن يتم الدفع بشكل أعم لمحاولة إصلاحها.

سوف يخبرك كزة سريعة حول في المصحح أن خطوط الفاصل هي subviews من UITableViewCell. يبدو أن الخلية نفسها تأخذ قدرا كبيرا من المسؤولية عن تخطيط هذه الخطوط.

يقدم iOS 8 مفهوم هوامش التخطيط . بشكل افتراضي ، تكون هوامش التخطيط في العرض هي 8 8pt كل الجوانب ، ويتم توريثها من طرق عرض السلف.

أفضل ما يمكن أن نقوله ، عند وضع خارج خط الفاصل الخاص به ، UITableViewCell اختار احترام هامش تخطيط الأيسر ، استخدامه لتقييد inset الأيسر.

وضع كل ذلك معاً ، لتحقيق الشكل المطلوب من الصفر ، نحتاج إلى:

  • قم بتعيين هامش التخطيط الأيسر على 0
  • أوقف أي هوامش موروثة تتجاوز ذلك

ضع مثل هذا ، إنها مهمة بسيطة جدًا لتحقيق ما يلي:

cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;

أشياء يجب ملاحظتها:

  • تحتاج هذه التعليمة البرمجية إلى العمل مرة واحدة فقط لكل خلية (أنت تقوم فقط بتكوين خصائص الخلية بعد كل شيء) ، ولا يوجد شيء مميز حول الوقت الذي تختار فيه تنفيذه. افعل ما يبدو أنظف لك.
  • للأسف ، لا تتوفر أي خاصية للتكوين في Interface Builder ، ولكن يمكنك تحديد سمة وقت تشغيل محددة من قبل المستخدم من أجل preservesSuperviewLayoutMargins إذا رغبت في ذلك.
  • بوضوح ، إذا كان تطبيقك يستهدف إصدارات نظام التشغيل السابقة أيضًا ، فستحتاج إلى تجنب تنفيذ الشفرة الواردة أعلاه حتى تعمل على نظام التشغيل iOS 8 والإصدارات الأحدث.
  • بدلاً من إعداد preservesSuperviewLayoutMargins ، يمكنك تكوين طرق عرض الأجداد (مثل الجدول) للحصول على الهامش الأيسر أيضًا ، ولكن هذا يبدو أكثر عرضة للخطأ بطبيعته حيث لا تتحكم في التسلسل الهرمي بأكمله.
  • من المحتمل أن يكون أنظف قليلاً لتعيين الهامش الأيسر فقط إلى 0 وترك الآخرين.
  • إذا كنت ترغب في الحصول على 0 inset على الفواصل "الإضافية" التي UITableView في أسفل جداول النمط العادي ، فأنا أعتقد أن ذلك سيتطلب تحديد الإعدادات نفسها على مستوى الجدول أيضًا (لم تجرب هذا واحد!)

هذا هو الحل الخاص بي. ينطبق هذا على الفئة الفرعية للخلية المخصصة ، فقط قم بإضافتهم إلى الفئة الفرعية.

  1. - (UIEdgeInsets)layoutMargins {    
        return UIEdgeInsetsMake(0, 10, 0, 10);
    }
    

2.

self.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10);

ومن الملائم أنه يمكنك تخصيص موقف الفاصل دون أن تطلب من المصمم رسم واحد من أجلك ..........


هذا هو الرمز الذي يعمل من أجلي ، في Swift:

override func viewDidLoad() 
{
    super.viewDidLoad()
    ...
    if tableView.respondsToSelector("setSeparatorInset:") {
        tableView.separatorInset = UIEdgeInsetsZero
    }
}

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath)
{
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset.left = CGFloat(0.0)
    }
    if tableView.respondsToSelector("setLayoutMargins:") {
        tableView.layoutMargins = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins.left = CGFloat(0.0)
    }
}

يبدو هذا أنظف بالنسبة لي (الآن) ، حيث أن كل تعديلات الخلية / tableView الحافة / الهامش تتم في tableView:willDisplayCell:forRowAtIndexPath: method ، بدون تكديس رمز غير tableView:cellForRowAtIndexPath:

بالمناسبة ، أقوم فقط بتعيين الفاصل الأيسر للخليةالنظام / التخطيطالمغناطيس ، لأنه في هذه الحالة لا أريد أن أفسد القيود التي أعددتها في زنزانتي.

تم تحديث الرمز إلى Swift 2.2:

 override func viewDidLoad() {
   super.viewDidLoad()       

    if tableView.respondsToSelector(Selector("setSeparatorInset:")) {
      tableView.separatorInset = UIEdgeInsetsZero
        }
    }

 override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
        if cell.respondsToSelector(Selector("setSeparatorInset:")) {
            cell.separatorInset.left = CGFloat(0.0)
        }
        if tableView.respondsToSelector(Selector("setLayoutMargins:")) {
            tableView.layoutMargins = UIEdgeInsetsZero
        }
        if cell.respondsToSelector(Selector("setLayoutMargins:")) {
            cell.layoutMargins.left = CGFloat(0.0)
        }
    }

يمكنك استخدام ميزة UIAppearance مرة واحدة ، عند بدء تشغيل التطبيق (قبل تحميل واجهة المستخدم) ، لتعيينها كإعدادات عامة افتراضية:

// iOS 7:
[[UITableView appearance] setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[[UITableView appearance] setSeparatorInset:UIEdgeInsetsZero];

[[UITableViewCell appearance] setSeparatorInset:UIEdgeInsetsZero];

// iOS 8:
if ([UITableView instancesRespondToSelector:@selector(setLayoutMargins:)]) {

    [[UITableView appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setPreservesSuperviewLayoutMargins:NO];

}

بهذه الطريقة ، يمكنك الاحتفاظ برمز UIViewController نظيفًا ويمكن دائمًا تجاوزه إذا كنت تريد ذلك.


سويفت 3.0 سبيل المثال:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // removing seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // prevent the cell from inheriting the tableView's margin settings
    if cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // explicitly setting cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}

إضافة هذا المقتطف ، أنيقة بسيطة في Swift تعمل لي في iOS8 :)

    // tableview single line
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero
}

لقد عمل هذا بشكل مثالي بالنسبة لي في iOS 8 و iOS 9.

ل OBJ-C

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  { 
        if ([tableView respondsToSelector:@selector(setSeparatorInset:)])
        {
            [tableView setSeparatorInset:UIEdgeInsetsZero];
        }

        if ([tableView respondsToSelector:@selector(setLayoutMargins:)])
        {
            [tableView setLayoutMargins:UIEdgeInsetsZero];
        }

        if ([cell respondsToSelector:@selector(setLayoutMargins:)])
        {
            [cell setLayoutMargins:UIEdgeInsetsZero];
        }
         return cell;
    }




ios8