Välkommen till slutbetalningen i vår serie om att bygga en iPad-läsare för Världarnas krig med Leaves-projektet. I dagens inlägg kommer jag att demonstrera flera tekniker som kan användas för att justera gränssnittet när enhetens orientering ändras.
Det har varit ungefär två veckor sedan mitt senaste inlägg i den här serien, så jag ger en snabb sammanfattning av vad vi har täckt hittills:
I den första handledningen i denna serie introducerade jag dig till Leaves-projektet och visade hur det skulle integreras med Xcode 4. Sedan visade jag hur man använder en UISlider med löv för att tillåta användare att snabbt skrubba igenom en PDF-fil. Slutligen visade jag hur man lägger till en anpassad innehållsförteckning för att användarna ska trycka på mellan kapitel.
Efter var och en av ovanstående inlägg slutade jag med en omröstning och bad dig rösta om vilken funktion eller ämne jag skulle täcka nästa. Som svar på den senaste handledningen ville majoriteten av respondenterna se hur man konfigurerar läsargränssnittet för enhetsorienteringsändringar, och det är vad jag täcker idag som den sista avbetalningen i serien.
Men innan jag går vidare, låt mig berätta vad denna handledning inte kommer att göra: Jag kommer inte att lägga till någon ny kärnfunktionalitet till Leaves-projektet. Det finns några riktigt fantastiska saker som du kan få hända om du är ute efter att hacka runt i kärnprojektkoden eller förkroppsligar Leaves-projektet självt. Jag uppmuntrar de som är involverade i samhället att hämta facklan och göra just det. Tyvärr är det inte möjligt att göra betydande kärnprojektförändringar i denna serie på grund av tidsbegränsningar. Istället ska jag helt enkelt visa hur man gör det bästa med vad bladet redan ger och hur man justerar de anpassade vyerna och gränssnittskontrollerna som vi skapade.
Det här är en videodemo av vad denna handledning lär dig att bygga:
Det första steget i att göra programorienteringen är medvetet att ange vilka orienteringar WOTWViewController, Den huvudsakliga projektvynskontrollen kan stödja. Detta görs med följande metod:
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation // Stöd alla orienteringar returnera JA;
De shouldAutorotateToInterfaceOrientation:
Metoden är ärvd från UIViewController
och låter varje vy av kontrollen ange vilka gränssnitt orienteringar som stöds. För denna handledning vill vi stödja dem alla, så jag returnerar helt enkelt "JA". Vi kunde dock testa för specifika UIInterfaceOrientation
värden här genom att markera interfaceOrientation
parameter.
Om du tittar på vårt projekt i simulatorn nu kommer du märka att saker börjar växla när orienteringen ändras, men du kommer också märka att dessa standardändringar lämnar mycket att önska. Det finns två grundläggande tillvägagångssätt som vi kan ta för att lösa detta. Ett tillvägagångssätt skulle vara att kroka in i UIViewController
metoder som meddelas när en orienteringsändring har inträffat, t.ex. didRotateFromInterfaceOrientation:
, och manuellt göra de nödvändiga ändringarna där. Men en bättre inställning för vår inställning är att helt enkelt konfigurera autoresizingMask
egendom på våra gränssnittselement för att flexibelt anpassa sig till skärmen ändras automatiskt.
Om du är ny på autoresizingMask
egendom, oroa dig inte. Du har sett det korrekt i Interface Builder, där du kan konfigurera det grafiskt så här:
Det du kanske inte har insett är att du också kan ställa in egenskapen manuellt i kod (anmärkning: som en allmän regel, om du kan göra det i gränssnittsbyggaren kan du göra det i kod) och med det gör du det möjligt att kontrollera hur automatiska orienteringsändringar kommer att äga rum. De möjliga orienteringsalternativen är följande:
Eftersom det autoresizingMask
egenskapen är en heltal bitmask, du kan kombinera flera värden till en enkelt genom att använda bitwise-OR-operatören för att kombinera dem.
Till exempel, om jag ville ställa in myContentView
att ha alla UIViewAutoresizing
alternativ, jag kunde göra det här:
myContentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
Eller om jag ville ha det myContentView
att inte ha något autorescerande beteende, kunde jag konfigurera det som så:
myContentView.autoresizingMask = UIViewAutoresizingNone;
Vi använder den här tekniken för att konfigurera autosiseringsbeteendet för följande gränssnittsobjekt: contentsButton
, pageSlider
, tableOfContentsView
, bookHeading
, bookOneSubtitle
, bookTwoSubtitle
, och sectionButton
.
Var och en av ändringarna nedan kommer att göras i WOTWViewController.m, och lämpligt linjenummer för ändringen anges tillsammans med källkoden.
contentsButton
MaskcontentButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
pageSlider
Maskself.pageSlider.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
tableOfContentsView
MasktableOfContentsView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
bookHeading
MaskbookHeading.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
bookOneSubtitle
MaskbookOneSubtitle.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
bookTwoSubtitle
MaskbookTwoSubtitle.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
sectionButton
MasksectionButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
sectionButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
När du har lagt till alla ovanstående egenskaper, spara, bygg och kör projektet. Du bör se att innehållsförteckningen ser mycket bättre ut i landskapsorientering nu! Om du är uppmärksam, märker du emellertid en skarp fel: "BOOK I" -förteckningen över innehållsförteckningen är avskärning vertikalt när du är i liggande riktning.
UIScrollView
Det finns naturligtvis flera sätt att hantera det faktum att vi inte har tillräckligt med vertikalt utrymme för att visa BOOK I-kapitlet. Till exempel kan vi försöka ändra höjden på knapparna eller ompositionera noteringen för att flyta horisontellt i stället för vertikalt. Enligt min åsikt är den bästa användarupplevelsen att använda en rullningsvy för att kontrollera vilken del av noteringen som är synlig.
Detta är lätt nog att uppnå. Börja med att förklara en ny UIScrollView
för att hålla våra kapitelknappar i WOTWViewController.h fil:
UIScrollView * sectionScrollView;
Starta sedan denna variabel i WOTWViewController.m viewDidLoad
metod och ställa in autoresceringsmasken:
sectionScrollView = [[UIScrollView alloc] initWithFrame: CGRectMake (20.0f, 100.0f, 530.0f, 700.0f)]; sectionScrollView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
Var noga med att släppa det senare.
Ställ sedan in colYOffset
och colXOffset
variabler till 0,0f för deras ursprungliga värde och uppdatera sedan koden i båda för
loopar för att lägga till sectionButton
objekt som undervisningar av sectionScrollView
istället för tableOfContentsScrollView
:
[sectionScrollView addSubview: sectionButton];
[sectionScrollView addSubview: sectionButton];
Ställ sedan in contentSize
egenskapen för rullningsvy:
sectionScrollView.contentSize = CGSizeMake (523.0f, 680.0f);
De contentSize
egendom styr längden och höjden på det rullbara innehållet och måste ställas in för att detta objekt ska fungera korrekt. De angivna värdena är A) 2: a kolumnen X offset plus 250 (längden på en enda knapp) och B) den första kolumnen y offset eftersom den första kolumnen har större vertikal höjd.
Lägg nu till följande rader av kod:
sectionScrollView.hidden = YES; [tableOfContentsView addSubview: sectionScrollView];
Ovanför lägger vi till rullningsvyn i huvudinställningen, men inser varför vi gömmer det först? Minns från en tidigare handledning i denna serie att vi var tvungna att manuellt aktivera och inaktivera TOC UIButton
föremål för att förhindra att bladen visar beröring från tidigt utlösande kapitelval. Alla knappobjekt är inbäddade i rullningsvyn nu, men vi vill fortfarande förhindra att rullningsvyn tar bort några händelser när det inte visas.
Eftersom det inte längre finns något behov av att manuellt byta knappobjekt mellan aktiverade och funktionshindrade stater, sök WOTWViewController.m för "enabled = YES" och "enabled = NO" och ta bort alla rader som var ansvariga för att växla detta värde på sektionsknapparna, inklusive de som finns inom displayTableOfContents
och contentsButtonPressed:
metoder.
När du har tagit bort de ovan angivna raderna, gör följande ändringar för att utlösa gömning och visa rullningsvyn istället:
- (void) displayTableOfContents // Dölj sidreglaget self.pageSlider.hidden = YES; // Visa rullningsvy-sektionenScrollView.hidden = NEJ; // Animera övergången med en horisontell flip från höger till vänster [UIView startAnimations: nil context: nil]; [UIView setAnimationDuration: 0.5f]; [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView: self-> leavesView cache: YES]; [self-> leavesView bringSubviewToFront: tableOfContentsView]; [UIView commitAnimations]; - (tomrum) contentButtonPressed: (UIButton *) avsändare // Uppdatera PDF-visningspositionen själv-> leavesView.currentPageIndex = sender.tag; // Visa UISlider self.pageSlider.hidden = NEJ; self.pageSlider.value = (float) sender.tag; // Animera PDF-filen till toppen av bladenSe undervyer [UIView startAnimations: nil context: nil]; [UIView setAnimationDuration: 0.5f]; [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView: self-> leavesView cache: YES]; [self-> leavesVisa sendSubviewToBack: tableOfContentsView]; [UIView commitAnimations]; // Dölj rullningsvy som läggs till i TOC när den inte är i snitt sectionScrollView.hidden = YES;
Rullningsvyn ska nu döljas när bladsvyn visas och visas när TOC visas. Spara, bygg och kör ditt projekt. Alla våra anpassade gränssnittsobjekt ska nu anpassas till orienteringsändringar!
Mitt mål att skriva den här serien var både att visa hur man lägger till användbara funktioner för en standardbläddringsimplementering samt att lära dig iOS SDK-programmeringstroppar och tekniker genom exempel på vägen. Jag hoppas att du har lärt dig åtminstone några intressanta nuggets och funnit den här serien för att vara till hjälp i dina egna projekt. Gärna lämna en kommentar nedan och låta mig veta om detta hjälpte till!
Under den här serien har vi sett både fördelar och begränsningar för att använda Leaves-projektet. Personligen älskar jag hur löv kan snabbt göra det möjligt för dig att skapa den grundläggande vänster / höger sidokrankanimationen medan du stöder ett antal olika innehållsformat (inklusive PDF). Men som vi har sett under den här serien har standardprojektimplementeringen mycket arbete för att vara lämplig för de flesta professionella projekt. Vi har behövt gå runt kärnprojektkoden när vi försökte lägga till en skjutreglage och en innehållsförteckning, och det gjorde vi inte ens på några av de mer komplexa, men allmänt nödvändiga funktioner som texthöjdpunkter, bokmärken, kommentarer, etc.
Naturligtvis är blad inte det enda alternativet för att uppnå denna typ av funktionalitet. I mitt första inlägg nämnde jag FlipView, HMGLTransitions och PaperStack-projektet (ännu ej utlämnat den 10/6/2011). Det finns också ett antal Leaves-projektgafflar och sannolikt några fler projekt som jag inte har listat här.
Min fråga till samhället är detta: gör de nuvarande alternativen för öppen källkod för att bygga eReader-program till dina behov? Om inte, varför inte? Vilka funktioner vill du se läggas till befintliga projekt som inte är tillgängliga för närvarande? Soundoff nedan. Jag överväger för närvarande att antingen gå med i en av eReader-projekten där ute eller kanske till och med sparka av en ny, så jag skulle gärna höra din feedback!