在表格视图的单元格中,我具有包含视图的堆栈视图。我跟踪堆栈视图的约束。我根据堆栈视图中要显示的视图数量来计算此尾随约束的值。
在设备旋转后,有什么方法可以重新计算该尾随约束值并显示视图,而无需在viewWillTransition
中重新加载表视图吗?
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
self.tableView.reloadData()
// self.view.layoutIfNeeded() // This doesn't recalculate constraints
}
答案 0 :(得分:1)
您可以通过几种方法进行此操作-轮换(或更改尺寸)时重新计算尺寸可能不是最佳方法。
一种利用from django.contrib.admin import widgets
from django.utils.http import urlencode
class AutocompleteSelect(widgets.AutocompleteSelect):
"""
Improved version of django's autocomplete select that sends an extra query parameter with the model and field name
it is editing, allowing the search function to apply the appropriate filter.
Also wider by default, and adds a debounce to the ajax requests
"""
def __init__(self, rel, admin_site, attrs=None, choices=(), using=None, for_field=None):
super().__init__(rel, admin_site, attrs=attrs, choices=choices, using=using)
self.for_field = for_field
def build_attrs(self, base_attrs, extra_attrs=None):
attrs = super().build_attrs(base_attrs, extra_attrs=extra_attrs)
attrs.update({
'data-ajax--delay': 250,
'style': 'width: 50em;'
})
return attrs
def get_url(self):
url = super().get_url()
url += '?' + urlencode({
'app_label': self.for_field.model._meta.app_label,
'model_name': self.for_field.model._meta.model_name,
'field_name': self.for_field.name
})
return url
class UseAutocompleteSelectMixin:
"""
To avoid ForeignKey fields to Event (such as on ReportColumn) in admin from pre-loading all events
and thus being really slow, we turn them into autocomplete fields which load the events based on search text
via an ajax call that goes through this method.
Problem is this ignores the limit_choices_to of the original field as this ajax is a general 'search events'
without knowing the context of what field it is populating. Someone else has exact same problem:
https://stackoverflow.com/questions/55344987/how-to-filter-modeladmin-autocomplete-fields-results-with-the-context-of-limit-c
So fix this by adding extra query parameters on the autocomplete request,
and use these on the target ModelAdmin to lookup the correct limit_choices_to and filter with it.
"""
# Overrides django.contrib.admin.options.BaseModelAdmin#formfield_for_foreignkey
# Is identical except in case db_field.name is in autocomplete fields it constructs our improved AutocompleteSelect
# instead of django's and passes it extra for_field parameter
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name in self.get_autocomplete_fields(request):
db = kwargs.get('using')
kwargs['widget'] = AutocompleteSelect(db_field.remote_field, self.admin_site, using=db, for_field=db_field)
if 'queryset' not in kwargs:
queryset = self.get_field_queryset(db, db_field, request)
if queryset is not None:
kwargs['queryset'] = queryset
return db_field.formfield(**kwargs)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
# In principle we could add this override in a different mixin as adding the formfield override above is needed on
# the source ModelAdmin, and this is needed on the target ModelAdmin, but there's do damage adding everywhere so combine them.
def get_search_results(self, request, queryset, search_term):
if 'app_label' in request.GET and 'model_name' in request.GET and 'field_name' in request.GET:
from django.apps import apps
model_class = apps.get_model(request.GET['app_label'], request.GET['model_name'])
limit_choices_to = model_class._meta.get_field(request.GET['field_name']).get_limit_choices_to()
if limit_choices_to:
queryset = queryset.filter(**limit_choices_to)
return super().get_search_results(request, queryset, search_term)
search_fields = ['translations__name']
处理所有布局的方法是在堆栈视图中添加“空白”视图。如果您仅设置要显示的1或2个“实际”视图,则还可以显示“空白”视图以填写 3个“列”。
因此,假设您可能会显示零实际视图的行,则将原型保持原样,但是然后:
UIStackView
中,创建3个清晰的awakeFromNib()
并将其添加到堆栈视图中现在,当您设置要显示的视图时, 隐藏 视图将显示为 not 而 显示 足够的空白视图以保持3个视图可见。
示例:
UIView
隐藏[1, 2]
并显示view3
blank1
隐藏[2]
和view1
并显示view3
和blank1
因此,您的堆栈中将始终有3个子视图,并且无需进行任何计算...自动布局将使它们保持排列状态。
这是一个示例实现:
blank2
产生肖像:
和风景:
编辑:
这是另一个示例,使用具有class ThreeColCell: UITableViewCell {
@IBOutlet var mainStackView: UIStackView!
@IBOutlet var view1: UIView!
@IBOutlet var view2: UIView!
@IBOutlet var view3: UIView!
var arrayOfRealViews: [UIView] = [UIView]()
var arrayOfBlankViews: [UIView] = [UIView]()
var myData: [Int] = [Int]() {
didSet {
// hide all the views in the stack
mainStackView.arrangedSubviews.forEach {
$0.isHidden = true
}
// show the specified "real" views
myData.forEach { i in
arrayOfRealViews[i - 1].isHidden = false
}
// if fewer than 3 "real" views, show "blank" view(s)
for i in 0..<(3 - myData.count) {
arrayOfBlankViews[i].isHidden = false
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
commonInit()
}
func commonInit() -> Void {
// ordered array of views 1 to 3
arrayOfRealViews = [view1, view2, view3]
// add 3 "blank" views to the stack view
// and to array of blank views
for _ in 0..<3 {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .clear
mainStackView.addArrangedSubview(v)
arrayOfBlankViews.append(v)
}
}
}
class ThreeColTableViewController: UITableViewController {
var theData = [
[1, 2],
[1, 2, 3],
[1],
[1, 2, 3],
[2],
[2, 3],
[1, 2, 3],
[3],
[2, 3],
[1, 2, 3],
]
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return theData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ThreeColCell", for: indexPath) as! ThreeColCell
cell.myData = theData[indexPath.row]
return cell
}
}
(以及2和3)属性的结构数组:
.isDisabled1
答案 1 :(得分:0)
您应该实现该方法
func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
当设备转换到新视图(横向或纵向)时会调用哪个。在这种情况下,您可以更改约束并致电
view.setNeedsLayout()
为了标记该布局,需要在下一个Runloop中重新计算。