RelativeLayout lub linearlayout w rozwoju iOS iPhone?


Chcę dodać widok podrzędny u góry mojego widoku, muszę przeliczyć pierwotną wartość y dla wszystkich innych widoków i zmienić ich położenie, aby zostawić miejsce na nowy dodany widok.
Jest to bardzo nudne, ponieważ wiem, że android ma układ relatywny lub liniowy układ może pomóc to zrobić automatycznie.
Jak łatwo rozwiązać ten problem w rozwoju iOS?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Stworzyłem bibliotekę, aby rozwiązać dokładnie ten problem:

CSLinearLayoutView
https://github.com/scalessec/CSLinearLayoutView
Używasz tego w ten sposób:
// create the linear layout view
CSLinearLayoutView *linearLayoutView = [[[CSLinearLayoutView alloc] initWithFrame:self.view.bounds] autorelease];
linearLayoutView.orientation = CSLinearLayoutViewOrientationVertical;
[self.view addSubview:linearLayoutView];// create a layout item for the view you want to display and add it to the layout view
CSLinearLayoutItem *item = [CSLinearLayoutItem layoutItemForView:someView];
item.padding = CSLinearLayoutMakePadding(5.0, 10.0, 5.0, 10.0);
item.horizontalAlignment = CSLinearLayoutItemHorizontalAlignmentCenter;
item.fillMode = CSLinearLayoutItemFillModeNormal;
[linearLayoutView addItem:item];// add more items
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Próbowałem na jakiś czas relatywny (liniowy) układ i ostatecznie postanowił wykonać podklasę UiscrollView.
Zacząłem od zwykłej zamiany layoutSubviews na prostą pętlę przez podwidoki, które zrzucają oryginalne dane, jednocześnie zachowując działanie Y. Ale do widoku przewijania dodano kilka nieoczekiwanych rzeczy, w tym widok UIInlineAutoCorrect z pól tekstowych/widoków, co oznacza, że ​​te rzeczy zostały zniekształcone przez układ . Dodałem więc trochę logiki, która używa właściwości tagu UIView, aby określić, czy powinienem to rozłożyć:
-(void) layoutSubviews{
CGFloat runningY = 0.0f;
CGFloat widestWidth = 0.0f;
for (UIView *view in self.subviews) {
if (view.tag != 1999) {
continue;
} view.origin = CGPointMake(view.origin.x, runningY);
runningY += view.height; if ([view autoresizingMask] == UIViewAutoresizingFlexibleWidth) {
view.width = self.width;
} if (view.width > widestWidth) {
widestWidth = view.width;
}
}
[self setContentSize:CGSizeMake(widestWidth, runningY)];}

Jeśli nadal chcesz używać unikatowych tagów w swoich widokach, wystarczy określić zakres tagów, które zostaną uwzględnione w układzie, a nie pojedynczą wartość.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Dla podklasy
UIView
nie jest dużo pracy, aby mieć sens w metodach takich jak
- (void) addView: toRightOfView:
itd. Możesz to zrobić na bieżąco przenosząc tylko te metody, których potrzebujesz. Następnie możesz wywołać je w swoim nadpisaniu
layoutSubviews
, jak wskazuje Benjamin.
Widoki mogą być budowane przy użyciu IB lub pisane programowo; Android działa tutaj dobrze, jeśli chodzi o czytelność układów, i możesz wnieść tę korzyść do widoków generowanych programowo na iOS. Fakt, że istnieje wiele urządzeń z systemem iOS oznacza, że ​​poza czytelnością wzór ten nie ma (jeszcze?) Wielu praktycznych zalet.
NB. Plik XIB jest plikiem XML. Otwórz go w swoim ulubionym edytorze tekstu i spójrz.
** EDIT.
Oto szybki przykład, który podskoczyłem. Nie zostało to przetestowane, ale coś takiego będzie działać w Twojej podklasie
UIView
(być może nazwij to
UIRelativeView
).
- (void) addSubview:(UIView *) viewOne
toRightOfSubview:(UIView *) viewTwo
{
if (viewTwo == nil ||
[self.subviews contains:viewTwo] == NO)
{
[self addSubview:viewOne];
}
else
{
CGRect frameTwo = viewTwo.frame;
CGPoint originOne = CGPointMake(frameTwo.origin.x + frameTwo.size.width,
frameTwo.origin.y); CGRect frameOne = CGRectZero;
frameOne.origin = originOne;
frameOne.size = viewOne.frame.size; [viewOne setFrame:frameOne];
[self addSubview:viewOne];
}
}- (void) moveSubview:(UIView *) viewOne
toRightOfSubview:(UIView *) viewTwo
{
if (viewTwo == nil ||
[self.subviews contains:viewTwo] == NO)
{
[self addSubview:viewOne];
}
else if ([self.subviews contains:viewOne] == NO)
{
[self addSubview:viewOne toRightOfSubview:viewTwo];
}
else
{
CGRect frameTwo = viewTwo.frame;
CGPoint originOne = CGPointMake(frameTwo.origin.x + frameTwo.size.width,
frameTwo.origin.y); CGRect frameOne = CGRectZero;
frameOne.origin = originOne;
frameOne.size = viewOne.frame.size; [viewOne setFrame:frameOne];
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Nie masz tu szczęścia.

iOS

nie zawiera przepisów dotyczących pozycjonowania widoków w różnych układach, takich jak

Android
... Musisz przenieść wszystkie inne podgatunki, aby zrobić miejsce dla nowego gatunku.
Istnieje kilka metod zmiany rozmiaru widoku, takich jak
sizeToFit
i
autoResizingMask
, ale nie pomogą one w tym przypadku.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

iOS bardziej koncentruje się na precyzji pikseli niż Android, który wykorzystuje układy względne, ponieważ musi radzić sobie z wieloma rozmiarami ekranu. Jednak na iOS konstruktor interfejsu jest niesamowicie dobrym narzędziem zawartym w Xcode, z którego możesz korzystać.
Ponadto, jeśli po prostu dodajesz podwidoki w powtarzalny sposób, możesz zastąpić metodę
layoutSubviews
i użyć jej do obsługi ręcznej pracy za Ciebie. Wspomniałeś o potrzebie „przeliczenia oryginalnej wartości y dla wszystkich innych widoków i zmiany ich położenia, aby zostawić miejsce na nowo dodany widok” ... możesz to zakodować w swoim
layoutSubviews
, aby nie mieć za każdym razem robić to samodzielnie.
Niestety, SDK nie ma domyślnie żadnego z nich.
autoresizingMask
jest świetny, ale nie możesz go użyć do początkowego linkowania; służy to do automatycznego użycia tylko podczas obracania.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Od iOS 9 możesz używać
UIStackView
, który działa bardzo podobnie do
LinearLayout
: dodajesz widoki, a widok stosu porządkuje je w razie potrzeby na podstawie preferencji rozmiaru:
  • Wyściółka pozostawi trzy z nich w ich naturalnym rozmiarze, a czwarta zajmie najwięcej miejsca. Używa priorytetu przytulania zawartości Auto Layout, aby zdecydować, który z nich rozciągnąć.
  • Wypełnij jednakowo sprawi, że każdy podgatunek będzie tej samej wielkości, tak aby wypełniał całą przestrzeń dostępną dla widoku stosu.
  • Wypełnij proporcjonalnie wykorzystuje wewnętrzną zawartość każdego podgatunku, aby zmienić ich rozmiar o taką samą wartość. Tak więc Widok 1 został zaprojektowany tak, aby był dwukrotnie wyższy od widoków 2, 3 i 4, a stosunek ten pozostanie, gdy zmieni się ich rozmiar - wszystkie podgatunki stają się proporcjonalnie większe lub mniejsze.
  • Równe odstępy nie zmieniają rozmiaru widoków podrzędnych, ale zamiast tego zmieniają rozmiar odstępów między widokami podrzędnymi, aby wypełnić przestrzeń.
  • Równe centrowanie jest najtrudniejsze, ale dla wielu ludzi i najbardziej estetyczne. Stara się zapewnić równą odległość między centrami każdego podgatunku.

Możesz również ustawić odstępy między widokami w widoku stosu, dodając dopełnienie.

WARNING
: podczas dodawania widoków podrzędnych widoku stosu do kodu, należy zawsze używać metody
addArrangedSubview ()
w ten sposób:
stackView.addArrangedSubview(someView)

Jeśli spróbujesz użyć zwykłego starego
addSubview ()
, nie będzie działać poprawnie, ponieważ widok stosu nie będzie wiedział, jak go ustawić.
Jeśli chodzi o usuwanie, musisz uważać, aby użyć
stackView.removeArrangedSubview (someView)

i
someView.removeFromSuperview ()
, w przeciwnym razie widok nie zostanie poprawnie usunięty.
Możesz potrzebować mojego

podręcznik
https://www.hackingwithswift.com/read/31/overview
UIStackView.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się